From 5496460df7147ea7974580effd38acb24243fd5d Mon Sep 17 00:00:00 2001 From: jianlin Date: Tue, 24 Jun 2025 18:15:35 +0800 Subject: [PATCH] =?UTF-8?q?6-24=E6=9B=B4=E6=96=B0=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=95=B0=E6=8D=AEpart2(=E4=BD=99=E9=87=8F=E5=A4=96=E5=B1=9E?= =?UTF-8?q?=E6=80=A7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/controller/StatisticsController.java | 18 ++ .../com/example/demo/mapper/StatisticsMapper.java | 53 +++++ .../com/example/demo/service/GeneralService.java | 14 ++ .../example/demo/service/StatisticsService.java | 18 ++ .../demo/serviceImpl/GeneralServiceImpl.java | 55 +++++ .../demo/serviceImpl/StatisticsServiceImpl.java | 222 +++++++++++++++++++++ src/main/resources/application.yml | 4 +- src/main/resources/mapper/StatisticsMapper.xml | 102 ++++++++++ 8 files changed, 484 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/example/demo/mapper/StatisticsMapper.java create mode 100644 src/main/resources/mapper/StatisticsMapper.xml diff --git a/src/main/java/com/example/demo/controller/StatisticsController.java b/src/main/java/com/example/demo/controller/StatisticsController.java index f40b449..b8bab1a 100644 --- a/src/main/java/com/example/demo/controller/StatisticsController.java +++ b/src/main/java/com/example/demo/controller/StatisticsController.java @@ -1,13 +1,20 @@ package com.example.demo.controller; +import com.example.demo.domain.entity.Statistics; +import com.example.demo.domain.vo.Result; +import com.example.demo.service.GeneralService; import com.example.demo.service.StatisticsService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Date; +import java.util.List; + /** * @program: gold-java * @ClassName StatisticsController @@ -25,4 +32,15 @@ import org.springframework.web.bind.annotation.RestController; public class StatisticsController { @Autowired private StatisticsService statisticsService; + @Autowired + private GeneralService generalService; + //测试定时任务1 + @PostMapping("/Hourly") + public void HourlyTask() { + statisticsService.runHourlyTask(); + } + + + + } diff --git a/src/main/java/com/example/demo/mapper/StatisticsMapper.java b/src/main/java/com/example/demo/mapper/StatisticsMapper.java new file mode 100644 index 0000000..a88b42d --- /dev/null +++ b/src/main/java/com/example/demo/mapper/StatisticsMapper.java @@ -0,0 +1,53 @@ +package com.example.demo.mapper; + +import com.example.demo.domain.entity.Statistics; +import com.example.demo.domain.entity.UserGoldRecord; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; + +/** + * @program: gold-java + * @ClassName StatisticsMapper + * @description: + * @author: Ethan + * @create: 2025−06-23 14:08 + * @Version 1.0 + **/ + +@Mapper +public interface StatisticsMapper { + //根据地区、审核状态、起止时间查询订单表数据 + List findByMarketAndAuditStatus(@Param("market") String market, + @Param("auditStatusList") List auditStatusList, + @Param("startTime") Date startTime, + @Param("endTime") Date endTime); + //获取某地区当前永久金币余量 + Integer sumCurrentPermanentGold(@Param("market") String market); + //获取某地区当前六月免费金币余量 + Integer sumCurrentFreeJune(@Param("market") String market); + //获取某地区当前永久金币余量 + Integer sumCurrentFreeDecember(@Param("market") String market); + //获取某地区当前永久金币余量 + Integer sumCurrentTaskGold(@Param("market") String market); + //计算该天充值人数 + int countRechargeNum( + @Param("market") String market, + @Param("startTime") Date startTime, + @Param("endTime") Date endTime); + //计算该天首充人数 + int countFirstRecharge( + @Param("market") String market, + @Param("startTime") Date startTime, + @Param("endTime") Date endTime); + //新增part2统计数据 + void insertPart2(Statistics statistics); + //更新part2统计数据 + void updatePart2(Statistics statistics); + //获取某地区某天的数据 + Statistics selectByMarketAndDate(@Param("market") String market, + @Param("startDate") Date startDate, + @Param("endDate") Date endDate); +} diff --git a/src/main/java/com/example/demo/service/GeneralService.java b/src/main/java/com/example/demo/service/GeneralService.java index 530bc15..80e13a4 100644 --- a/src/main/java/com/example/demo/service/GeneralService.java +++ b/src/main/java/com/example/demo/service/GeneralService.java @@ -1,5 +1,9 @@ package com.example.demo.service; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.util.Date; import java.util.List; /** @@ -12,6 +16,16 @@ import java.util.List; **/ public interface GeneralService { + //获取所有市场(地区) List getMarket(); + //获取平台 List getPlatform(); + //获取昨天的日期 + Date getYesterday(); + //获取某天的开始时间(00:00:00) + Date getStartOfDay(Date date); + //转换日期格式为yyyy-MM-dd + String formatDate(Date date) ; + //获取时间段内的所有日期(包含起始和结束日) + List getAllDatesBetween(Date start, Date end); } diff --git a/src/main/java/com/example/demo/service/StatisticsService.java b/src/main/java/com/example/demo/service/StatisticsService.java index 603116f..bfdc214 100644 --- a/src/main/java/com/example/demo/service/StatisticsService.java +++ b/src/main/java/com/example/demo/service/StatisticsService.java @@ -1,5 +1,9 @@ package com.example.demo.service; +import com.example.demo.domain.entity.Statistics; + +import java.util.Date; + /** * @program: gold-java * @ClassName StatisticsService @@ -11,4 +15,18 @@ package com.example.demo.service; public interface StatisticsService { + //12点,18点执行定时任务更新当天数据 + public void runHourlyTask(); + //0点执行定时任务更新近一周数据 + public void runDailyTask(); + //查询某地区某天是否已存在统计数据 + public Statistics getExistStatistics(String market,Date date); + + //新增或更新或不修改某地区某天统计数据 + public void saveStatistics(String market, Date date); + //根据地区与日期获取part1(余量属性)统计数据 + public Statistics getStatisticsPart1(String market, Date date); + //根据地区与日期获取part2(余量外属性)统计数据 + public Statistics getStatisticsPart2(String market, Date date); + } diff --git a/src/main/java/com/example/demo/serviceImpl/GeneralServiceImpl.java b/src/main/java/com/example/demo/serviceImpl/GeneralServiceImpl.java index 5c6d8b5..36b9873 100644 --- a/src/main/java/com/example/demo/serviceImpl/GeneralServiceImpl.java +++ b/src/main/java/com/example/demo/serviceImpl/GeneralServiceImpl.java @@ -5,6 +5,12 @@ import com.example.demo.service.GeneralService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; import java.util.List; /** @@ -32,4 +38,53 @@ public class GeneralServiceImpl implements GeneralService { List list = generalMapper.getPlatform(); return list; } + + /* + 获取昨天的日期 + */ + @Override + public Date getYesterday() { + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_YEAR, -1); //当前天数-1 + return getStartOfDay(cal.getTime()); //昨天的00:00:00 + } + /* + 获取某天的开始时间(00:00:00) + */ + @Override + public Date getStartOfDay(Date date) { + LocalDateTime localDate = date.toInstant() + .atZone(ZoneId.systemDefault()) // 转换为本地时区 + .toLocalDateTime() + .with(LocalTime.MIN); // 设置时间为当天 00:00:00 + return Date.from(localDate.atZone(ZoneId.systemDefault()).toInstant()); + } + /* + 转换日期格式为yyyy-MM-dd + */ + @Override + public String formatDate(Date date) { + return date.toInstant() + .atZone(ZoneId.systemDefault()) + .format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE); // 输出格式如 "2025-10-01" + } + /* + 获取时间段内的所有日期(包含起始和结束日) + */ + @Override + public List getAllDatesBetween(Date start, Date end) { + List dates = new ArrayList<>(); + //初始化日历对象 + Calendar tempStart = Calendar.getInstance(); + tempStart.setTime(start); + Calendar tempEnd = Calendar.getInstance(); + tempEnd.setTime(end); + + while (!tempStart.after(tempEnd)) { + dates.add(tempStart.getTime()); // 将当前日期添加到列表中 + tempStart.add(Calendar.DAY_OF_YEAR, 1); // 每次增加一天 + } + + return dates; + } } diff --git a/src/main/java/com/example/demo/serviceImpl/StatisticsServiceImpl.java b/src/main/java/com/example/demo/serviceImpl/StatisticsServiceImpl.java index a54bab7..b870f8f 100644 --- a/src/main/java/com/example/demo/serviceImpl/StatisticsServiceImpl.java +++ b/src/main/java/com/example/demo/serviceImpl/StatisticsServiceImpl.java @@ -1,8 +1,21 @@ 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.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.util.*; + /** * @program: gold-java * @ClassName StatisticsServiceImpl @@ -14,4 +27,213 @@ import org.springframework.stereotype.Service; @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点执行定时任务更新当天数据 + */ + @Override + @Scheduled(cron = "0 0 12,18 * * ?") + public void runHourlyTask() { + Date today = new Date(); //取当天日期 + for(String market : generalService.getMarket()){ + saveStatistics(market,today); + } + } + /* + 0点执行定时任务更新近一周数据 + */ + @Override + @Scheduled(cron = "0 0 0 * * ?") + public void runDailyTask() { + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_YEAR, -7); // 一周前 + Date startDate = cal.getTime(); + Date endDate = generalService.getYesterday(); // 昨天 + //近一周的日期列表 + List dateList =generalService.getAllDatesBetween(startDate, endDate); + + for (Date date : dateList) { + for (String market : generalService.getMarket()) { + saveStatistics(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())); + } + /* + 新增或更新或不修改某地区某天统计数据 + */ + @Override + public void saveStatistics(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{ + log.atInfo().log("数据未发生改变"); + } + } + } + + //根据地区与日期获取part1(余量属性)统计数据 + @Override + public Statistics getStatisticsPart1(String market, Date date) { + //初始化Statistics对象 + Statistics statistics = new Statistics(); + statistics.setMarket(market); + //计算属性 + //当前金币余量 + Integer currentGold = statisticsMapper.sumCurrentPermanentGold(market)+ + statisticsMapper.sumCurrentFreeJune( market)+ + statisticsMapper.sumCurrentFreeDecember(market)+ + statisticsMapper.sumCurrentTaskGold( market); + statistics.setCurrentGold(currentGold); + //当前永久金币 + 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) { + //把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(date); + //计算属性 + //充值相关-当日充值(永久+免费) + 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; + } + /* + * 判断两个统计对象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()); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 6d9081f..6d2229c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,7 +4,7 @@ spring: fail-on-unknown-properties: false datasource: mysql1: - jdbc-url: jdbc:mysql://localhost:3306/hwgold?serverTimezone=Asia/Shanghai + jdbc-url: jdbc:mysql://192.168.8.220:3306/hwgold?serverTimezone=Asia/Shanghai username: hwgold password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver @@ -91,7 +91,7 @@ upload: server: - port: 8080 + port: 8081 logging: level: diff --git a/src/main/resources/mapper/StatisticsMapper.xml b/src/main/resources/mapper/StatisticsMapper.xml new file mode 100644 index 0000000..4e77423 --- /dev/null +++ b/src/main/resources/mapper/StatisticsMapper.xml @@ -0,0 +1,102 @@ + + + + + + INSERT INTO statistics ( + market, current_datetime, + recharge, money, + consume_permanent, consume_free_june, + consume_free_december, consume_task, + refund_permanent, refund_free_june, + refund_free_december,refund_task, + recharge_num, first_recharge + ) VALUES ( + #{market}, #{currentDatetime}, + #{recharge}, #{money}, + #{consumePermanent}, #{consumeFreeJune}, + #{consumeFreeDecember}, #{consumeTask}, + #{refundPermanent}, #{refundFreeJune}, + #{refundFreeDecember}, #{refundTask}, + #{rechargeNum}, #{firstRecharge} + ) + + + + UPDATE statistics + SET + recharge = #{recharge}, + money = #{money}, + consume_permanent = #{consumePermanent}, + consume_free_june = #{consumeFreeJune}, + consume_free_december = #{consumeFreeDecember}, + consume_task = #{consumeTask}, + refund_permanent = #{refundPermanent}, + refund_free_june = #{refundFreeJune}, + refund_free_december = #{refundFreeDecember}, + refund_task = #{refundTask}, + recharge_num = #{rechargeNum}, + first_recharge = #{firstRecharge}, + WHERE id = #{id} + + + + + + + + + + + + +