xw 20 часов назад
Родитель
Сommit
141e18a525

+ 37 - 1
fs-admin/src/main/java/com/fs/course/controller/CourseRandomRedPacketController.java

@@ -6,11 +6,15 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.R;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.BusinessType;
 import com.fs.course.config.CourseRandomRedPacketConfig;
 import com.fs.course.config.CourseRandomRedPacketConfig;
+import com.fs.course.param.CourseRandomRedPacketBatchSaveParam;
+import com.fs.course.param.CourseRandomRedPacketCopyParam;
 import com.fs.course.service.ICourseRandomRedPacketService;
 import com.fs.course.service.ICourseRandomRedPacketService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
+import java.util.List;
+
 /**
 /**
  * 课程随机红包配置控制器,对应 fs_user_course.project
  * 课程随机红包配置控制器,对应 fs_user_course.project
  */
  */
@@ -32,7 +36,17 @@ public class CourseRandomRedPacketController extends BaseController {
     }
     }
 
 
     /**
     /**
-     * 修改/保存课程随机红包配置
+     * 查询所有已配置的课程项目
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseRandomRedPacket:query')")
+    @GetMapping("/list")
+    public R listConfiguredProjects() {
+        List<CourseRandomRedPacketConfig> list = courseRandomRedPacketService.listConfiguredProjects();
+        return R.ok().put("data", list);
+    }
+
+    /**
+     * 修改/保存课程随机红包配置(单个项目)
      */
      */
     @PreAuthorize("@ss.hasPermi('course:courseRandomRedPacket:edit')")
     @PreAuthorize("@ss.hasPermi('course:courseRandomRedPacket:edit')")
     @Log(title = "课程随机红包配置", businessType = BusinessType.UPDATE)
     @Log(title = "课程随机红包配置", businessType = BusinessType.UPDATE)
@@ -41,4 +55,26 @@ public class CourseRandomRedPacketController extends BaseController {
         courseRandomRedPacketService.saveConfig(config);
         courseRandomRedPacketService.saveConfig(config);
         return AjaxResult.success();
         return AjaxResult.success();
     }
     }
+
+    /**
+     * 批量保存:同一套配置应用到多个课程项目
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseRandomRedPacket:edit')")
+    @Log(title = "课程随机红包批量配置", businessType = BusinessType.UPDATE)
+    @PostMapping("/batch")
+    public AjaxResult batchSaveConfig(@RequestBody CourseRandomRedPacketBatchSaveParam param) {
+        courseRandomRedPacketService.batchSaveConfig(param);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 复制配置:将源项目配置复制到多个目标项目
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseRandomRedPacket:edit')")
+    @Log(title = "课程随机红包配置复制", businessType = BusinessType.UPDATE)
+    @PostMapping("/copy")
+    public AjaxResult copyConfig(@RequestBody CourseRandomRedPacketCopyParam param) {
+        courseRandomRedPacketService.copyConfig(param);
+        return AjaxResult.success();
+    }
 }
 }

+ 25 - 0
fs-service/src/main/java/com/fs/course/param/CourseRandomRedPacketBatchSaveParam.java

@@ -0,0 +1,25 @@
+package com.fs.course.param;
+
+import com.fs.course.config.CourseRandomRedPacketTier;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 课程随机红包批量保存入参
+ */
+@Data
+public class CourseRandomRedPacketBatchSaveParam {
+
+    /** 课程项目ID列表,对应 fs_user_course.project */
+    private List<Long> projects;
+
+    /** 是否开启随机红包 */
+    private Boolean enableRandom;
+
+    /** 企业白名单,多个企业逗号分隔,ALL代表全部企业可见 */
+    private String companyWhitelist;
+
+    /** 红包档位配置 */
+    private List<CourseRandomRedPacketTier> tiers;
+}

+ 18 - 0
fs-service/src/main/java/com/fs/course/param/CourseRandomRedPacketCopyParam.java

@@ -0,0 +1,18 @@
+package com.fs.course.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 课程随机红包配置复制入参:将源项目配置复制到多个目标项目
+ */
+@Data
+public class CourseRandomRedPacketCopyParam {
+
+    /** 源课程项目ID */
+    private Long sourceProject;
+
+    /** 目标课程项目ID列表 */
+    private List<Long> targetProjects;
+}

+ 18 - 0
fs-service/src/main/java/com/fs/course/service/ICourseRandomRedPacketService.java

@@ -2,8 +2,11 @@ package com.fs.course.service;
 
 
 import com.fs.course.config.CourseRandomRedPacketConfig;
 import com.fs.course.config.CourseRandomRedPacketConfig;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.param.CourseRandomRedPacketBatchSaveParam;
+import com.fs.course.param.CourseRandomRedPacketCopyParam;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
+import java.util.List;
 
 
 /**
 /**
  * 课程随机红包配置服务接口
  * 课程随机红包配置服务接口
@@ -20,6 +23,21 @@ public interface ICourseRandomRedPacketService {
      */
      */
     void saveConfig(CourseRandomRedPacketConfig config);
     void saveConfig(CourseRandomRedPacketConfig config);
 
 
+    /**
+     * 批量保存:同一套配置应用到多个课程项目
+     */
+    void batchSaveConfig(CourseRandomRedPacketBatchSaveParam param);
+
+    /**
+     * 复制配置:将源项目配置复制到多个目标项目
+     */
+    void copyConfig(CourseRandomRedPacketCopyParam param);
+
+    /**
+     * 查询所有已配置的课程项目
+     */
+    List<CourseRandomRedPacketConfig> listConfiguredProjects();
+
     /**
     /**
      * 计算最终红包金额:优先使用课程红包配置,异常时返回基础金额兜底
      * 计算最终红包金额:优先使用课程红包配置,异常时返回基础金额兜底
      *
      *

+ 105 - 1
fs-service/src/main/java/com/fs/course/service/impl/CourseRandomRedPacketServiceImpl.java

@@ -11,6 +11,8 @@ import com.fs.course.config.RandomRedPacketRule;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.mapper.FsUserCourseMapper;
 import com.fs.course.mapper.FsUserCourseMapper;
+import com.fs.course.param.CourseRandomRedPacketBatchSaveParam;
+import com.fs.course.param.CourseRandomRedPacketCopyParam;
 import com.fs.course.service.ICourseRandomRedPacketService;
 import com.fs.course.service.ICourseRandomRedPacketService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
 import com.fs.system.service.ISysConfigService;
@@ -65,9 +67,78 @@ public class CourseRandomRedPacketServiceImpl implements ICourseRandomRedPacketS
 
 
     @Override
     @Override
     public void saveConfig(CourseRandomRedPacketConfig config) {
     public void saveConfig(CourseRandomRedPacketConfig config) {
-        if (config == null || config.getProject() == null) {
+        validateConfig(config);
+        doSaveConfig(config);
+    }
+
+    @Override
+    public void batchSaveConfig(CourseRandomRedPacketBatchSaveParam param) {
+        if (param == null || CollectionUtils.isEmpty(param.getProjects())) {
             throw new IllegalArgumentException("课程项目不能为空");
             throw new IllegalArgumentException("课程项目不能为空");
         }
         }
+        CourseRandomRedPacketConfig template = buildConfigFromBatchParam(param);
+        validateConfig(template);
+        for (Long project : param.getProjects()) {
+            if (project == null) {
+                continue;
+            }
+            CourseRandomRedPacketConfig config = copyConfigFields(template);
+            config.setProject(project);
+            doSaveConfig(config);
+        }
+    }
+
+    @Override
+    public void copyConfig(CourseRandomRedPacketCopyParam param) {
+        if (param == null || param.getSourceProject() == null) {
+            throw new IllegalArgumentException("源课程项目不能为空");
+        }
+        if (CollectionUtils.isEmpty(param.getTargetProjects())) {
+            throw new IllegalArgumentException("目标课程项目不能为空");
+        }
+        CourseRandomRedPacketConfig sourceConfig = getConfigByProject(param.getSourceProject());
+        if (sourceConfig == null) {
+            throw new IllegalArgumentException("源课程项目未配置红包规则");
+        }
+        for (Long targetProject : param.getTargetProjects()) {
+            if (targetProject == null || targetProject.equals(param.getSourceProject())) {
+                continue;
+            }
+            CourseRandomRedPacketConfig config = copyConfigFields(sourceConfig);
+            config.setProject(targetProject);
+            doSaveConfig(config);
+        }
+    }
+
+    @Override
+    public List<CourseRandomRedPacketConfig> listConfiguredProjects() {
+        SysConfig query = new SysConfig();
+        query.setConfigKey(CONFIG_KEY_PREFIX);
+        List<SysConfig> configList = configService.selectConfigList(query);
+        if (CollectionUtils.isEmpty(configList)) {
+            return new ArrayList<>();
+        }
+        List<CourseRandomRedPacketConfig> result = new ArrayList<>();
+        for (SysConfig sysConfig : configList) {
+            if (sysConfig == null || StringUtils.isBlank(sysConfig.getConfigKey())
+                    || !sysConfig.getConfigKey().startsWith(CONFIG_KEY_PREFIX)) {
+                continue;
+            }
+            String projectStr = sysConfig.getConfigKey().substring(CONFIG_KEY_PREFIX.length());
+            try {
+                Long project = Long.valueOf(projectStr);
+                CourseRandomRedPacketConfig config = getConfigByProject(project);
+                if (config != null) {
+                    result.add(config);
+                }
+            } catch (NumberFormatException e) {
+                logger.warn("忽略无效的课程红包配置键 configKey={}", sysConfig.getConfigKey());
+            }
+        }
+        return result;
+    }
+
+    private void doSaveConfig(CourseRandomRedPacketConfig config) {
         String configKey = buildConfigKey(config.getProject());
         String configKey = buildConfigKey(config.getProject());
         String json = JSONUtil.toJsonStr(config);
         String json = JSONUtil.toJsonStr(config);
         SysConfig existing = configService.selectConfigByConfigKey(configKey);
         SysConfig existing = configService.selectConfigByConfigKey(configKey);
@@ -84,6 +155,39 @@ public class CourseRandomRedPacketServiceImpl implements ICourseRandomRedPacketS
         configService.insertConfig(sysConfig);
         configService.insertConfig(sysConfig);
     }
     }
 
 
+    private CourseRandomRedPacketConfig buildConfigFromBatchParam(CourseRandomRedPacketBatchSaveParam param) {
+        CourseRandomRedPacketConfig config = new CourseRandomRedPacketConfig();
+        config.setProject(param.getProjects().get(0));
+        config.setEnableRandom(param.getEnableRandom());
+        config.setCompanyWhitelist(param.getCompanyWhitelist());
+        config.setTiers(param.getTiers());
+        return config;
+    }
+
+    private CourseRandomRedPacketConfig copyConfigFields(CourseRandomRedPacketConfig source) {
+        CourseRandomRedPacketConfig config = new CourseRandomRedPacketConfig();
+        config.setEnableRandom(source.getEnableRandom());
+        config.setCompanyWhitelist(source.getCompanyWhitelist());
+        config.setTiers(source.getTiers());
+        return config;
+    }
+
+    private void validateConfig(CourseRandomRedPacketConfig config) {
+        if (config == null || config.getProject() == null) {
+            throw new IllegalArgumentException("课程项目不能为空");
+        }
+        if (!Boolean.TRUE.equals(config.getEnableRandom()) || CollectionUtils.isEmpty(config.getTiers())) {
+            return;
+        }
+        int totalWeight = config.getTiers().stream()
+                .filter(t -> t.getWeight() != null && t.getWeight() > 0)
+                .mapToInt(CourseRandomRedPacketTier::getWeight)
+                .sum();
+        if (totalWeight != 100) {
+            throw new IllegalArgumentException("权重总和必须为100%");
+        }
+    }
+
     @Override
     @Override
     public BigDecimal resolveAmount(BigDecimal baseAmount, Long courseId, Long companyId,
     public BigDecimal resolveAmount(BigDecimal baseAmount, Long courseId, Long companyId,
                                     FsUserCourseVideo video, boolean allowLegacyRandom) {
                                     FsUserCourseVideo video, boolean allowLegacyRandom) {