Forráskód Böngészése

新增随机红包功能

lmx 5 napja
szülő
commit
1712514d8c

+ 30 - 39
fs-admin/src/main/java/com/fs/web/controller/system/SysConfigController.java

@@ -30,13 +30,10 @@ import com.fs.system.service.ISysConfigService;
 
 /**
  * 参数配置 信息操作处理
- *
-
  */
 @RestController
 @RequestMapping("/system/config")
-public class SysConfigController extends BaseController
-{
+public class SysConfigController extends BaseController {
     @Autowired
     private ISysConfigService configService;
     @Autowired
@@ -47,8 +44,7 @@ public class SysConfigController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:config:list')")
     @GetMapping("/list")
-    public TableDataInfo list(SysConfig config)
-    {
+    public TableDataInfo list(SysConfig config) {
         startPage();
         List<SysConfig> list = configService.selectConfigList(config);
         return getDataTable(list);
@@ -57,8 +53,7 @@ public class SysConfigController extends BaseController
     @Log(title = "参数管理", businessType = BusinessType.EXPORT)
     @PreAuthorize("@ss.hasPermi('system:config:export')")
     @GetMapping("/export")
-    public AjaxResult export(SysConfig config)
-    {
+    public AjaxResult export(SysConfig config) {
         List<SysConfig> list = configService.selectConfigList(config);
         ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
         return util.exportExcel(list, "参数数据");
@@ -69,8 +64,7 @@ public class SysConfigController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:config:query')")
     @GetMapping(value = "/{configId}")
-    public AjaxResult getInfo(@PathVariable Long configId)
-    {
+    public AjaxResult getInfo(@PathVariable Long configId) {
         return AjaxResult.success(configService.selectConfigById(configId));
     }
 
@@ -78,8 +72,7 @@ public class SysConfigController extends BaseController
      * 根据参数键名查询参数值
      */
     @GetMapping(value = "/configKey/{configKey}")
-    public AjaxResult getConfigKey(@PathVariable String configKey)
-    {
+    public AjaxResult getConfigKey(@PathVariable String configKey) {
         return AjaxResult.success(configService.selectConfigByKey(configKey));
     }
 
@@ -90,10 +83,8 @@ public class SysConfigController extends BaseController
     @Log(title = "参数管理", businessType = BusinessType.INSERT)
     @PostMapping
     @RepeatSubmit
-    public AjaxResult add(@Validated @RequestBody SysConfig config)
-    {
-        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
-        {
+    public AjaxResult add(@Validated @RequestBody SysConfig config) {
+        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
             return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
         }
         config.setCreateBy(getUsername());
@@ -106,10 +97,8 @@ public class SysConfigController extends BaseController
     @PreAuthorize("@ss.hasPermi('system:config:edit')")
     @Log(title = "参数管理", businessType = BusinessType.UPDATE)
     @PutMapping
-    public AjaxResult edit(@Validated @RequestBody SysConfig config)
-    {
-        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
-        {
+    public AjaxResult edit(@Validated @RequestBody SysConfig config) {
+        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
             return AjaxResult.error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
         }
         config.setUpdateBy(getUsername());
@@ -122,8 +111,7 @@ public class SysConfigController extends BaseController
     @PreAuthorize("@ss.hasPermi('system:config:remove')")
     @Log(title = "参数管理", businessType = BusinessType.DELETE)
     @DeleteMapping("/{configIds}")
-    public AjaxResult remove(@PathVariable Long[] configIds)
-    {
+    public AjaxResult remove(@PathVariable Long[] configIds) {
         configService.deleteConfigByIds(configIds);
         return success();
     }
@@ -134,50 +122,53 @@ public class SysConfigController extends BaseController
     @PreAuthorize("@ss.hasPermi('system:config:remove')")
     @Log(title = "参数管理", businessType = BusinessType.CLEAN)
     @DeleteMapping("/refreshCache")
-    public AjaxResult refreshCache()
-    {
+    public AjaxResult refreshCache() {
         configService.resetConfigCache();
         return AjaxResult.success();
     }
 
     @GetMapping(value = "/getConfigByKey/{configKey}")
-    public AjaxResult getConfigByKey(@PathVariable String configKey)
-    {
-        SysConfig config=configService.selectConfigByConfigKey(configKey);
+    public AjaxResult getConfigByKey(@PathVariable String configKey) {
+        SysConfig config = configService.selectConfigByConfigKey(configKey);
         return AjaxResult.success(config);
     }
 
     @PostMapping(value = "/updateConfigByKey")
     @Log(title = "更改参数", businessType = BusinessType.UPDATE)
     @RepeatSubmit
-    public AjaxResult updateConfigByKey(@Validated @RequestBody SysConfig config)
-    {
+    public AjaxResult updateConfigByKey(@Validated @RequestBody SysConfig config) {
         config.setCreateBy(SecurityUtils.getUsername());
-        return toAjax(configService.updateConfig(config));
+        //修复只能更新的BUG
+        if (null != config.getConfigId()) {
+            return toAjax(configService.updateConfig(config));
+        } else {
+            return toAjax(configService.insertConfig(config));
+        }
+
     }
 
 
     /**
      * 启用-关闭小程序销售管理
+     *
      * @param bock
      * @return
      */
     @GetMapping("/updateIsTownOn")
-    public R queryIsTownOn(String bock, String appId)
-    {
-        String key = appId+"start_status_001";
+    public R queryIsTownOn(String bock, String appId) {
+        String key = appId + "start_status_001";
         String start = redisCache.getCacheObject(key);
-        if (ObjectUtil.isNotEmpty(bock)){
-            if (bock.equals("001")){
-                redisCache.setCacheObject(key,bock);
+        if (ObjectUtil.isNotEmpty(bock)) {
+            if (bock.equals("001")) {
+                redisCache.setCacheObject(key, bock);
                 return R.ok("调整成功");
-            }else if (bock.equals("002")){
-                redisCache.setCacheObject(key,bock);
+            } else if (bock.equals("002")) {
+                redisCache.setCacheObject(key, bock);
                 return R.ok("调整成功");
             }
 
         }
-        return R.ok().put("date",start);
+        return R.ok().put("date", start);
     }
 
 }

+ 19 - 0
fs-service/src/main/java/com/fs/course/config/RandomRedPacketConfig.java

@@ -0,0 +1,19 @@
+package com.fs.course.config;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author MixLiu
+ * @date 2025/11/27 下午2:07)
+ */
+@Data
+public class RandomRedPacketConfig {
+    /**
+     * 是否开启随机红包
+     */
+    private Boolean enableRandomRedpacket;
+
+    private List<RandomRedPacketRule> rules;
+}

+ 28 - 0
fs-service/src/main/java/com/fs/course/config/RandomRedPacketRule.java

@@ -0,0 +1,28 @@
+package com.fs.course.config;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author MixLiu
+ * @date 2025/11/27 下午2:08)
+ */
+
+@Data
+public class RandomRedPacketRule {
+    /**
+     * 最小金额
+     */
+    private BigDecimal minAmount;
+
+    /**
+     * 最大金额
+     */
+    private BigDecimal maxAmount;
+
+    /**
+     * 权重
+     */
+    private Integer weight;
+}

+ 6 - 0
fs-service/src/main/java/com/fs/course/domain/FsUserCourseVideo.java

@@ -78,6 +78,12 @@ public class FsUserCourseVideo extends BaseEntity
     private Integer uploadType;
 
     private BigDecimal redPacketMoney;
+
+    /**
+     * 随机红包配置
+     */
+    private String randomRedPacketRules;
+
     private Long fileSize;//文件大小  字节
     private String fileKey;//文件key 对用存储桶
     private String round;//轮次

+ 1 - 1
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java

@@ -62,7 +62,7 @@ public interface FsUserCourseVideoMapper
     public int updateFsUserCourseVideo(FsUserCourseVideo fsUserCourseVideo);
 
     @Update("<script> " +
-            "update fs_user_course_video set red_packet_money=#{data.redPacketMoney} where course_id=#{data.courseId} " +
+            "update fs_user_course_video set red_packet_money=#{data.redPacketMoney}, random_red_packet_rules = #{data.randomRedPacketRules} where course_id=#{data.courseId} " +
             "</script>")
     public int updateFsUserCourseRedPage(@Param("data") FsUserCourseRedPageParam courseRedPageParam);
 

+ 84 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.course.service.impl;
 
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -33,6 +34,8 @@ import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.company.service.ICompanyService;
 import com.fs.config.cloud.CloudHostProper;
 import com.fs.course.config.CourseConfig;
+import com.fs.course.config.RandomRedPacketConfig;
+import com.fs.course.config.RandomRedPacketRule;
 import com.fs.course.domain.*;
 import com.fs.course.dto.CoursePackageDTO;
 import com.fs.course.mapper.*;
@@ -1444,6 +1447,33 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             amount = redPackage.getRedPacketMoney();
         } else if (video != null) {
             amount = video.getRedPacketMoney();
+            //是否开启了随机红包
+            String json = configService.selectConfigByKey("randomRedpacket:config");
+            if(StringUtils.isNotBlank(json)){
+                RandomRedPacketConfig randomRedPacket = JSONUtil.toBean(json, RandomRedPacketConfig.class);
+                //是否开启拼手气红包
+                if(null != randomRedPacket && randomRedPacket.getEnableRandomRedpacket()){
+                    BigDecimal randomMoney = BigDecimal.ZERO;
+                    //优先读取课程配置随机红包规则
+                    String randomRedPacketRules = video.getRandomRedPacketRules();
+                    if(StringUtils.isNotBlank(randomRedPacketRules) ){
+                        JSONArray array = JSONObject.parseArray(randomRedPacketRules);
+                        List<RandomRedPacketRule> rules = new ArrayList<>();
+                        for (Object o : array) {
+                            rules.add(JSONObject.toJavaObject((JSONObject) o, RandomRedPacketRule.class));
+                        }
+                        randomMoney = getRandomMoneyByRules(rules);
+                    }
+                    //如果课程没有配置 读取后台默认随机规则
+                    else{
+                        randomMoney = getRandomMoneyByRules(randomRedPacket.getRules());
+                    }
+                    //兼容拼手气红包报错情况的发放红包情况
+                    if(BigDecimal.ZERO.compareTo(randomMoney) < 0){
+                        amount = randomMoney;
+                    }
+                }
+            }
         }
 
         // 准备发送红包参数
@@ -3613,6 +3643,60 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         return R.ok();
     }
 
+    /**
+     * 根据匹配规则返回随机红包值(需求是概率独立计算)
+     * @param rules
+     * @return
+     */
+    private BigDecimal getRandomMoneyByRules(List<RandomRedPacketRule> rules) {
+        try {
+
+            if (CollectionUtils.isEmpty(rules)) {
+                logger.error("随机红包规则列表为空,不予处理");
+//            throw new ServiceException("随机红包规则列表为空");
+            }
+            // 计算总权重
+            int totalWeight = rules.stream()
+                    .mapToInt(RandomRedPacketRule::getWeight)
+                    .sum();
+            // 根据权重随机选择规则
+            Random random = new Random();
+            int randomPoint = random.nextInt(totalWeight);
+
+            RandomRedPacketRule selectedRule = null;
+            int currentWeight = 0;
+
+            for (RandomRedPacketRule rule : rules) {
+                currentWeight += rule.getWeight();
+                if (randomPoint < currentWeight) {
+                    selectedRule = rule;
+                    break;
+                }
+            }
+
+            // 如果因为计算精度问题没有选中规则,默认选第一个
+            if (selectedRule == null) {
+                selectedRule = rules.get(0);
+            }
+            // 在选中规则的范围内生成随机金额
+            BigDecimal maxAmount = selectedRule.getMaxAmount();
+            BigDecimal minAmount = selectedRule.getMinAmount();
+            // 如果最大最小金额相等,直接返回该金额
+            if (maxAmount.compareTo(minAmount) == 0) {
+                return maxAmount;
+            }
+            // 生成随机金额
+            BigDecimal range = maxAmount.subtract(minAmount);
+            BigDecimal randomValue = range.multiply(BigDecimal.valueOf(random.nextDouble()));
+            BigDecimal result = minAmount.add(randomValue);
+            // 保留两位小数,四舍五入
+            return result.setScale(2, RoundingMode.HALF_UP);
+        } catch (Exception e) {
+            logger.error("获取拼手气红包金额异常:{}",rules, e);
+        }
+
+        return BigDecimal.ZERO;
+    }
 
 
 }

+ 6 - 0
fs-service/src/main/java/com/fs/course/vo/FsUserCourseVideoQVO.java

@@ -68,6 +68,12 @@ public class FsUserCourseVideoQVO extends BaseEntity {
     private String lineThree; //线路三 华为云obs
     private Integer uploadType;
     private String redPacketMoney;
+
+    /**
+     * 随机红包配置
+     */
+    private String randomRedPacketRules;
+
     private Long fileSize;//文件大小  字节
     private String fileKey;//文件key 对用存储桶
     private String round;//轮次

+ 5 - 0
fs-service/src/main/java/com/fs/qw/param/FsUserCourseRedPageParam.java

@@ -11,5 +11,10 @@ public class FsUserCourseRedPageParam {
     private Long courseId;
     //红包
     private BigDecimal redPacketMoney;
+
+    /**
+     * 新增配置 随机红包配置
+     */
+    private String randomRedPacketRules;
 }
 

+ 1 - 0
fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -218,6 +218,7 @@
             <if test="lineThree != null">line_three = #{lineThree},</if>
             <if test="uploadType != null">upload_type = #{uploadType},</if>
             <if test="redPacketMoney != null">red_packet_money = #{redPacketMoney},</if>
+            <if test="randomRedPacketRules != null">random_red_packet_rules = #{randomRedPacketRules},</if>
             <if test="fileSize != null">file_size = #{fileSize},</if>
             <if test="fileKey != null">file_key = #{fileKey},</if>
             <if test="round != null">round = #{round},</if>