package com.tcm.training.admin.statistics.service; import com.tcm.training.admin.statistics.mapper.ContentStatisticsMapper; import com.tcm.training.admin.statistics.row.ContentStatisticsDailyRow; import com.tcm.training.admin.statistics.vo.ContentStatisticsOverviewVO; import com.tcm.training.admin.statistics.vo.ContentStatisticsTrendItemVO; import com.tcm.training.admin.statistics.vo.ContentStatisticsVO; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Service public class ContentStatisticsAppService { private final ContentStatisticsMapper contentStatisticsMapper; public ContentStatisticsAppService(ContentStatisticsMapper contentStatisticsMapper) { this.contentStatisticsMapper = contentStatisticsMapper; } public ContentStatisticsVO statistics(LocalDate dateFrom, LocalDate dateTo) { DateRange range = normalizeRange(dateFrom, dateTo); List rows = contentStatisticsMapper.selectDailyStatistics( range.getStart().atStartOfDay(), LocalDateTime.of(range.getEnd(), LocalTime.MAX) ); Map rowMap = new HashMap(); for (ContentStatisticsDailyRow row : rows) { rowMap.put(row.getStatDate(), row); } ContentStatisticsOverviewVO overview = new ContentStatisticsOverviewVO(); overview.setVideoPlayCount(0L); overview.setCourseFavoriteCount(0L); overview.setPointsEarnedCount(0L); overview.setConsultClickCount(0L); List contentTrend = new ArrayList(); List pointsTrend = new ArrayList(); LocalDate cursor = range.getStart(); while (!cursor.isAfter(range.getEnd())) { ContentStatisticsDailyRow row = rowMap.get(cursor); Long videoPlayCount = nvl(row == null ? null : row.getVideoPlayCount()); Long courseFavoriteCount = nvl(row == null ? null : row.getCourseFavoriteCount()); Long consultClickCount = nvl(row == null ? null : row.getConsultClickCount()); Long pointsEarnedCount = nvl(row == null ? null : row.getPointsEarnedCount()); ContentStatisticsTrendItemVO contentTrendItem = new ContentStatisticsTrendItemVO(); contentTrendItem.setDate(cursor.toString()); contentTrendItem.setVideoPlayCount(videoPlayCount); contentTrendItem.setCourseFavoriteCount(courseFavoriteCount); contentTrendItem.setConsultClickCount(consultClickCount); contentTrend.add(contentTrendItem); ContentStatisticsTrendItemVO pointsTrendItem = new ContentStatisticsTrendItemVO(); pointsTrendItem.setDate(cursor.toString()); pointsTrendItem.setPointsEarnedCount(pointsEarnedCount); pointsTrend.add(pointsTrendItem); overview.setVideoPlayCount(overview.getVideoPlayCount() + videoPlayCount); overview.setCourseFavoriteCount(overview.getCourseFavoriteCount() + courseFavoriteCount); overview.setConsultClickCount(overview.getConsultClickCount() + consultClickCount); overview.setPointsEarnedCount(overview.getPointsEarnedCount() + pointsEarnedCount); cursor = cursor.plusDays(1); } ContentStatisticsVO result = new ContentStatisticsVO(); result.setOverview(overview); result.setContentTrend(contentTrend); result.setPointsTrend(pointsTrend); return result; } private DateRange normalizeRange(LocalDate dateFrom, LocalDate dateTo) { LocalDate start = dateFrom; LocalDate end = dateTo; if (start == null && end == null) { start = LocalDate.now(); end = start; } else if (start == null) { start = end; } else if (end == null) { end = start; } if (start.isAfter(end)) { throw new IllegalArgumentException("开始日期不能晚于结束日期"); } return new DateRange(start, end); } private Long nvl(Long value) { return value == null ? 0L : value; } private static class DateRange { private final LocalDate start; private final LocalDate end; private DateRange(LocalDate start, LocalDate end) { this.start = start; this.end = end; } private LocalDate getStart() { return start; } private LocalDate getEnd() { return end; } } }