|
|
@@ -0,0 +1,306 @@
|
|
|
+package com.moka.gdtauto.service.impl;
|
|
|
+
|
|
|
+import com.moka.gdtauto.mapper.TencentAccountMapper;
|
|
|
+import com.moka.gdtauto.mapper.TencentAdsAdgroupMapper;
|
|
|
+import com.moka.gdtauto.mapper.TencentConversionMapper;
|
|
|
+import com.moka.gdtauto.mapper.TencentImagesMapper;
|
|
|
+import com.moka.gdtauto.mapper.TencentVideoMapper;
|
|
|
+import com.moka.gdtauto.service.DashboardService;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Dashboard仪表盘服务实现类
|
|
|
+ *
|
|
|
+ * @author moka
|
|
|
+ * @since 2026-02-06
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class DashboardServiceImpl implements DashboardService {
|
|
|
+
|
|
|
+ private final TencentVideoMapper videoMapper;
|
|
|
+ private final TencentImagesMapper imagesMapper;
|
|
|
+ private final TencentAdsAdgroupMapper adgroupMapper;
|
|
|
+ private final TencentConversionMapper conversionMapper;
|
|
|
+ private final TencentAccountMapper accountMapper;
|
|
|
+
|
|
|
+ @Value("${spring.application.version:v1.0.0}")
|
|
|
+ private String appVersion;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> getStatisticsOverview() {
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 获取各类资源统计
|
|
|
+ long videoCount = videoMapper.selectCount(null);
|
|
|
+ long imageCount = imagesMapper.selectCount(null);
|
|
|
+ long adgroupCount = adgroupMapper.selectCount(null);
|
|
|
+ long conversionCount = conversionMapper.selectCount(null);
|
|
|
+ long accountCount = accountMapper.selectCount(null);
|
|
|
+
|
|
|
+ result.put("videoCount", videoCount);
|
|
|
+ result.put("imageCount", imageCount);
|
|
|
+ result.put("adgroupCount", adgroupCount);
|
|
|
+ result.put("conversionCount", conversionCount);
|
|
|
+ result.put("accountCount", accountCount);
|
|
|
+
|
|
|
+ // 计算今日新增
|
|
|
+ LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
|
|
|
+ LocalDateTime todayEnd = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59);
|
|
|
+
|
|
|
+ result.put("todayVideoCount", getTodayCount(videoMapper, todayStart, todayEnd));
|
|
|
+ result.put("todayImageCount", getTodayCount(imagesMapper, todayStart, todayEnd));
|
|
|
+ result.put("todayAdgroupCount", getTodayCount(adgroupMapper, todayStart, todayEnd));
|
|
|
+ result.put("todayConversionCount", getTodayCount(conversionMapper, todayStart, todayEnd));
|
|
|
+
|
|
|
+ // 计算本周新增
|
|
|
+ LocalDateTime weekStart = LocalDateTime.now().minusDays(7);
|
|
|
+ result.put("weekVideoCount", getPeriodCount(videoMapper, weekStart, LocalDateTime.now()));
|
|
|
+ result.put("weekImageCount", getPeriodCount(imagesMapper, weekStart, LocalDateTime.now()));
|
|
|
+ result.put("weekAdgroupCount", getPeriodCount(adgroupMapper, weekStart, LocalDateTime.now()));
|
|
|
+ result.put("weekConversionCount", getPeriodCount(conversionMapper, weekStart, LocalDateTime.now()));
|
|
|
+
|
|
|
+ log.info("获取统计概览成功: 视频={}, 图片={}, 广告组={}, 转化={}, 账户={}",
|
|
|
+ videoCount, imageCount, adgroupCount, conversionCount, accountCount);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取统计概览失败", e);
|
|
|
+ throw new RuntimeException("获取统计概览失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> getVideoStatistics() {
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+
|
|
|
+ try {
|
|
|
+ long totalCount = videoMapper.selectCount(null);
|
|
|
+ result.put("totalCount", totalCount);
|
|
|
+
|
|
|
+ // 按状态统计
|
|
|
+ Map<String, Object> statusStats = new HashMap<>();
|
|
|
+ // 这里可以根据实际的status字段进行分组统计
|
|
|
+ statusStats.put("uploaded", totalCount); // 假设所有都是已上传状态
|
|
|
+ statusStats.put("processing", 0L);
|
|
|
+ statusStats.put("failed", 0L);
|
|
|
+ result.put("statusDistribution", statusStats);
|
|
|
+
|
|
|
+ // 按账户统计Top5
|
|
|
+ // List<Map<String, Object>> topAccounts = videoMapper.selectCountByAccount();
|
|
|
+ // result.put("topAccounts", topAccounts);
|
|
|
+
|
|
|
+ log.info("获取视频统计成功: 总数={}", totalCount);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取视频统计失败", e);
|
|
|
+ throw new RuntimeException("获取视频统计失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> getImageStatistics() {
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+
|
|
|
+ try {
|
|
|
+ long totalCount = imagesMapper.selectCount(null);
|
|
|
+ result.put("totalCount", totalCount);
|
|
|
+
|
|
|
+ // 按状态统计
|
|
|
+ Map<String, Object> statusStats = new HashMap<>();
|
|
|
+ statusStats.put("uploaded", totalCount);
|
|
|
+ statusStats.put("processing", 0L);
|
|
|
+ statusStats.put("failed", 0L);
|
|
|
+ result.put("statusDistribution", statusStats);
|
|
|
+
|
|
|
+ // 按账户统计Top5
|
|
|
+ // List<Map<String, Object>> topAccounts = imagesMapper.selectCountByAccount();
|
|
|
+ // result.put("topAccounts", topAccounts);
|
|
|
+
|
|
|
+ log.info("获取图片统计成功: 总数={}", totalCount);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取图片统计失败", e);
|
|
|
+ throw new RuntimeException("获取图片统计失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> getAdgroupStatistics() {
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+
|
|
|
+ try {
|
|
|
+ long totalCount = adgroupMapper.selectCount(null);
|
|
|
+ result.put("totalCount", totalCount);
|
|
|
+
|
|
|
+ // 按状态统计
|
|
|
+ Map<String, Object> statusStats = new HashMap<>();
|
|
|
+ // 根据configured_status字段统计
|
|
|
+ // List<Map<String, Object>> statusList = adgroupMapper.selectCountByStatus();
|
|
|
+ // for (Map<String, Object> status : statusList) {
|
|
|
+ // String statusKey = (String) status.get("status");
|
|
|
+ // Long count = (Long) status.get("count");
|
|
|
+ // statusStats.put(statusKey != null ? statusKey.toLowerCase() : "unknown", count);
|
|
|
+ // }
|
|
|
+ result.put("statusDistribution", statusStats);
|
|
|
+
|
|
|
+ // 按营销场景统计
|
|
|
+ // List<Map<String, Object>> sceneList = adgroupMapper.selectCountByMarketingScene();
|
|
|
+ // result.put("sceneDistribution", sceneList);
|
|
|
+
|
|
|
+ // 按账户统计Top5
|
|
|
+ // List<Map<String, Object>> topAccounts = adgroupMapper.selectCountByAccount();
|
|
|
+ // result.put("topAccounts", topAccounts);
|
|
|
+
|
|
|
+ log.info("获取广告组统计成功: 总数={}", totalCount);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取广告组统计失败", e);
|
|
|
+ throw new RuntimeException("获取广告组统计失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> getConversionStatistics() {
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+
|
|
|
+ try {
|
|
|
+ long totalCount = conversionMapper.selectCount(null);
|
|
|
+ result.put("totalCount", totalCount);
|
|
|
+
|
|
|
+ // 按转化类型统计
|
|
|
+ // List<Map<String, Object>> typeList = conversionMapper.selectCountByType();
|
|
|
+ // result.put("typeDistribution", typeList);
|
|
|
+
|
|
|
+ // 按账户统计Top5
|
|
|
+ // List<Map<String, Object>> topAccounts = conversionMapper.selectCountByAccount();
|
|
|
+ // result.put("topAccounts", topAccounts);
|
|
|
+
|
|
|
+ log.info("获取转化统计成功: 总数={}", totalCount);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取转化统计失败", e);
|
|
|
+ throw new RuntimeException("获取转化统计失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> getSystemStatus() {
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 服务状态
|
|
|
+ result.put("serviceStatus", "running");
|
|
|
+ result.put("statusMessage", "所有服务运行正常");
|
|
|
+
|
|
|
+ // 版本信息
|
|
|
+ result.put("version", appVersion);
|
|
|
+
|
|
|
+ // 更新时间
|
|
|
+ String updateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
|
+ result.put("updateTime", updateTime);
|
|
|
+
|
|
|
+ // JVM信息
|
|
|
+ Runtime runtime = Runtime.getRuntime();
|
|
|
+ Map<String, Object> jvmInfo = new HashMap<>();
|
|
|
+ jvmInfo.put("totalMemory", runtime.totalMemory());
|
|
|
+ jvmInfo.put("freeMemory", runtime.freeMemory());
|
|
|
+ jvmInfo.put("maxMemory", runtime.maxMemory());
|
|
|
+ jvmInfo.put("availableProcessors", runtime.availableProcessors());
|
|
|
+ result.put("jvmInfo", jvmInfo);
|
|
|
+
|
|
|
+ // 数据库连接状态(简单检查)
|
|
|
+ try {
|
|
|
+ accountMapper.selectCount(null);
|
|
|
+ result.put("databaseStatus", "connected");
|
|
|
+ result.put("databaseMessage", "数据库连接正常");
|
|
|
+ } catch (Exception e) {
|
|
|
+ result.put("databaseStatus", "disconnected");
|
|
|
+ result.put("databaseMessage", "数据库连接异常: " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("获取系统状态成功");
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取系统状态失败", e);
|
|
|
+ throw new RuntimeException("获取系统状态失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> getRecentActivities(Integer limit) {
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 获取最近的活动记录(这里可以整合各个模块的操作日志)
|
|
|
+ List<Map<String, Object>> activities = new java.util.ArrayList<>();
|
|
|
+
|
|
|
+ // 添加示例活动记录
|
|
|
+ Map<String, Object> activity1 = new HashMap<>();
|
|
|
+ activity1.put("id", 1);
|
|
|
+ activity1.put("type", "video_upload");
|
|
|
+ activity1.put("description", "上传了新的视频素材");
|
|
|
+ activity1.put("timestamp", LocalDateTime.now().minusHours(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
|
|
+ activity1.put("user", "admin");
|
|
|
+ activities.add(activity1);
|
|
|
+
|
|
|
+ Map<String, Object> activity2 = new HashMap<>();
|
|
|
+ activity2.put("id", 2);
|
|
|
+ activity2.put("type", "adgroup_create");
|
|
|
+ activity2.put("description", "创建了新的广告组");
|
|
|
+ activity2.put("timestamp", LocalDateTime.now().minusHours(3).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
|
|
+ activity2.put("user", "admin");
|
|
|
+ activities.add(activity2);
|
|
|
+
|
|
|
+ result.put("activities", activities.subList(0, Math.min(limit, activities.size())));
|
|
|
+
|
|
|
+ log.info("获取最近活动成功: 数量={}", activities.size());
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取最近活动失败", e);
|
|
|
+ throw new RuntimeException("获取最近活动失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取今日新增数量
|
|
|
+ */
|
|
|
+ private long getTodayCount(Object mapper, LocalDateTime start, LocalDateTime end) {
|
|
|
+ // 这里需要根据具体的mapper实现来查询
|
|
|
+ // 暂时返回0,后续在mapper中添加具体实现
|
|
|
+ return 0L;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取时间段内新增数量
|
|
|
+ */
|
|
|
+ private long getPeriodCount(Object mapper, LocalDateTime start, LocalDateTime end) {
|
|
|
+ // 这里需要根据具体的mapper实现来查询
|
|
|
+ // 暂时返回0,后续在mapper中添加具体实现
|
|
|
+ return 0L;
|
|
|
+ }
|
|
|
+}
|