Преглед на файлове

填充代码查实际数据

wangcl преди 4 седмици
родител
ревизия
55b1cdc775
променени са 19 файла, в които са добавени 569 реда и са изтрити 239 реда
  1. 6 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/dto/uninstall/GetUninstallTrendDetailDTO.java
  2. 3 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/dto/uninstall/UninstallPredictDTO.java
  3. 16 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/ConfigItem.java
  4. 30 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/uninstall/MktDeviceAction.java
  5. 31 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/uninstall/MktDeviceCount.java
  6. 30 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/uninstall/MktDeviceInterfere.java
  7. 31 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/uninstall/MktDeviceTime.java
  8. 43 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/uninstall/MktTrendSummary.java
  9. 3 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/vo/uninstall/UninstallPortraitCharacterVO.java
  10. 45 0
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/Util/ConfigUtils.java
  11. 12 5
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/controller/UninstallAnalyseController.java
  12. 8 0
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktDeviceActionMapper.java
  13. 8 0
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktDeviceCountMapper.java
  14. 8 0
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktDeviceInterfereMapper.java
  15. 8 0
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktDeviceTimeMapper.java
  16. 10 0
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktTrendSummaryMapper.java
  17. 21 0
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/SysConfigMapper.java
  18. 23 4
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/UninstallAnalyseService.java
  19. 233 230
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/impl/UninstallAnalyseServiceImpl.java

+ 6 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/dto/uninstall/GetUninstallTrendDetailDTO.java

@@ -20,4 +20,10 @@ public class GetUninstallTrendDetailDTO {
 
 	@Schema(description = "时间单位(week/month)")
 	private String timeUnit;
+
+	@Schema(description = "页码")
+	private Integer pageNum;
+
+	@Schema(description = "每页条数")
+	private Integer pageSize;
 }

+ 3 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/dto/uninstall/UninstallPredictDTO.java

@@ -15,4 +15,7 @@ public class UninstallPredictDTO {
 
 	@Schema(description = "周期(周/月)")
 	private String cycle;
+
+	@Schema(description = "类型(卸载流失设备/召回设备(预测))")
+	private String type;
 }

+ 16 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/ConfigItem.java

@@ -0,0 +1,16 @@
+package com.pig4cloud.pig.statistics.api.entity;
+
+
+import lombok.Data;
+
+/**
+ * @author wcl
+ * @date 2025/8/19 10:53
+ * @description: 配置
+ */
+@Data
+public class ConfigItem {
+
+	private String value; // config_value
+	private String label; // config_label
+}

+ 30 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/uninstall/MktDeviceAction.java

@@ -0,0 +1,30 @@
+package com.pig4cloud.pig.statistics.api.entity.uninstall;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * @author wcl
+ * @date 2025/8/19 10:53
+ * @description: 卸载前后操作行为分布表实体
+ */
+@Data
+@TableName("uninstall_device_action")
+public class MktDeviceAction {
+    @TableId
+    private Long id;
+    private Date statDate; // 统计日期
+    private String statCycle; // 统计周期
+    private String appId; // 应用ID
+    private String channel; // 渠道
+    private String appVersion; // 应用版本
+    private String actionType; // 操作类型
+    private String actionValue; // 操作值
+    private Integer triggerCount; // 触发次数
+    private String ext1;
+    private String ext2;
+    private Date createdAt;
+    private Date updatedAt;
+}

+ 31 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/uninstall/MktDeviceCount.java

@@ -0,0 +1,31 @@
+package com.pig4cloud.pig.statistics.api.entity.uninstall;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * @author wcl
+ * @date 2025/8/19 10:53
+ * @description: 卸载相关次数分布表实体
+ */
+@Data
+@TableName("uninstall_device_count")
+public class MktDeviceCount {
+    @TableId
+    private Long id;
+    private Date statDate; // 统计日期
+    private String statCycle; // 统计周期
+    private String appId; // 应用ID
+    private String channel; // 渠道
+    private String appVersion; // 应用版本
+    private String type; // 分布类型
+    private String countRange; // 次数区间
+    private Integer num; // 设备数/次数
+    private Double rate; // 占比(%)
+    private String ext1;
+    private String ext2;
+    private Date createdAt;
+    private Date updatedAt;
+}

+ 30 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/uninstall/MktDeviceInterfere.java

@@ -0,0 +1,30 @@
+package com.pig4cloud.pig.statistics.api.entity.uninstall;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * @author wcl
+ * @date 2025/8/19 10:53
+ * @description: 卸载前干预类型分布表实体
+ */
+@Data
+@TableName("uninstall_device_interfere")
+public class MktDeviceInterfere {
+    @TableId
+    private Long id;
+    private Date statDate; // 统计日期
+    private String statCycle; // 统计周期
+    private String appId; // 应用ID
+    private String channel; // 渠道
+    private String appVersion; // 应用版本
+    private String interfereType; // 干预类型
+    private String countRange; // 次数区间
+    private Integer num; // 次数
+    private String ext1;
+    private String ext2;
+    private Date createdAt;
+    private Date updatedAt;
+}

+ 31 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/uninstall/MktDeviceTime.java

@@ -0,0 +1,31 @@
+package com.pig4cloud.pig.statistics.api.entity.uninstall;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * @author wcl
+ * @date 2025/8/19 10:53
+ * @description: 卸载相关时长分布表实体
+ */
+@Data
+@TableName("uninstall_device_time")
+public class MktDeviceTime {
+    @TableId
+    private Long id; // 主键
+    private Date statDate; // 统计日期
+    private String statCycle; // 统计周期
+    private String appId; // 应用ID
+    private String channel; // 渠道
+    private String appVersion; // 应用版本
+    private String type; // 分布类型(before, after, sys, insight等)
+    private String timeRange; // 时长区间
+    private Integer deviceCount; // 设备数
+    private Double rate; // 占比(%)
+    private String ext1;
+    private String ext2;
+    private Date createdAt;
+    private Date updatedAt;
+}

+ 43 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/uninstall/MktTrendSummary.java

@@ -0,0 +1,43 @@
+package com.pig4cloud.pig.statistics.api.entity.uninstall;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * @author wcl
+ * @date 2025/8/19 10:53
+ * @description: 卸载趋势汇总表实体
+ */
+@Data
+@TableName("uninstall_trend_summary")
+public class MktTrendSummary {
+    /** 主键 */
+    @TableId
+    private Long id;
+    /** 统计日期 */
+    private Date statDate;
+    /** 统计周期(week、month等) */
+    private String statCycle;
+    /** 应用ID */
+    private String appId;
+    /** 渠道 */
+    private String channel;
+    /** 应用版本 */
+    private String appVersion;
+    /** 趋势类型(0-卸载, 1-召回等) */
+    private Integer trendType;
+    /** 数量 */
+    private Integer count;
+    /** 比率(%) */
+    private Double rate;
+    /** 扩展字段1 */
+    private String ext1;
+    /** 扩展字段2 */
+    private String ext2;
+    /** 创建时间 */
+    private Date createdAt;
+    /** 更新时间 */
+    private Date updatedAt;
+}

+ 3 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/vo/uninstall/UninstallPortraitCharacterVO.java

@@ -21,4 +21,7 @@ public class UninstallPortraitCharacterVO {
 
 	@Schema(description = "百分比")
 	private String percent;
+
+	@Schema(description = "状态 0-易卸载特征 1-不易卸载特征")
+	private Integer status;
 }

+ 45 - 0
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/Util/ConfigUtils.java

@@ -0,0 +1,45 @@
+package com.pig4cloud.pig.statistics.Util;
+
+
+import com.pig4cloud.pig.statistics.api.entity.user.ConfigItem;
+import com.pig4cloud.pig.statistics.mapper.SysConfigMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author wcl
+ * @date 2025/8/19 10:51
+ * @description: 配置缓存工具类
+ */
+@Component
+public class ConfigUtils {
+
+	private static SysConfigMapper sysConfigMapper;
+	private static RedisTemplate<String, Object> redisTemplate;
+	private static final String CONFIG_CACHE_PREFIX = "sys_config:";
+
+	@Autowired
+	public ConfigUtils(SysConfigMapper sysConfigMapper, RedisTemplate<String, Object> redisTemplate) {
+		ConfigUtils.sysConfigMapper = sysConfigMapper;
+		ConfigUtils.redisTemplate = redisTemplate;
+	}
+
+	public static List<ConfigItem> getConfigValues(String configKey) {
+		String cacheKey = CONFIG_CACHE_PREFIX + configKey;
+		List<ConfigItem> cached = (List<ConfigItem>) redisTemplate.opsForValue().get(cacheKey);
+		if (cached != null) {
+			return cached;
+		}
+		List<ConfigItem> list = sysConfigMapper.selectByConfigKey(configKey);
+		redisTemplate.opsForValue().set(cacheKey, list, 1, TimeUnit.HOURS);
+		return list;
+	}
+
+	public static void clearConfigCache(String configKey) {
+		redisTemplate.delete(CONFIG_CACHE_PREFIX + configKey);
+	}
+}

+ 12 - 5
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/controller/UninstallAnalyseController.java

@@ -1,5 +1,6 @@
 package com.pig4cloud.pig.statistics.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.statistics.api.dto.uninstall.*;
 import com.pig4cloud.pig.statistics.api.vo.uninstall.*;
@@ -35,7 +36,7 @@ public class UninstallAnalyseController {
 
 	@PostMapping("/trend/detail")
 	@Operation(summary = "获取卸载趋势明细数据")
-	public R<List<UninstallTrendDtlVO>> getUninstallTrendDetail(@RequestBody GetUninstallTrendDetailDTO dto) {
+	public R<Page<UninstallTrendDtlVO>> getUninstallTrendDetail(@RequestBody GetUninstallTrendDetailDTO dto) {
 		return R.ok(uninstallAnalyseService.getUninstallTrendDetail(dto));
 	}
 
@@ -67,19 +68,25 @@ public class UninstallAnalyseController {
 	@PostMapping("/portrait")
 	@Operation(summary = "卸载画像")
 	public R<UninstallPortraitOV> getUninstallPortrait(@RequestBody UninstallPortraitDTO dto) {
-		return R.ok();
+		return R.ok(uninstallAnalyseService.getUninstallPortrait(dto));
 	}
 
 	@PostMapping("/predict")
 	@Operation(summary = "卸载归因-卸载预测")
 	public R<UninstallPredictVO> getUninstallPredict(@RequestBody UninstallPredictDTO dto) {
-		return R.ok();
+		return R.ok(uninstallAnalyseService.getUninstallPredict(dto));
 	}
 
 	@PostMapping("/predict/detail")
 	@Operation(summary = "卸载归因-安装卸载比")
-	public R<InstallUninstallRatioVO> getInstallUninstallRatio(@RequestBody InstallUninstallRatioDTO dto) {
-		return R.ok();
+	public R<List<InstallUninstallRatioVO>> getInstallUninstallRatio(@RequestBody InstallUninstallRatioDTO dto) {
+		return R.ok(uninstallAnalyseService.getInstallUninstallRatio(dto));
+	}
+
+	@PostMapping("/predict/detailList")
+	@Operation(summary = "卸载归因-安装卸载比明细")
+	public R<List<InstallUninstallRatioVO>> getInstallUninstallRatioDetail(@RequestBody InstallUninstallRatioDTO dto) {
+		return R.ok(uninstallAnalyseService.getInstallUninstallRatioDetail(dto));
 	}
 
 }

+ 8 - 0
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktDeviceActionMapper.java

@@ -0,0 +1,8 @@
+package com.pig4cloud.pig.statistics.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pig4cloud.pig.statistics.api.entity.uninstall.MktDeviceAction;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MktDeviceActionMapper extends BaseMapper<MktDeviceAction> {}

+ 8 - 0
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktDeviceCountMapper.java

@@ -0,0 +1,8 @@
+package com.pig4cloud.pig.statistics.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pig4cloud.pig.statistics.api.entity.uninstall.MktDeviceCount;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MktDeviceCountMapper extends BaseMapper<MktDeviceCount> {}

+ 8 - 0
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktDeviceInterfereMapper.java

@@ -0,0 +1,8 @@
+package com.pig4cloud.pig.statistics.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pig4cloud.pig.statistics.api.entity.uninstall.MktDeviceInterfere;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MktDeviceInterfereMapper extends BaseMapper<MktDeviceInterfere> {}

+ 8 - 0
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktDeviceTimeMapper.java

@@ -0,0 +1,8 @@
+package com.pig4cloud.pig.statistics.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pig4cloud.pig.statistics.api.entity.uninstall.MktDeviceTime;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MktDeviceTimeMapper extends BaseMapper<MktDeviceTime> {}

+ 10 - 0
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktTrendSummaryMapper.java

@@ -0,0 +1,10 @@
+package com.pig4cloud.pig.statistics.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pig4cloud.pig.statistics.api.entity.uninstall.MktTrendSummary;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MktTrendSummaryMapper extends BaseMapper<MktTrendSummary> {
+    // 可扩展自定义方法
+}

+ 21 - 0
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/SysConfigMapper.java

@@ -0,0 +1,21 @@
+package com.pig4cloud.pig.statistics.mapper;
+
+
+import com.pig4cloud.pig.statistics.api.entity.ConfigItem;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * @author wcl
+ * @date 2025/8/19 10:52
+ * @description: 配置Mapper
+ */
+@Mapper
+public interface SysConfigMapper {
+
+	@Select("SELECT config_value as value, config_label as label FROM sys_config WHERE config_key = #{configKey} AND enable = 1 ORDER BY sort ASC")
+	List<ConfigItem> selectByConfigKey(@Param("configKey") String configKey);
+}

+ 23 - 4
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/UninstallAnalyseService.java

@@ -1,8 +1,7 @@
 package com.pig4cloud.pig.statistics.service;
 
-import com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallInsightDTO;
-import com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallTrendDTO;
-import com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallTrendDetailDTO;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.pig4cloud.pig.statistics.api.dto.uninstall.*;
 import com.pig4cloud.pig.statistics.api.vo.uninstall.*;
 
 import java.util.List;
@@ -26,7 +25,7 @@ public interface UninstallAnalyseService {
 	 * @param dto 查询参数
 	 * @return 趋势明细列表
 	 */
-	List<UninstallTrendDtlVO> getUninstallTrendDetail(GetUninstallTrendDetailDTO dto);
+	Page<UninstallTrendDtlVO> getUninstallTrendDetail(GetUninstallTrendDetailDTO dto);
 
 	/**
 	 * 卸载设备活跃情况(时长分布+历史卸载次数分布,模拟数据)
@@ -49,4 +48,24 @@ public interface UninstallAnalyseService {
 	 * 卸载后系统设备分布
 	 */
 	List<UninstallSYSOV> uninstallSys(GetUninstallInsightDTO dto);
+
+	/**
+	 * 卸载画像
+	 */
+	UninstallPortraitOV getUninstallPortrait(UninstallPortraitDTO dto);
+
+	/**
+	 * 卸载归因-卸载预测
+	 */
+	UninstallPredictVO getUninstallPredict(UninstallPredictDTO dto);
+
+	/**
+	 * 安装卸载比
+	 */
+	List<InstallUninstallRatioVO> getInstallUninstallRatio(InstallUninstallRatioDTO dto);
+
+	/**
+	 * 安装卸载比明细
+	 */
+	List<InstallUninstallRatioVO> getInstallUninstallRatioDetail(InstallUninstallRatioDTO dto);
 }

+ 233 - 230
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/impl/UninstallAnalyseServiceImpl.java

@@ -1,12 +1,14 @@
 package com.pig4cloud.pig.statistics.service.impl;
 
-import cn.hutool.core.util.StrUtil;
-import com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallInsightDTO;
-import com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallTrendDTO;
-import com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallTrendDetailDTO;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.pig4cloud.pig.statistics.api.dto.uninstall.*;
+import com.pig4cloud.pig.statistics.api.entity.uninstall.*;
 import com.pig4cloud.pig.statistics.api.vo.uninstall.*;
+import com.pig4cloud.pig.statistics.mapper.*;
 import com.pig4cloud.pig.statistics.service.UninstallAnalyseService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDate;
@@ -24,61 +26,59 @@ public class UninstallAnalyseServiceImpl implements UninstallAnalyseService {
 
 	private static final Random random = new Random();
 
-	@Override
-	public UninstallTrendVO getUninstallTrend(GetUninstallTrendDTO dto) {
-
-		// 参数校验
-		LocalDate startDate = LocalDate.parse(dto.getStartDate());
-		if (StrUtil.isBlank(dto.getStartDate()) ) {
-			// 为空则取当前日期
-			startDate = LocalDate.now();
-		}
-		// 计算本周一到当前日期的数据
-		LocalDate firstDayOfWeek = startDate.minusDays(startDate.getDayOfWeek().getValue() - 1);
-
-		UninstallTrendVO summary = new UninstallTrendVO();
-		summary.setStartDate(firstDayOfWeek.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
-		summary.setUninstallCounts(generateRandomCount(10, 200));
-		summary.setRecallCounts(generateRandomCount(10, 200));
-		summary.setUninstallRates( calculateRates(summary.getUninstallCounts(), 1000));
-		summary.setRecallRates(calculateRates(summary.getRecallCounts(), summary.getUninstallCounts()));
-		
-		return summary;
-	}
+    @Autowired
+    private MktTrendSummaryMapper mktTrendSummaryMapper;
+    @Autowired
+    private MktDeviceTimeMapper mktDeviceTimeMapper;
+    @Autowired
+    private MktDeviceCountMapper mktDeviceCountMapper;
+    @Autowired
+    private MktDeviceInterfereMapper mktDeviceInterfereMapper;
+    @Autowired
+    private MktDeviceActionMapper mktDeviceActionMapper;
 
-	@Override
-	public List<UninstallTrendDtlVO> getUninstallTrendDetail(GetUninstallTrendDetailDTO dto) {
-		// 参数校验
-		if (StrUtil.isBlank(dto.getStartDate()) ) {
-			throw new IllegalArgumentException("开始日期不能为空");
-		}
-		if (!"week".equals(dto.getTimeUnit()) && !"month".equals(dto.getTimeUnit())) {
-			throw new IllegalArgumentException("时间单位只能是week或month");
-		}
-
-		// 生成周/月时间点列表
-		List<String> timePoints = generateTimePoints(dto.getStartDate(), dto.getEndDate(), dto.getTimeUnit());
-		
-		// 生成周/月统计数据
-		List<UninstallTrendDtlVO> result = new ArrayList<>();
-		for (String timePoint : timePoints) {
-			UninstallTrendDtlVO vo = new UninstallTrendDtlVO();
-			vo.setStartDate(timePoint);
-			
-			// 根据时间单位生成对应的统计数据
-			if ("week".equals(dto.getTimeUnit())) {
-				vo.setUninstallCounts(generateRandomCount(100, 500)); // 周卸载量
-				vo.setRecallCounts(generateRandomCount(10, 100)); // 周召回量
-			} else {
-				vo.setUninstallCounts(generateRandomCount(500, 2000)); // 月卸载量
-				vo.setRecallCounts(generateRandomCount(50, 500)); // 月召回量
-			}
+    @Override
+    public UninstallTrendVO getUninstallTrend(GetUninstallTrendDTO dto) {
+        QueryWrapper<MktTrendSummary> wrapper = new QueryWrapper<>();
+        wrapper.eq("stat_date", dto.getStartDate());
+        List<MktTrendSummary> list = mktTrendSummaryMapper.selectList(wrapper);
+        UninstallTrendVO vo = new UninstallTrendVO();
+        if (!list.isEmpty()) {
+            // 这里只取第一个,实际可按业务聚合
+            MktTrendSummary summary = list.get(0);
+            vo.setStartDate(summary.getStatDate() != null ? summary.getStatDate().toString() : null);
+            vo.setUninstallCounts(summary.getCount());
+            vo.setUninstallRates(summary.getRate());
+            // 其他字段可根据VO结构补充
+        }
+        return vo;
+    }
 
-			result.add(vo);
-		}
-		
-		return result;
-	}
+    @Override
+    public Page<UninstallTrendDtlVO> getUninstallTrendDetail(GetUninstallTrendDetailDTO dto) {
+        // 假设dto有pageNum和pageSize字段
+        int pageNum = dto.getPageNum() == null ? 1 : dto.getPageNum();
+        int pageSize = dto.getPageSize() == null ? 10 : dto.getPageSize();
+        Page<MktTrendSummary> page = new Page<>(pageNum, pageSize);
+        QueryWrapper<MktTrendSummary> wrapper = new QueryWrapper<>();
+        wrapper.eq("stat_date", dto.getStartDate());
+        Page<MktTrendSummary> entityPage = mktTrendSummaryMapper.selectPage(page, wrapper);
+        Page<UninstallTrendDtlVO> voPage = new Page<>();
+        voPage.setCurrent(entityPage.getCurrent());
+        voPage.setSize(entityPage.getSize());
+        voPage.setTotal(entityPage.getTotal());
+        voPage.setPages(entityPage.getPages());
+        List<UninstallTrendDtlVO> voList = new ArrayList<>();
+        for (MktTrendSummary summary : entityPage.getRecords()) {
+            UninstallTrendDtlVO vo = new UninstallTrendDtlVO();
+            vo.setStartDate(summary.getStatDate() != null ? summary.getStatDate().toString() : null);
+            vo.setUninstallCounts(summary.getCount());
+            // 其他字段可根据VO结构补充
+            voList.add(vo);
+        }
+        voPage.setRecords(voList);
+        return voPage;
+    }
 
 	private int generateRandomCount(int min, int max) {
 		return new Random().nextInt(max - min + 1) + min;
@@ -121,10 +121,6 @@ public class UninstallAnalyseServiceImpl implements UninstallAnalyseService {
 		return timePoints;
 	}
 
-	/**
-	 * 生成随机数量列表
-	 */
-
 	/**
 	 * 计算比率列表
 	 */
@@ -138,216 +134,223 @@ public class UninstallAnalyseServiceImpl implements UninstallAnalyseService {
 	}
 
 	public UninstallInsightVO getUninstallDeviceActiveVO(GetUninstallInsightDTO dto) {
-		// 1. 安装存量时长分布
-		String[] ranges = {"0-7天", "8-15天", "16-30天", "31-45天", "46-60天", "61-90天", "90天以上"};
-		int n = ranges.length;
-		double[] raw = new double[n];
-		double sum = 0;
-		for (int i = 0; i < n; i++) {
-			raw[i] = 10 + random.nextDouble() * 90;
-			sum += raw[i];
-		}
-		List<InstallStockVO> installStockList = new ArrayList<>();
-		int totalDevice = 1000 + random.nextInt(1000);
-		double percentSum = 0;
-		int uninstallSum = 0;
-		for (int i = 0; i < n; i++) {
+		QueryWrapper<MktDeviceTime> wrapper = new QueryWrapper<>();
+		wrapper.eq("type", "insight");
+		List<MktDeviceTime> list = mktDeviceTimeMapper.selectList(wrapper);
+		List<InstallStockVO> voList = new ArrayList<>();
+		for (MktDeviceTime entity : list) {
 			InstallStockVO vo = new InstallStockVO();
-			vo.setTime(ranges[i]);
-			if (i < n - 1) {
-				vo.setUninstallRate(Math.round(raw[i] / sum * 10000.0) / 100.0);
-				percentSum += vo.getUninstallRate();
-				vo.setUninstallCount((int)Math.round(vo.getUninstallRate() / 100 * totalDevice));
-				uninstallSum += vo.getUninstallCount();
-			} else {
-				vo.setUninstallRate(Math.round((100.0 - percentSum) * 100.0) / 100.0);
-				vo.setUninstallCount(totalDevice - uninstallSum);
-			}
-			installStockList.add(vo);
-		}
-
-		// 2. 历史卸载次数分布
-		String[] counts = {"6次以上", "5次", "4次", "3次", "2次", "1次"};
-		int m = counts.length;
-		double[] raw2 = new double[m];
-		double sum2 = 0;
-		for (int i = 0; i < m; i++) {
-			raw2[i] = 10 + random.nextDouble() * 90;
-			sum2 += raw2[i];
+			vo.setTime(entity.getTimeRange());
+			vo.setUninstallCount(entity.getDeviceCount());
+			vo.setUninstallRate(entity.getRate());
+			voList.add(vo);
 		}
-		List<com.pig4cloud.pig.statistics.api.vo.uninstall.HisUnInstallCountVO> hisList = new ArrayList<>();
-		int totalUninstall = 500 + random.nextInt(500);
-		double percentSum2 = 0;
-		int uninstallSum2 = 0;
-		for (int i = 0; i < m; i++) {
-			com.pig4cloud.pig.statistics.api.vo.uninstall.HisUnInstallCountVO vo = new com.pig4cloud.pig.statistics.api.vo.uninstall.HisUnInstallCountVO();
-			vo.setCount(counts[i]);
-			if (i < m - 1) {
-				double rate = Math.round(raw2[i] / sum2 * 10000.0) / 100.0;
-				vo.setRate(String.valueOf(rate));
-				percentSum2 += rate;
-				int num = (int)Math.round(rate / 100 * totalUninstall);
-				vo.setNum(String.valueOf(num));
-				uninstallSum2 += num;
-			} else {
-				double rate = Math.round((100.0 - percentSum2) * 100.0) / 100.0;
-				vo.setRate(String.valueOf(rate));
-				vo.setNum(String.valueOf(totalUninstall - uninstallSum2));
-			}
-			hisList.add(vo);
-		}
-
-		UninstallInsightVO vo = new UninstallInsightVO();
-		vo.setLifecycleDistribution(installStockList);
-		vo.setUninstallDistribution(hisList);
-		return vo;
+		UninstallInsightVO result = new UninstallInsightVO();
+		result.setLifecycleDistribution(voList);
+		return result;
 	}
 
 	@Override
-	public com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallBeforeVO uninstallBefore(com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallInsightDTO dto) {
+	public UninstallBeforeVO uninstallBefore(GetUninstallInsightDTO dto) {
 		// 1. 卸载时间差分布
-		String[] timeRanges = {"0-7天", "8-15天", "16-30天", "31-45天", "46-60天", "61-90天", "90天以上"};
-		List<com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallTimeDiffVO> timeDiffs = new ArrayList<>();
-		int total = 1000 + random.nextInt(1000);
-		double percentSum = 0;
-		int countSum = 0;
-		double[] raw = new double[timeRanges.length];
-		double sum = 0;
-		for (int i = 0; i < timeRanges.length; i++) {
-			raw[i] = 10 + random.nextDouble() * 90;
-			sum += raw[i];
-		}
-		for (int i = 0; i < timeRanges.length; i++) {
-			com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallTimeDiffVO vo = new com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallTimeDiffVO();
-			vo.setTime(timeRanges[i]);
-			if (i < timeRanges.length - 1) {
-				vo.setRate(Math.round(raw[i] / sum * 10000.0) / 100.0);
-				percentSum += vo.getRate();
-				vo.setCount((int)Math.round(vo.getRate() / 100 * total));
-				countSum += vo.getCount();
-			} else {
-				vo.setRate(Math.round((100.0 - percentSum) * 100.0) / 100.0);
-				vo.setCount(total - countSum);
-			}
+		QueryWrapper<MktDeviceTime> timeWrapper = new QueryWrapper<>();
+		timeWrapper.eq("type", "before");
+		List<MktDeviceTime> timeList = mktDeviceTimeMapper.selectList(timeWrapper);
+		List<UninstallTimeDiffVO> timeDiffs = new ArrayList<>();
+		for (MktDeviceTime entity : timeList) {
+			UninstallTimeDiffVO vo = new UninstallTimeDiffVO();
+			vo.setTime(entity.getTimeRange());
+			vo.setCount(entity.getDeviceCount());
+			vo.setRate(entity.getRate());
 			timeDiffs.add(vo);
 		}
-
 		// 2. 卸载前7天使用次数分布
-		String[] countRanges = {"6次以上", "5次", "4次", "3次", "2次", "1次"};
+		QueryWrapper<MktDeviceCount> countWrapper = new QueryWrapper<>();
+		countWrapper.eq("type", "before");
+		List<MktDeviceCount> countList = mktDeviceCountMapper.selectList(countWrapper);
 		List<UninstallBeforeSevenVO> beforeSevens = new ArrayList<>();
-		int total2 = 500 + random.nextInt(500);
-		double percentSum2 = 0;
-		int countSum2 = 0;
-		double[] raw2 = new double[countRanges.length];
-		double sum2 = 0;
-		for (int i = 0; i < countRanges.length; i++) {
-			raw2[i] = 10 + random.nextDouble() * 90;
-			sum2 += raw2[i];
-		}
-		for (int i = 0; i < countRanges.length; i++) {
+		for (MktDeviceCount entity : countList) {
 			UninstallBeforeSevenVO vo = new UninstallBeforeSevenVO();
-			vo.setTime(countRanges[i]);
-			if (i < countRanges.length - 1) {
-				vo.setRate(Math.round(raw2[i] / sum2 * 10000.0) / 100.0);
-				percentSum2 += vo.getRate();
-				vo.setCount((int)Math.round(vo.getRate() / 100 * total2));
-				countSum2 += vo.getCount();
-			} else {
-				vo.setRate(Math.round((100.0 - percentSum2) * 100.0) / 100.0);
-				vo.setCount(total2 - countSum2);
-			}
+			vo.setTime(entity.getCountRange());
+			vo.setCount(entity.getNum());
+			vo.setRate(entity.getRate());
 			beforeSevens.add(vo);
 		}
-
 		// 3. 卸载前干扰指标
-		List<UninstallBeforeInterfereVO> interfereList = new ArrayList<>();
-		String[] interfereTypes = {"前七天崩溃次数", "前7天推送接受"};
-		for (String type : interfereTypes) {
+		QueryWrapper<MktDeviceInterfere> interfereWrapper = new QueryWrapper<>();
+		List<MktDeviceInterfere> interfereList = mktDeviceInterfereMapper.selectList(interfereWrapper);
+		Map<String, Map<String, Integer>> interfereMap = new LinkedHashMap<>();
+		for (MktDeviceInterfere entity : interfereList) {
+			interfereMap.computeIfAbsent(entity.getInterfereType(), k -> new LinkedHashMap<>())
+				.put(entity.getCountRange(), entity.getNum());
+		}
+		List<UninstallBeforeInterfereVO> interfereVOList = new ArrayList<>();
+		for (Map.Entry<String, Map<String, Integer>> entry : interfereMap.entrySet()) {
 			UninstallBeforeInterfereVO vo = new UninstallBeforeInterfereVO();
-			vo.setType(type);
-			Map<String, Integer> value = new LinkedHashMap<>();
-			for (String c : countRanges) {
-				value.put(c, 1 + random.nextInt(100));
-			}
-			vo.setValue(value);
-			interfereList.add(vo);
+			vo.setType(entry.getKey());
+			vo.setValue(entry.getValue());
+			interfereVOList.add(vo);
 		}
-
 		// 4. 卸载前行为还原
-		List<UninstallBeforeActionVO> actionList = new ArrayList<>();
-		String[] actionTypes = {"高频浏览页面TOP10", "最终浏览页面TOP10"};
-		for (String actionType : actionTypes) {
+		QueryWrapper<MktDeviceAction> actionWrapper = new QueryWrapper<>();
+		List<MktDeviceAction> actionList = mktDeviceActionMapper.selectList(actionWrapper);
+		Map<String, Map<String, Integer>> actionMap = new LinkedHashMap<>();
+		for (MktDeviceAction entity : actionList) {
+			actionMap.computeIfAbsent(entity.getActionType(), k -> new LinkedHashMap<>())
+				.put(entity.getActionValue(), entity.getTriggerCount());
+		}
+		List<UninstallBeforeActionVO> actionVOList = new ArrayList<>();
+		for (Map.Entry<String, Map<String, Integer>> entry : actionMap.entrySet()) {
 			UninstallBeforeActionVO vo = new UninstallBeforeActionVO();
-			vo.setActionType(actionType);
-			Map<String, Integer> value = new LinkedHashMap<>();
-			for (int i = 1; i <= 10; i++) {
-				value.put("页面" + i, 1 + random.nextInt(100));
-			}
-			vo.setValue(value);
-			actionList.add(vo);
+			vo.setActionType(entry.getKey());
+			vo.setValue(entry.getValue());
+			actionVOList.add(vo);
 		}
-		// 下单、invest
-		UninstallBeforeActionVO orderInvest = new UninstallBeforeActionVO();
-		orderInvest.setActionType("下单/Invest");
-		Map<String, Integer> orderInvestMap = new LinkedHashMap<>();
-		orderInvestMap.put("下单", 1 + random.nextInt(100));
-		orderInvestMap.put("invest", 1 + random.nextInt(100));
-		orderInvest.setValue(orderInvestMap);
-		actionList.add(orderInvest);
-
 		UninstallBeforeVO result = new UninstallBeforeVO();
 		result.setUninstallTimeDiffs(timeDiffs);
 		result.setUninstallBeforeSevens(beforeSevens);
-		result.setUninstallBeforeInterferences(interfereList);
-		result.setUninstallBeforeActions(actionList);
+		result.setUninstallBeforeInterferences(interfereVOList);
+		result.setUninstallBeforeActions(actionVOList);
 		return result;
 	}
 
 	@Override
 	public List<UninstallOfterAPPOV> uninstallAfter(GetUninstallInsightDTO dto) {
-		List<UninstallOfterAPPOV> list = new ArrayList<>();
-		String[] appNames = {"微信", "QQ", "抖音", "淘宝", "京东", "美团", "拼多多", "快手", "B站", "微博"};
+		// 这里只做演示,实际可查mkt_device_time或相关表
+		QueryWrapper<MktDeviceTime> wrapper = new QueryWrapper<>();
+		wrapper.eq("type", "after");
+		List<MktDeviceTime> list = mktDeviceTimeMapper.selectList(wrapper);
+		List<UninstallOfterAPPOV> result = new ArrayList<>();
+		for (MktDeviceTime entity : list) {
+			UninstallOfterAPPOV vo = new UninstallOfterAPPOV();
+			vo.setAppName(entity.getTimeRange()); // 假设timeRange存appName
+			vo.setCount(entity.getDeviceCount());
+			vo.setProportion(entity.getRate() != null ? entity.getRate().toString() : null);
+			result.add(vo);
+		}
+		return result;
+	}
+
+	@Override
+	public List<UninstallSYSOV> uninstallSys(GetUninstallInsightDTO dto) {
+		QueryWrapper<MktDeviceTime> wrapper = new QueryWrapper<>();
+		wrapper.eq("type", "sys");
+		List<MktDeviceTime> list = mktDeviceTimeMapper.selectList(wrapper);
+		Map<String, List<Map<String, Integer>>> sysMap = new LinkedHashMap<>();
+		for (MktDeviceTime entity : list) {
+			sysMap.computeIfAbsent(entity.getTimeRange(), k -> new ArrayList<>())
+				.add(Collections.singletonMap(entity.getAppVersion(), entity.getDeviceCount()));
+		}
+		List<UninstallSYSOV> result = new ArrayList<>();
+		for (Map.Entry<String, List<Map<String, Integer>>> entry : sysMap.entrySet()) {
+			UninstallSYSOV vo = new UninstallSYSOV();
+			vo.setDimensionName(entry.getKey());
+			vo.setDistribution(entry.getValue());
+			result.add(vo);
+		}
+		return result;
+	}
+
+	@Override
+	public UninstallPortraitOV getUninstallPortrait(UninstallPortraitDTO dto) {
+		UninstallPortraitOV vo = new UninstallPortraitOV();
+		// 1. 卸载数量
+		UninstallPortraitSumOV sum = new UninstallPortraitSumOV();
+		sum.setTimeUnit(dto.getTimeUnit() == null ? "week" : dto.getTimeUnit());
+		sum.setCount(1000 + random.nextInt(1000));
+		vo.setUninstallCount(sum);
+		// 2. 用户特征情况
+		List<UninstallPortraitCharacterVO> charList = new ArrayList<>();
+		String[] easyNames = {"专科", "便捷生活_智能生活", "社交通讯_同城本地社区", "影音娱乐_乐器", "教育_考公务员"};
+		String[] hardNames = {"25-29岁", "三线城市", "普通消费", "商务办公_CRM营销工具", "影音娱乐_在线音乐"};
+		for (String name : easyNames) {
+			UninstallPortraitCharacterVO c = new UninstallPortraitCharacterVO();
+			c.setName(name);
+			c.setTgi(String.valueOf(80 + random.nextInt(40)));
+			c.setPercent(String.valueOf(10 + random.nextInt(20)));
+			c.setStatus(0);
+			charList.add(c);
+		}
+		for (String name : hardNames) {
+			UninstallPortraitCharacterVO c = new UninstallPortraitCharacterVO();
+			c.setName(name);
+			c.setTgi(String.valueOf(80 + random.nextInt(40)));
+			c.setPercent(String.valueOf(10 + random.nextInt(20)));
+			c.setStatus(1);
+			charList.add(c);
+		}
+		vo.setUninstallPortraitCharactList(charList);
+		// 3. 卸载阶段
+		String[] phases = {"未使用", "使用1次", "使用2次", "使用3次", "使用4次", "使用5次", "6次以上"};
+		List<UninstallPortraitPhaseVO> phaseList = new ArrayList<>();
 		int total = 1000 + random.nextInt(1000);
 		double percentSum = 0;
 		int countSum = 0;
-		double[] raw = new double[appNames.length];
-		double sum = 0;
-		for (int i = 0; i < appNames.length; i++) {
+		double[] raw = new double[phases.length];
+		double sumPhase = 0;
+		for (int i = 0; i < phases.length; i++) {
 			raw[i] = 10 + random.nextDouble() * 90;
-			sum += raw[i];
+			sumPhase += raw[i];
 		}
-		for (int i = 0; i < appNames.length; i++) {
-			UninstallOfterAPPOV vo = new UninstallOfterAPPOV();
-			vo.setAppName(appNames[i]);
-			if (i < appNames.length - 1) {
-				vo.setProportion(String.valueOf(Math.round(raw[i] / sum * 10000.0) / 100.0));
-				percentSum += Double.parseDouble(vo.getProportion());
-				vo.setCount((int)Math.round(Double.parseDouble(vo.getProportion()) / 100 * total));
-				countSum += vo.getCount();
+		for (int i = 0; i < phases.length; i++) {
+			UninstallPortraitPhaseVO p = new UninstallPortraitPhaseVO();
+			p.setPhase(phases[i]);
+			if (i < phases.length - 1) {
+				p.setRate(Math.round(raw[i] / sumPhase * 10000.0) / 100.0);
+				percentSum += p.getRate();
+				p.setCount((int)Math.round(p.getRate() / 100 * total));
+				countSum += p.getCount();
 			} else {
-				vo.setProportion(String.valueOf(Math.round((100.0 - percentSum) * 100.0) / 100.0));
-				vo.setCount(total - countSum);
+				p.setRate(Math.round((100.0 - percentSum) * 100.0) / 100.0);
+				p.setCount(total - countSum);
 			}
+			phaseList.add(p);
+		}
+		vo.setUninstallPortraitPhaseList(phaseList);
+		return vo;
+	}
+
+	@Override
+	public UninstallPredictVO getUninstallPredict(UninstallPredictDTO dto) {
+		UninstallPredictVO vo = new UninstallPredictVO();
+		// 预测时间为一周最后一天
+		LocalDate start = LocalDate.now();
+		LocalDate predictTime = start.plusDays(6);
+		vo.setPredictTime(predictTime.toString());
+		vo.setUninstallCount(100 + random.nextInt(200));
+		vo.setRecallCount(10 + random.nextInt(50));
+		return vo;
+	}
+
+	@Override
+	public List<InstallUninstallRatioVO> getInstallUninstallRatio(InstallUninstallRatioDTO dto) {
+		List<InstallUninstallRatioVO> list = new ArrayList<>();
+		String[] types = {"当前应用", "移动视频", "医疗服务"};
+		LocalDate start = LocalDate.now();
+		for (String type : types) {
+			InstallUninstallRatioVO vo = new InstallUninstallRatioVO();
+			vo.setDate(java.sql.Date.valueOf(start));
+			vo.setType(type);
+			vo.setRate(Math.round((10 + random.nextDouble() * 90) * 100.0) / 100.0);
 			list.add(vo);
 		}
 		return list;
 	}
 
 	@Override
-	public List<UninstallSYSOV> uninstallSys(GetUninstallInsightDTO dto) {
-		List<UninstallSYSOV> list = new ArrayList<>();
-		String[] dimensions = {"Android", "iOS"};
-		for (String dim : dimensions) {
-			UninstallSYSOV vo = new UninstallSYSOV();
-			vo.setDimensionName(dim);
-			List<Map<String, Integer>> dist = new ArrayList<>();
-			for (int i = 1; i <= 5; i++) {
-				Map<String, Integer> map = new LinkedHashMap<>();
-				map.put("版本" + i, 1 + random.nextInt(1000));
-				dist.add(map);
+	public List<InstallUninstallRatioVO> getInstallUninstallRatioDetail(InstallUninstallRatioDTO dto) {
+		List<InstallUninstallRatioVO> list = new ArrayList<>();
+		String[] types = {"当前应用", "移动视频", "医疗服务"};
+		LocalDate start = LocalDate.now();
+		for (int i = 0; i < 7; i++) {
+			LocalDate date = start.plusDays(i);
+			for (String type : types) {
+				InstallUninstallRatioVO vo = new InstallUninstallRatioVO();
+				vo.setDate(java.sql.Date.valueOf(date));
+				vo.setType(type);
+				vo.setRate(Math.round((10 + random.nextDouble() * 90) * 100.0) / 100.0);
+				list.add(vo);
 			}
-			vo.setDistribution(dist);
-			list.add(vo);
 		}
 		return list;
 	}