package com.example.demo.serviceImpl; import com.example.demo.domain.entity.Statistics; import com.example.demo.domain.entity.UserGoldRecord; import com.example.demo.mapper.StatisticsMapper; import com.example.demo.service.GeneralService; import com.example.demo.service.StatisticsService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; /** * @program: gold-java * @ClassName StatisticsServiceImpl * @description: 统计相关 * @author: Ethan * @create: 2025−06-18 12:00 * @Version 1.0 **/ @Service public class StatisticsServiceImpl implements StatisticsService { private static final Logger log = LoggerFactory.getLogger(StatisticsServiceImpl.class); @Autowired private StatisticsMapper statisticsMapper; @Autowired private GeneralService generalService; /* 12点,18点,23点30分执行定时任务更新当天part1数据 */ @Override @Scheduled(cron = "0 0 12,18 * * ?") // 分别在 12:00 和 18:00 执行 @Scheduled(cron = "0 30 23 * * ?") // 在 23:30 执行 public void runHourlyTaskPart1() { Date today = new Date(); //取当天日期 for(String market : generalService.getMarket()){ saveStatisticsPart1(market,today); } } /* 12点,18点执行定时任务更新当天part2数据 */ @Override @Scheduled(cron = "0 0 12,18 * * ?") public void runHourlyTaskPart2() { Date today = new Date(); //取当天日期 for(String market : generalService.getMarket()){ saveStatisticsPart2(market,today); } } /* 0点执行定时任务更新近一周part2数据 */ @Override @Scheduled(cron = "0 0 0 * * ?") public void runDailyTaskPart2() { Calendar cal = Calendar.getInstance(); cal.add(Calendar.DAY_OF_YEAR, -7); // 一周前 Date startDate = cal.getTime(); Date yesterday = generalService.getYesterday(); // 昨天 // 获取 Calendar 实例并设置为昨天的日期 Calendar calendar = Calendar.getInstance(); calendar.setTime(yesterday); // 设置时间为昨天的23:55 calendar.set(Calendar.HOUR_OF_DAY, 23); calendar.set(Calendar.MINUTE, 59); calendar.set(Calendar.SECOND, 55); //把yesterday的结束时间设为结束时间 Date endDate= calendar.getTime(); //近一周的日期列表 List dateList =generalService.getAllDatesBetween(startDate, endDate); for (Date date : dateList) { for (String market : generalService.getMarket()) { saveStatisticsPart2(market, date); } } } /* 查询某地区某天已存在的统计数据 */ @Override public Statistics getExistStatistics(String market, Date date) { LocalDateTime startTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().with(LocalTime.MIN); LocalDateTime endTime= startTime.plusDays(1).minusSeconds(1); return statisticsMapper.selectByMarketAndDate(market, Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()), Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant())); } /* 新增或更新或不修改某地区某天part1统计数据 */ @Override public void saveStatisticsPart1(String market, Date date) { //获取该地区该日期part1(余量属性)统计数据 Statistics newStats=getStatisticsPart1(market,date); //获取该地区该日期已存在的数据 Statistics existStats = getExistStatistics(market, date); //判断是否存在已存在的数据 if(existStats==null){ //没有记录,新增 statisticsMapper.insertPart1(newStats ); }else { //判断新旧数据part1部分(余量属性)是否一致 if (!isSameStatisticsPart1(existStats,newStats)){ statisticsMapper.updatePart1(newStats); }else{ System.out.println("数据未发生改变"); } } } /* 新增或更新或不修改某地区某天part2统计数据 */ @Override public void saveStatisticsPart2(String market, Date date){ //获取该地区该日期part2(余量外属性)统计数据 Statistics newStats=getStatisticsPart2(market,date); //获取该地区该日期已存在的数据 Statistics existStats = getExistStatistics(market, date); //判断是否存在已存在的数据 if(existStats==null){ //没有记录,新增 statisticsMapper.insertPart2(newStats ); }else { //判断新旧数据part2部分(余量外属性)是否一致 if (!isSameStatisticsPart2(existStats,newStats)){ statisticsMapper.updatePart2(newStats); }else{ System.out.println("数据未发生改变"); } } } //根据地区与日期获取part1(余量属性)统计数据 @Override public Statistics getStatisticsPart1(String market, Date date) { //获取日期 LocalDate localDate=date.toInstant() .atZone(ZoneId.of("Asia/Shanghai")) // 使用系统默认时区 .toLocalDate(); //初始化Statistics对象 Statistics statistics = new Statistics(); statistics.setMarket(market); statistics.setCurrentDatetime(localDate); //计算属性 //当前金币余量 Integer currentGold = statisticsMapper.sumCurrentPermanentGold(market)+ statisticsMapper.sumCurrentFreeJune( market)+ statisticsMapper.sumCurrentFreeDecember(market)+ statisticsMapper.sumCurrentTaskGold( market); statistics.setCurrentGold(currentGold); //较前一日变化 Date yesterday =generalService.getYesterday(); //把yesterday改为昨天的开始时间和结束时间 LocalDateTime startTime = yesterday.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().with(LocalTime.MIN); LocalDateTime endTime= startTime.plusDays(1).minusSeconds(1); //昨天金币余量 Statistics ydayStats = statisticsMapper.selectByMarketAndDate(market, Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()), Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant())); Integer yesterdayGold=0; if (ydayStats != null) { yesterdayGold = ydayStats.getCurrentGold(); } Integer dailyChange = currentGold - yesterdayGold; statistics.setDailyChange(dailyChange); //当前永久金币 Integer currentPermanent = statisticsMapper.sumCurrentPermanentGold(market); statistics.setCurrentPermanent(currentPermanent); //当前免费六月金币 Integer currentFreeJune = statisticsMapper.sumCurrentFreeJune(market); statistics.setCurrentFreeJune(currentFreeJune); //当前免费十二月金币 Integer currentFreeDecember = statisticsMapper.sumCurrentFreeDecember(market); statistics.setCurrentFreeDecember(currentFreeDecember); //当前任务金币 Integer currentTask = statisticsMapper.sumCurrentTaskGold(market); statistics.setCurrentTask(currentTask); return statistics; } /* 根据地区与日期获取part2(余量外属性)统计数据 */ @Override public Statistics getStatisticsPart2(String market, Date date) { //获取日期 LocalDate localDate=date.toInstant() .atZone(ZoneId.of("Asia/Shanghai")) // 使用系统默认时区 .toLocalDate(); //把date改为当天的开始时间和结束时间 LocalDateTime startTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().with(LocalTime.MIN); LocalDateTime endTime= startTime.plusDays(1).minusSeconds(1); //定义审核状态列表 List auditStatusList = new ArrayList<>(); auditStatusList.add(1); // 审核通过 auditStatusList.add(3); // 外部传入默认通过 //查询当天该地区审核通过的所有数据 List records = statisticsMapper.findByMarketAndAuditStatus(market, auditStatusList, Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant())); //初始化Statistics对象 Statistics statistics = new Statistics(); statistics.setMarket(market); statistics.setCurrentDatetime(localDate); //计算属性 //充值相关-当日充值(永久+免费) Integer recharge = records.stream() .filter(record -> record.getType() == 0) // 类型为充值 .mapToInt(record -> record.getPermanentGold() + record.getFreeJune() + record.getFreeDecember() + record.getTaskGold()) .sum(); statistics.setRecharge(recharge); //充值相关-当日金额(永久) Integer money = records.stream() .filter(record -> record.getType() == 0) // 类型为充值 .mapToInt(UserGoldRecord::getPermanentGold) .sum(); statistics.setMoney(money); //消费相关-当日新增消费(永久) Integer consumePermanent = records.stream() .filter(record -> record.getType() == 1) // 类型为消费 .mapToInt(UserGoldRecord::getPermanentGold) .sum(); statistics.setConsumePermanent(consumePermanent); //消费相关-当日新增消费(六月免费) Integer consumeFreeJune = records.stream() .filter(record -> record.getType() == 1) // 类型为消费 .mapToInt(UserGoldRecord::getFreeJune) .sum(); statistics.setConsumeFreeJune(consumeFreeJune); //消费相关-当日新增消费(十二月免费) Integer consumeFreeDecember = records.stream() .filter(record -> record.getType() == 1) // 类型为消费 .mapToInt(UserGoldRecord::getFreeDecember) .sum(); statistics.setConsumeFreeDecember(consumeFreeDecember); //消费相关-当日新增消费(任务) Integer consumeTask = records.stream() .filter(record -> record.getType() == 1) // 类型为消费 .mapToInt(UserGoldRecord::getTaskGold) .sum(); statistics.setConsumeTask(consumeTask); //退款相关-当日退款(永久) Integer refundPermanent = records.stream() .filter(record -> record.getType() == 2) // 类型为退款 .mapToInt(UserGoldRecord::getPermanentGold) .sum(); statistics.setRefundPermanent(refundPermanent); //退款相关-当日退款(六月免费) Integer refundFreeJune = records.stream() .filter(record -> record.getType() == 2) // 类型为退款 .mapToInt(UserGoldRecord::getFreeJune) .sum(); statistics.setRefundFreeJune(refundFreeJune); //退款相关-当日退款(十二月免费) Integer refundFreeDecember = records.stream() .filter(record -> record.getType() == 2) // 类型为退款 .mapToInt(UserGoldRecord::getFreeDecember) .sum(); statistics.setRefundFreeDecember(refundFreeDecember); //退款相关-当日退款(任务) Integer refundTask = records.stream() .filter(record -> record.getType() == 2) // 类型为退款 .mapToInt(UserGoldRecord::getTaskGold) .sum(); statistics.setRefundTask(refundTask); //充值人数 int rechargeNum= statisticsMapper.countRechargeNum(market,Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant())); statistics.setRechargeNum(rechargeNum); //首充人数 int firstRecharge= statisticsMapper.countFirstRecharge(market,Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant())); statistics.setFirstRecharge(firstRecharge); return statistics; } /* * 判断两个统计对象part1(余量属性)是否相同 */ private boolean isSameStatisticsPart1(Statistics oldStats, Statistics newStats) { return Objects.equals(oldStats.getCurrentGold(), newStats.getCurrentGold()) && Objects.equals(oldStats.getCurrentPermanent(), newStats.getCurrentPermanent()) && Objects.equals(oldStats.getCurrentFreeJune(), newStats.getCurrentFreeJune()) && Objects.equals(oldStats.getCurrentFreeDecember(), newStats.getCurrentFreeDecember()) && Objects.equals(oldStats.getCurrentTask(), newStats.getCurrentTask()) && Objects.equals(oldStats.getDailyChange(), newStats.getDailyChange()) ; } /* * 判断两个统计对象part2(余量外属性)是否相同 */ private boolean isSameStatisticsPart2(Statistics oldStats, Statistics newStats) { return Objects.equals(oldStats.getRecharge(), newStats.getRecharge()) && Objects.equals(oldStats.getMoney(), newStats.getMoney()) && Objects.equals(oldStats.getConsumePermanent(), newStats.getConsumePermanent()) && Objects.equals(oldStats.getConsumeFreeJune(), newStats.getConsumeFreeJune()) && Objects.equals(oldStats.getConsumeFreeDecember(), newStats.getConsumeFreeDecember()) && Objects.equals(oldStats.getConsumeTask(), newStats.getConsumeTask()) && Objects.equals(oldStats.getRefundPermanent(), newStats.getRefundPermanent()) && Objects.equals(oldStats.getRefundFreeJune(), newStats.getRefundFreeJune()) && Objects.equals(oldStats.getRefundFreeDecember(), newStats.getRefundFreeDecember()) && Objects.equals(oldStats.getRefundTask(), newStats.getRefundTask()) && Objects.equals(oldStats.getRechargeNum(), newStats.getRechargeNum()) && Objects.equals(oldStats.getFirstRecharge(), newStats.getFirstRecharge()) && Objects.equals(oldStats.getCurrentGold(), newStats.getCurrentGold()) && Objects.equals(oldStats.getDailyChange(), newStats.getDailyChange()) && Objects.equals(oldStats.getCurrentPermanent(), newStats.getCurrentPermanent()) && Objects.equals(oldStats.getCurrentFreeJune(), newStats.getCurrentFreeJune()) && Objects.equals(oldStats.getCurrentFreeDecember(), newStats.getCurrentFreeDecember()) && Objects.equals(oldStats.getCurrentTask(), newStats.getCurrentTask()); } }