2 コミット b24078ea2c ... 7c3ec8d784

作者 SHA1 メッセージ 日付
  yfh 7c3ec8d784 Merge remote-tracking branch 'origin/master' 1 日 前
  yfh 7590698b9a 1、红包流量充值业务逻辑梳理 1 日 前

+ 8 - 0
fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java

@@ -3,6 +3,8 @@ package com.fs.api.controller;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.statis.StatisticsRedisConstant;
 import com.fs.statis.dto.*;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import com.fs.common.core.domain.R;
@@ -20,6 +22,9 @@ import static com.fs.statis.StatisticsRedisConstant.*;
 public class IndexStatisticsController {
     @Autowired
     private RedisCache redisCache;
+
+    @Autowired
+    private ISysConfigService sysConfigService;
     /**
      * 分析概览
      */
@@ -59,6 +64,9 @@ public class IndexStatisticsController {
     @GetMapping("/trafficLog")
     public R getTrafficLog(){
         TrafficLogDTO trafficLogDTO = redisCache.getCacheObject(DATA_OVERVIEW_TRAFFIC_LOG);
+        SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
+        String configValue = sysConfig.getConfigValue();
+        trafficLogDTO.setTraffic(configValue);
         return R.ok().put("data",trafficLogDTO);
     }
 

+ 17 - 0
fs-admin/src/main/java/com/fs/course/controller/FsCourseTrafficLogController.java

@@ -14,6 +14,7 @@ import com.fs.core.web.service.TokenService;
 import com.fs.course.domain.FsCourseTrafficLog;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.param.FsCourseTrafficLogParam;
+import com.fs.course.param.InternetTrafficParam;
 import com.fs.course.service.IFsCourseTrafficLogService;
 import com.fs.course.service.IFsUserCourseService;
 import com.fs.course.vo.FsCourseTrafficLogListVO;
@@ -26,7 +27,9 @@ import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.time.YearMonth;
 import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 
 /**
@@ -140,4 +143,18 @@ public class FsCourseTrafficLogController extends BaseController
         List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id,loginUser.getUser().getUserId());
         return R.ok().put("list", optionsVOS);
     }
+
+    /**
+     * 充值流量
+     *
+     * @param internetTrafficParam
+     * @return
+     */
+    @PostMapping(value = "/rechargeTraffic")
+    public R rechargeTraffic(@RequestBody InternetTrafficParam internetTrafficParam) {
+
+        fsCourseTrafficLogService.updateTrafficStatus(internetTrafficParam);
+        return R.ok().put("data", null);  // 返回计算结果
+    }
+
 }

+ 10 - 1
fs-admin/src/test/java/com/fs/course/controller/AdHtmlClickLogServiceImplTest.java

@@ -2,6 +2,8 @@ package com.fs.course.controller;
 
 
 import com.fs.FSAdminApplication;
+import com.fs.course.param.InternetTrafficParam;
+import com.fs.course.service.IFsCourseTrafficLogService;
 import lombok.extern.slf4j.Slf4j;
 import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
@@ -14,6 +16,13 @@ import java.math.BigDecimal;
 @SpringBootTest(classes = FSAdminApplication.class)
 @Slf4j
 public class AdHtmlClickLogServiceImplTest {
+    @Autowired
+    private IFsCourseTrafficLogService fsCourseTrafficLogService;
 
-
+    @Test
+    public void test(){
+        InternetTrafficParam internetTrafficParam = new InternetTrafficParam();
+        internetTrafficParam.setAccount("1");
+        fsCourseTrafficLogService.updateTrafficStatus(internetTrafficParam);
+    }
 }

+ 43 - 0
fs-service-system/src/main/java/com/fs/course/mapper/FsCourseTrafficLogMapper.java

@@ -3,10 +3,12 @@ package com.fs.course.mapper;
 import java.util.List;
 import com.fs.course.domain.FsCourseTrafficLog;
 import com.fs.course.param.FsCourseTrafficLogParam;
+import com.fs.course.param.TrafficRecord;
 import com.fs.course.vo.FsCourseTrafficLogListVO;
 import com.fs.statis.dto.TrafficLogDTO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 
 /**
  * 短链课程流量记录Mapper接口
@@ -96,4 +98,45 @@ public interface FsCourseTrafficLogMapper
     Long getYesterdayTrafficLog();
     Long getYesterdayTrafficLogCompanyId(@Param("companyId") Long companyId,@Param("companyUserId") Long companyUserId);
 
+
+
+    // 按创建时间查询未使用的流量记录(用于分批更新)
+    @Select("<script>" +
+            "SELECT COALESCE(sum(internet_traffic), 0) FROM fs_course_traffic_log " +
+            "WHERE status = 0" +
+            "<if test='companyId != null'>AND company_id = #{companyId}</if> " +
+            "</script>")
+    Long findRecordsNum(@Param("companyId") Long companyId);
+
+    // 批量更新状态
+    @Update("<script>" +
+            "UPDATE fs_course_traffic_log SET status = 1 WHERE log_id IN " +
+            "<foreach item='id' collection='ids' open='(' separator=',' close=')'>" +
+            "#{id}" +
+            "</foreach>" +
+            "</script>")
+    int updateStatusByIds(@Param("ids") List<Long> ids);
+
+    @Select("<script>" +
+            "SELECT internet_traffic FROM fs_course_traffic_log WHERE log_id IN " +
+            "<foreach item='id' collection='ids' open='(' separator=',' close=')'>" +
+            "#{id}" +
+            "</foreach>" +
+            "</script>")
+    List<Long> getTrafficByIds(@Param("ids") List<Long> ids);
+
+    // 新增带流量字段的记录查询(按公司ID)
+    @Select("<script>" +
+            "SELECT log_id, internet_traffic FROM fs_course_traffic_log " +
+            "WHERE status = 0" +
+            "<if test='companyId != null'>AND company_id = #{companyId}</if> " +
+            "ORDER BY create_time ASC " +
+            "LIMIT #{offset}, #{pageSize}" +
+            "</script>")
+    List<TrafficRecord> findUnusedRecordsWithTraffic(
+            @Param("companyId") Long companyId,
+            @Param("offset") int offset,
+            @Param("pageSize") int pageSize);
+
+
 }

+ 20 - 0
fs-service-system/src/main/java/com/fs/course/param/InternetTrafficParam.java

@@ -0,0 +1,20 @@
+package com.fs.course.param;
+
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.YearMonth;
+
+@Data
+public class InternetTrafficParam {
+
+  /**
+   * 充值金额
+   */
+  public String account;
+
+  /**
+   * 公司id
+   */
+  public Long companyId;
+}

+ 9 - 0
fs-service-system/src/main/java/com/fs/course/param/TrafficRecord.java

@@ -0,0 +1,9 @@
+package com.fs.course.param;
+
+import lombok.Data;
+
+@Data
+public class TrafficRecord {
+    private Long logId;
+    private Long internetTraffic; // 单位:KB
+}

+ 3 - 0
fs-service-system/src/main/java/com/fs/course/service/IFsCourseTrafficLogService.java

@@ -3,6 +3,7 @@ package com.fs.course.service;
 import java.util.List;
 import com.fs.course.domain.FsCourseTrafficLog;
 import com.fs.course.param.FsCourseTrafficLogParam;
+import com.fs.course.param.InternetTrafficParam;
 import com.fs.course.vo.FsCourseTrafficLogListVO;
 
 /**
@@ -64,4 +65,6 @@ public interface IFsCourseTrafficLogService
 
     List<FsCourseTrafficLogListVO> selectTrafficByCompany(FsCourseTrafficLogParam param);
     List<FsCourseTrafficLogListVO> selectTrafficNew(FsCourseTrafficLogParam param);
+
+    void updateTrafficStatus(InternetTrafficParam internetTrafficParam);
 }

+ 134 - 2
fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseTrafficLogServiceImpl.java

@@ -1,7 +1,6 @@
 package com.fs.course.service.impl;
 
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
 
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.exception.CustomException;
@@ -9,8 +8,12 @@ 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 org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -32,6 +35,8 @@ public class FsCourseTrafficLogServiceImpl implements IFsCourseTrafficLogService
     @Autowired
     private ICompanyCacheService companyCacheService;
     @Autowired
+    private ISysConfigService iSysConfigService;
+    @Autowired
     private IFsUserCourseCacheService fsUserCourseCacheService;
 
     /**
@@ -93,6 +98,17 @@ public class FsCourseTrafficLogServiceImpl implements IFsCourseTrafficLogService
     public int insertFsCourseTrafficLog(FsCourseTrafficLog fsCourseTrafficLog)
     {
         fsCourseTrafficLog.setCreateTime(DateUtils.getNowDate());
+        SysConfig sysConfig = iSysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
+        if (ObjectUtils.isEmpty(sysConfig)){
+            sysConfig = new SysConfig();
+            sysConfig.setConfigKey("redPacket.Traffic.config");
+            sysConfig.setConfigName("红包流量配置");
+            sysConfig.setConfigValue("-"+fsCourseTrafficLog.getInternetTraffic());
+            iSysConfigService.insertConfig(sysConfig);
+        }else {
+            sysConfig.setConfigValue(String.valueOf((Long.parseLong(sysConfig.getConfigValue())-fsCourseTrafficLog.getInternetTraffic())));
+            iSysConfigService.updateConfig(sysConfig);
+        }
         return fsCourseTrafficLogMapper.insertFsCourseTrafficLog(fsCourseTrafficLog);
     }
 
@@ -167,4 +183,120 @@ public class FsCourseTrafficLogServiceImpl implements IFsCourseTrafficLogService
         }
         return fsCourseTrafficLogListVOS;
     }
+
+    @Override
+    public void updateTrafficStatus(InternetTrafficParam internetTrafficParam) {
+        System.out.println("开始处理流量充值...");
+
+        // 计算充值对应的流量
+        double account = Double.parseDouble(internetTrafficParam.getAccount());
+        double pricePerGB = 0.05;
+        double trafficGB = account / pricePerGB;
+        long trafficKB = (long) (trafficGB * 1024 * 1024);
+
+        System.out.println("充值金额:" + account + " 元,对应可用流量:" + trafficKB + " KB");
+
+        long updatedTrafficKB = 0L;
+        int pageSize = 3;  // 每次查询1000条
+        int pageNum = 0;  // 分页页码
+        int loopCount = 0; // 查询次数
+        int maxLoop = 20;  // 最大循环次数
+
+        List<Long> idsToUpdate = new ArrayList<>();
+        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) {
+                if (updatedTrafficKB >= trafficKB) break;  // 达到目标流量则退出
+
+                Long logId = record.getLogId();
+                if (processedIds.contains(logId)) {
+                    continue; // 如果记录已处理过,则跳过
+                }
+
+                updatedTrafficKB += record.getInternetTraffic();  // 累加已使用的流量
+                idsToUpdate.add(logId);  // 记录需要更新的ID
+                processedIds.add(logId);  // 标记为已处理
+
+                remainingTrafficKB = Math.max(0, trafficKB - updatedTrafficKB);  // 更新剩余流量
+                totalInternetTrafficRemaining += record.getInternetTraffic();  // 累计未处理的流量
+                // 如果剩余流量不足,则停止处理
+                if (remainingTrafficKB == 0) {
+                    break;
+                }
+            }
+
+            // 模拟数据库压力,休眠一段时间
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                break;
+            }
+
+            pageNum++;  // 翻到下一页
+        }
+        // 更新数据库状态
+        if (!idsToUpdate.isEmpty()) {
+            fsCourseTrafficLogMapper.updateStatusByIds(idsToUpdate);
+            System.out.println("共更新状态记录数:" + idsToUpdate.size());
+        } else {
+            System.out.println("没有记录被更新。");
+        }
+
+        // 计算超出充值流量的部分
+        Long count = fsCourseTrafficLogMapper.findRecordsNum(internetTrafficParam.getCompanyId());
+        long overflowTrafficKB = Math.max(0, updatedTrafficKB - trafficKB)+count;
+        if (overflowTrafficKB > 0) {
+            System.out.println("已使用流量超过充值流量,超出部分:" + overflowTrafficKB + " KB");
+        }
+
+        // 输出未处理的流量信息
+        long remainingUnprocessedTrafficKB = totalInternetTrafficRemaining - overflowTrafficKB;
+        if (updatedTrafficKB < trafficKB) {
+            System.out.println("处理完毕,未使用完的剩余流量:" + remainingUnprocessedTrafficKB + " 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 = null;
+        if (finalRemainingTrafficKB==0){
+            trafficCount = "-"+overflowTrafficKB;
+        }else {
+            trafficCount = 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);
+        }
+    }
+
+
+
+
+
 }

+ 4 - 0
fs-service-system/src/main/java/com/fs/statis/dto/TrafficLogDTO.java

@@ -22,4 +22,8 @@ public class TrafficLogDTO implements Serializable {
      * 本月流量
      */
     private Long thisMonth;
+    /**
+     * 剩余流量
+     */
+    private String traffic;
 }