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<ContentStatisticsDailyRow> rows = contentStatisticsMapper.selectDailyStatistics(
|
range.getStart().atStartOfDay(),
|
LocalDateTime.of(range.getEnd(), LocalTime.MAX)
|
);
|
|
Map<LocalDate, ContentStatisticsDailyRow> rowMap = new HashMap<LocalDate, ContentStatisticsDailyRow>();
|
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<ContentStatisticsTrendItemVO> contentTrend = new ArrayList<ContentStatisticsTrendItemVO>();
|
List<ContentStatisticsTrendItemVO> pointsTrend = new ArrayList<ContentStatisticsTrendItemVO>();
|
|
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;
|
}
|
}
|
}
|