|  | @@ -1,18 +1,21 @@
 | 
	
		
			
				|  |  |  package com.fs.course.service.impl;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import java.text.SimpleDateFormat;
 | 
	
		
			
				|  |  | -import java.util.Collections;
 | 
	
		
			
				|  |  | -import java.util.Date;
 | 
	
		
			
				|  |  | -import java.util.List;
 | 
	
		
			
				|  |  | +import java.util.*;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import com.alibaba.fastjson.JSONObject;
 | 
	
		
			
				|  |  |  import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 | 
	
		
			
				|  |  |  import com.fs.common.exception.CustomException;
 | 
	
		
			
				|  |  |  import com.fs.common.utils.DateUtils;
 | 
	
		
			
				|  |  |  import com.fs.common.utils.DictUtils;
 | 
	
		
			
				|  |  |  import com.fs.company.cache.ICompanyCacheService;
 | 
	
		
			
				|  |  |  import com.fs.course.param.FsCourseTrafficLogParam;
 | 
	
		
			
				|  |  | +import com.fs.course.param.InternetTrafficParam;
 | 
	
		
			
				|  |  | +import com.fs.course.param.TrafficRecord;
 | 
	
		
			
				|  |  |  import com.fs.course.vo.FsCourseTrafficLogListVO;
 | 
	
		
			
				|  |  |  import com.fs.store.service.cache.IFsUserCourseCacheService;
 | 
	
		
			
				|  |  | +import com.fs.system.domain.SysConfig;
 | 
	
		
			
				|  |  | +import com.fs.system.service.ISysConfigService;
 | 
	
		
			
				|  |  |  import com.hc.openapi.tool.util.StringUtils;
 | 
	
		
			
				|  |  |  import lombok.extern.slf4j.Slf4j;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Autowired;
 | 
	
	
		
			
				|  | @@ -33,7 +36,8 @@ public class FsCourseTrafficLogServiceImpl implements IFsCourseTrafficLogService
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private FsCourseTrafficLogMapper fsCourseTrafficLogMapper;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private ISysConfigService iSysConfigService;
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private ICompanyCacheService companyCacheService;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -202,6 +206,164 @@ public class FsCourseTrafficLogServiceImpl implements IFsCourseTrafficLogService
 | 
	
		
			
				|  |  |          return fsCourseTrafficLogListVOS;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void updateTrafficStatus(InternetTrafficParam internetTrafficParam) {
 | 
	
		
			
				|  |  | +        System.out.println("开始处理流量充值...");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 计算充值对应的流量
 | 
	
		
			
				|  |  | +        double account = Double.parseDouble(internetTrafficParam.getAccount());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        SysConfig config = iSysConfigService.selectConfigByConfigKey("statis.config");
 | 
	
		
			
				|  |  | +        JSONObject jsonObject = JSONObject.parseObject(config.getConfigValue());
 | 
	
		
			
				|  |  | +        float trafficPrice = jsonObject.getFloatValue("trafficPrice");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        double trafficGB = account / trafficPrice;
 | 
	
		
			
				|  |  | +        long trafficKB = (long) (trafficGB * 1024 * 1024);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        System.out.println("充值金额:" + account + " 元,对应可用流量:" + trafficKB + " KB");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        long updatedTrafficKB = 0L;
 | 
	
		
			
				|  |  | +        int pageSize = 1000;  // 每次查询1000条
 | 
	
		
			
				|  |  | +        int pageNum = 0;      // 分页页码
 | 
	
		
			
				|  |  | +        int loopCount = 0;    // 查询次数
 | 
	
		
			
				|  |  | +        int maxLoop = 20;     // 最大循环次数
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        List<Long> idsToUpdate = new ArrayList<>();       // 用于更新状态为1的ID
 | 
	
		
			
				|  |  | +        Set<Long> processedIds = new HashSet<>();         // 用于去重
 | 
	
		
			
				|  |  | +        long remainingTrafficKB = trafficKB;              // 还需补充的流量
 | 
	
		
			
				|  |  | +        long totalInternetTrafficRemaining = 0L;          // 记录未处理的流量总和
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 第一阶段:处理需要用于充值的记录
 | 
	
		
			
				|  |  | +        while (updatedTrafficKB < trafficKB && loopCount < maxLoop) {
 | 
	
		
			
				|  |  | +            loopCount++;
 | 
	
		
			
				|  |  | +            int offset = pageNum * pageSize;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 查询当前分页的数据
 | 
	
		
			
				|  |  | +            List<TrafficRecord> trafficRecords =
 | 
	
		
			
				|  |  | +                    fsCourseTrafficLogMapper.findUnusedRecordsWithTraffic(
 | 
	
		
			
				|  |  | +                            internetTrafficParam.getCompanyId(), offset, pageSize);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (trafficRecords.isEmpty()) {
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 处理当前批次的数据
 | 
	
		
			
				|  |  | +            for (TrafficRecord record : trafficRecords) {
 | 
	
		
			
				|  |  | +                Long logId = record.getLogId();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (processedIds.contains(logId)) {
 | 
	
		
			
				|  |  | +                    continue;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (updatedTrafficKB < trafficKB) {
 | 
	
		
			
				|  |  | +                    updatedTrafficKB += record.getInternetTraffic();
 | 
	
		
			
				|  |  | +                    idsToUpdate.add(logId);
 | 
	
		
			
				|  |  | +                    remainingTrafficKB = Math.max(0, trafficKB - updatedTrafficKB);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                processedIds.add(logId);
 | 
	
		
			
				|  |  | +                totalInternetTrafficRemaining += record.getInternetTraffic();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                Thread.sleep(100);
 | 
	
		
			
				|  |  | +            } catch (InterruptedException e) {
 | 
	
		
			
				|  |  | +                Thread.currentThread().interrupt();
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            pageNum++;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 第二阶段:将所有未处理的记录状态改为3
 | 
	
		
			
				|  |  | +        List<Long> allUnprocessedIds = new ArrayList<>();
 | 
	
		
			
				|  |  | +        pageNum = 0;  // 重置分页
 | 
	
		
			
				|  |  | +        boolean hasMore = true;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        while (hasMore && loopCount < maxLoop * 2) {  // 扩大循环次数限制
 | 
	
		
			
				|  |  | +            loopCount++;
 | 
	
		
			
				|  |  | +            int offset = pageNum * pageSize;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            List<TrafficRecord> allRecords =
 | 
	
		
			
				|  |  | +                    fsCourseTrafficLogMapper.findUnusedRecordsWithTraffic(
 | 
	
		
			
				|  |  | +                            internetTrafficParam.getCompanyId(), offset, pageSize);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (allRecords.isEmpty()) {
 | 
	
		
			
				|  |  | +                hasMore = false;
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for (TrafficRecord record : allRecords) {
 | 
	
		
			
				|  |  | +                Long logId = record.getLogId();
 | 
	
		
			
				|  |  | +                if (!idsToUpdate.contains(logId)) {  // 不是已处理的记录
 | 
	
		
			
				|  |  | +                    allUnprocessedIds.add(logId);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            pageNum++;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 更新数据库状态
 | 
	
		
			
				|  |  | +        if (!idsToUpdate.isEmpty()) {
 | 
	
		
			
				|  |  | +            fsCourseTrafficLogMapper.updateStatusByIds(idsToUpdate, 1);
 | 
	
		
			
				|  |  | +            System.out.println("共更新状态为1的记录数:" + idsToUpdate.size());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (!allUnprocessedIds.isEmpty()) {
 | 
	
		
			
				|  |  | +            fsCourseTrafficLogMapper.updateStatusByIds(allUnprocessedIds, 3);
 | 
	
		
			
				|  |  | +            System.out.println("共更新状态为3的记录数:" + allUnprocessedIds.size());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 剩余的计算和输出逻辑保持不变...
 | 
	
		
			
				|  |  | +        Long count = fsCourseTrafficLogMapper.findRecordsNum(internetTrafficParam.getCompanyId());
 | 
	
		
			
				|  |  | +        long overflowTrafficKB = Math.max(0, updatedTrafficKB - trafficKB) + count;
 | 
	
		
			
				|  |  | +        if (overflowTrafficKB > 0) {
 | 
	
		
			
				|  |  | +            System.out.println("已使用流量超过充值流量,超出部分:" + overflowTrafficKB + " KB");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        System.out.println("充值总流量:" + trafficKB + " KB");
 | 
	
		
			
				|  |  | +        System.out.println("已使用流量:" + updatedTrafficKB + " KB");
 | 
	
		
			
				|  |  | +        long finalRemainingTrafficKB = Math.max(0, trafficKB - updatedTrafficKB);
 | 
	
		
			
				|  |  | +        System.out.println("最终剩余流量:" + finalRemainingTrafficKB + " KB");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 系统配置更新逻辑保持不变...
 | 
	
		
			
				|  |  | +        SysConfig sysConfig = iSysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
 | 
	
		
			
				|  |  | +        String trafficCount = finalRemainingTrafficKB == 0 ?
 | 
	
		
			
				|  |  | +                "-" + overflowTrafficKB : String.valueOf(finalRemainingTrafficKB);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (ObjectUtils.isEmpty(sysConfig)) {
 | 
	
		
			
				|  |  | +            sysConfig = new SysConfig();
 | 
	
		
			
				|  |  | +            sysConfig.setConfigKey("redPacket.Traffic.config");
 | 
	
		
			
				|  |  | +            sysConfig.setConfigName("红包流量配置");
 | 
	
		
			
				|  |  | +            sysConfig.setConfigValue(trafficCount);
 | 
	
		
			
				|  |  | +            iSysConfigService.insertConfig(sysConfig);
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            sysConfig.setConfigValue(trafficCount);
 | 
	
		
			
				|  |  | +            iSysConfigService.updateConfig(sysConfig);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void sumTrafficlog() {
 | 
	
		
			
				|  |  | +        SysConfig sysConfig = iSysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
 | 
	
		
			
				|  |  | +        Date date = new Date();
 | 
	
		
			
				|  |  | +        Long count = fsCourseTrafficLogMapper.findRecordsNumBYD(date);
 | 
	
		
			
				|  |  | +        List<Long> ids = fsCourseTrafficLogMapper.findRecordsNumByIds(date);
 | 
	
		
			
				|  |  | +        if (count<=0){
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (ObjectUtils.isEmpty(sysConfig)){
 | 
	
		
			
				|  |  | +            sysConfig = new SysConfig();
 | 
	
		
			
				|  |  | +            sysConfig.setConfigKey("redPacket.Traffic.config");
 | 
	
		
			
				|  |  | +            sysConfig.setConfigName("红包流量配置");
 | 
	
		
			
				|  |  | +            sysConfig.setConfigValue("-"+count);
 | 
	
		
			
				|  |  | +            iSysConfigService.insertConfig(sysConfig);
 | 
	
		
			
				|  |  | +        }else {
 | 
	
		
			
				|  |  | +            sysConfig.setConfigValue(String.valueOf((Long.parseLong(sysConfig.getConfigValue())-count)));
 | 
	
		
			
				|  |  | +            iSysConfigService.updateConfig(sysConfig);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        fsCourseTrafficLogMapper.updateStatusByIds(ids,2);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      private static String formatDuration(long millis) {
 | 
	
		
			
				|  |  |          long seconds = millis / 1000;
 | 
	
		
			
				|  |  |          long minutes = seconds / 60;
 |