Parcourir la source

Merge remote-tracking branch 'origin/master'

吴树波 il y a 1 mois
Parent
commit
ebbc63bf07
28 fichiers modifiés avec 1436 ajouts et 60 suppressions
  1. 20 8
      fs-admin/src/main/java/com/fs/course/controller/FsUserCoursePeriodController.java
  2. 101 0
      fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java
  3. 18 0
      fs-company-app/src/main/java/com/fs/app/config/ImageStorageConfig.java
  4. 55 0
      fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  5. 5 0
      fs-company-app/src/main/resources/application.yml
  6. 135 11
      fs-service-system/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java
  7. 81 0
      fs-service-system/src/main/java/com/fs/course/domain/FsUserCourseTrainingCamp.java
  8. 78 0
      fs-service-system/src/main/java/com/fs/course/domain/FsVideoResource.java
  9. 16 9
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCoursePeriodMapper.java
  10. 61 0
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseTrainingCampMapper.java
  11. 19 0
      fs-service-system/src/main/java/com/fs/course/mapper/FsVideoResourceMapper.java
  12. 10 1
      fs-service-system/src/main/java/com/fs/course/param/newfs/FsCourseSortLinkParam.java
  13. 27 0
      fs-service-system/src/main/java/com/fs/course/param/newfs/FsUserCourseBeMemberParam.java
  14. 17 9
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCoursePeriodService.java
  15. 21 0
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseService.java
  16. 61 0
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseTrainingCampService.java
  17. 18 0
      fs-service-system/src/main/java/com/fs/course/service/IFsVideoResourceService.java
  18. 15 9
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java
  19. 236 0
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  20. 95 0
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseTrainingCampServiceImpl.java
  21. 25 0
      fs-service-system/src/main/java/com/fs/course/service/impl/FsVideoResourceServiceImpl.java
  22. 84 0
      fs-service-system/src/main/java/com/fs/course/vo/FsUserCoursePeriodVO.java
  23. 9 0
      fs-service-system/src/main/java/com/fs/store/service/IFsUserService.java
  24. 56 0
      fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java
  25. 76 13
      fs-service-system/src/main/resources/mapper/course/FsUserCoursePeriodMapper.xml
  26. 68 0
      fs-service-system/src/main/resources/mapper/course/FsUserCourseTrainingCampMapper.xml
  27. 16 0
      fs-service-system/src/main/resources/mapper/course/FsVideoResourceMapper.xml
  28. 13 0
      fs-user-app/src/main/java/com/fs/app/controller/CourseWxH5Controller.java

+ 20 - 8
fs-user-app/src/main/java/com/fs/app/controller/FsUserCoursePeriodController.java → fs-admin/src/main/java/com/fs/course/controller/FsUserCoursePeriodController.java

@@ -1,6 +1,9 @@
-package com.fs.app.controller;
+package com.fs.course.controller;
 
 import java.util.List;
+
+import com.fs.course.vo.FsUserCoursePeriodVO;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -27,7 +30,7 @@ import com.fs.common.core.page.TableDataInfo;
  * @date 2025-04-11
  */
 @RestController
-@RequestMapping("/course/userCoursePeriod")
+@RequestMapping("/course/period")
 public class FsUserCoursePeriodController extends BaseController
 {
     @Autowired
@@ -36,7 +39,7 @@ public class FsUserCoursePeriodController extends BaseController
     /**
      * 查询会员营期列表
      */
-    @PreAuthorize("@ss.hasPermi('course:userCoursePeriod:list')")
+//    @PreAuthorize("@ss.hasPermi('course:period:list')")
     @GetMapping("/list")
     public TableDataInfo list(FsUserCoursePeriod fsUserCoursePeriod)
     {
@@ -45,10 +48,19 @@ public class FsUserCoursePeriodController extends BaseController
         return getDataTable(list);
     }
 
+    @PostMapping("/page")
+    @ApiOperation("自定义查询主列表分页")
+    public TableDataInfo pageList(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
+    {
+        startPage();
+        List<FsUserCoursePeriodVO> list = fsUserCoursePeriodService.selectFsUserCoursePeriodPage(fsUserCoursePeriod);
+        return getDataTable(list);
+    }
+
     /**
      * 导出会员营期列表
      */
-    @PreAuthorize("@ss.hasPermi('course:userCoursePeriod:export')")
+//    @PreAuthorize("@ss.hasPermi('course:period:export')")
     @Log(title = "会员营期", businessType = BusinessType.EXPORT)
     @GetMapping("/export")
     public AjaxResult export(FsUserCoursePeriod fsUserCoursePeriod)
@@ -61,7 +73,7 @@ public class FsUserCoursePeriodController extends BaseController
     /**
      * 获取会员营期详细信息
      */
-    @PreAuthorize("@ss.hasPermi('course:userCoursePeriod:query')")
+    @PreAuthorize("@ss.hasPermi('course:period:query')")
     @GetMapping(value = "/{periodId}")
     public AjaxResult getInfo(@PathVariable("periodId") Long periodId)
     {
@@ -71,7 +83,7 @@ public class FsUserCoursePeriodController extends BaseController
     /**
      * 新增会员营期
      */
-    @PreAuthorize("@ss.hasPermi('course:userCoursePeriod:add')")
+    @PreAuthorize("@ss.hasPermi('course:period:add')")
     @Log(title = "会员营期", businessType = BusinessType.INSERT)
     @PostMapping
     public AjaxResult add(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
@@ -82,7 +94,7 @@ public class FsUserCoursePeriodController extends BaseController
     /**
      * 修改会员营期
      */
-    @PreAuthorize("@ss.hasPermi('course:userCoursePeriod:edit')")
+    @PreAuthorize("@ss.hasPermi('course:period:edit')")
     @Log(title = "会员营期", businessType = BusinessType.UPDATE)
     @PutMapping
     public AjaxResult edit(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
@@ -93,7 +105,7 @@ public class FsUserCoursePeriodController extends BaseController
     /**
      * 删除会员营期
      */
-    @PreAuthorize("@ss.hasPermi('course:userCoursePeriod:remove')")
+    @PreAuthorize("@ss.hasPermi('course:period:remove')")
     @Log(title = "会员营期", businessType = BusinessType.DELETE)
 	@DeleteMapping("/{periodIds}")
     public AjaxResult remove(@PathVariable Long[] periodIds)

+ 101 - 0
fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java

@@ -0,0 +1,101 @@
+package com.fs.course.controller;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.DateUtils;
+import com.fs.course.domain.FsVideoResource;
+import com.fs.course.service.IFsVideoResourceService;
+import com.github.pagehelper.PageHelper;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 资源库管理
+ */
+@RestController
+@RequestMapping("/course/videoResource")
+@AllArgsConstructor
+public class FsVideoResourceController extends BaseController {
+
+    private final IFsVideoResourceService fsVideoResourceService;
+
+    /**
+     * 查询视频素材库列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:videoResource:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(@RequestParam(required = false) String resourceName,
+                              @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                              @RequestParam(required = false, defaultValue = "10") Integer pageSize)
+    {
+        Map<String, Object> params = new HashMap<>();
+        params.put("resourceName", resourceName);
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<FsVideoResource> list = fsVideoResourceService.selectVideoResourceListByMap(params);
+        return getDataTable(list);
+    }
+
+
+    /**
+     * 获取视频素材库详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:videoResource:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsVideoResourceService.getById(id));
+    }
+
+    /**
+     * 新增视频素材库
+     */
+    @PreAuthorize("@ss.hasPermi('course:videoResource:add')")
+    @Log(title = "视频素材库", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsVideoResource fsVideoResource)
+    {
+        fsVideoResource.setCreateTime(LocalDateTime.now());
+        fsVideoResourceService.save(fsVideoResource);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 修改视频素材库
+     */
+    @PreAuthorize("@ss.hasPermi('course:videoResource:edit')")
+    @Log(title = "视频素材库", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsVideoResource fsVideoResource)
+    {
+        fsVideoResourceService.updateById(fsVideoResource);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 删除视频素材库
+     */
+    @PreAuthorize("@ss.hasPermi('course:videoResource:remove')")
+    @Log(title = "视频素材库", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        Wrapper<FsVideoResource> updateWrapper = Wrappers.<FsVideoResource>lambdaUpdate()
+                .set(FsVideoResource::getIsDel, 1)
+                .in(FsVideoResource::getId, Arrays.asList(ids));
+        fsVideoResourceService.update(updateWrapper);
+        return AjaxResult.success();
+    }
+}

+ 18 - 0
fs-company-app/src/main/java/com/fs/app/config/ImageStorageConfig.java

@@ -0,0 +1,18 @@
+package com.fs.app.config;
+
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Getter
+@Configuration
+public class ImageStorageConfig {
+
+    // 直接返回配置的路径
+    @Value("${image.storage.local-path}")
+    private String localPath;
+
+    @Value("${image.storage.server-path}")
+    private String serverPath;
+
+}

+ 55 - 0
fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java

@@ -1,12 +1,15 @@
 package com.fs.app.controller;
 
 import com.fs.app.annotation.Login;
+import com.fs.app.config.ImageStorageConfig;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
+import com.fs.common.utils.StringUtils;
 import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.param.newfs.FsCourseSortLinkParam;
 import com.fs.course.param.newfs.FsUserCourseListParam;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
+import com.fs.course.service.IFsCourseLinkService;
 import com.fs.course.service.IFsUserCourseService;
 import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.vo.FsUserCourseParticipationRecordVO;
@@ -23,6 +26,7 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.io.File;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -40,6 +44,12 @@ public class FsUserCourseVideoController extends AppBaseController {
     @Autowired
     private IFsUserCourseService fsUserCourseService;
 
+    @Autowired
+    private IFsCourseLinkService courseLinkService;
+
+    @Autowired
+    private ImageStorageConfig imageConfig;
+
     @Login
     @GetMapping("/pageList")
     @ApiOperation("课程分页列表")
@@ -112,4 +122,49 @@ public class FsUserCourseVideoController extends AppBaseController {
         map.put("url", url);
         return R.ok(map);
     }
+
+    @Login
+    @PostMapping("/courseImage")
+    @ApiOperation("生成课程海报")
+    public R createCourseImage(@RequestBody FsCourseSortLinkParam param) {
+        // 获取生成链接
+        FsCourseLinkCreateParam fsCourseLinkCreateParam = new FsCourseLinkCreateParam();
+        BeanUtils.copyProperties(param, fsCourseLinkCreateParam);
+
+        R courseSortLink = fsUserCourseService.createCourseSortLink(fsCourseLinkCreateParam);
+        String link = courseSortLink.get("link").toString();
+        R r = courseLinkService.getRealLink(link);
+        String realLink = r.get("realLink").toString();
+        try {
+            String path = imageConfig.getServerPath();
+            log.info("获取的logo图片路径,fileUrl:{}", path);
+            File file = new File(path);
+            if (StringUtils.isEmpty(param.getImgUrl())) {
+                return R.error(400, "课程封面不能为空!");
+            }
+            String base64Image = fsUserCourseService.createCourseImageQR(realLink, param.getImgUrl(), file, "png", param.getTitle(), param.getDuration());
+            // 返回Base64编码的图片字符串
+            Map<String, Object> map = new HashMap<>();
+            map.put("url", base64Image);
+            return R.ok().put("posterImage", map);
+        } catch (Exception e) {
+            log.error("生成海报失败,param:{}", param);
+            return R.error("生成海报失败!");
+        }
+    }
+
+
+//    @Login
+//    @PostMapping("/sortLink/courseMember")
+//    @ApiOperation("生成分享成为会员短链")
+//    public R createCourseMemberSortLink(@RequestBody FsUserCourseBeMemberParam param) {
+//        FsCourseLinkCreateParam fsCourseLinkCreateParam = new FsCourseLinkCreateParam();
+//        BeanUtils.copyProperties(param, fsCourseLinkCreateParam);
+//
+//        R courseSortLink = fsUserCourseService.createCourseMemberSortLink(fsCourseLinkCreateParam);
+//        String url = courseSortLink.get("url").toString();
+//        Map<String, Object> map = new HashMap<>();
+//        map.put("url", url);
+//        return R.ok(map);
+//    }
 }

+ 5 - 0
fs-company-app/src/main/resources/application.yml

@@ -133,3 +133,8 @@ xss:
   excludes: /system/notice/*,/system/config/*
   # 匹配链接
   urlPatterns: /system/*,/monitor/*,/tool/*
+
+image:
+  storage:
+    local-path: C:\logoFile\logo.jpg
+    server-path: C:\logoFile\logo.jpg

+ 135 - 11
fs-service-system/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java

@@ -1,9 +1,10 @@
 package com.fs.course.domain;
 
 import java.util.Date;
+import java.util.List;
+
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
-import com.fs.common.core.domain.BaseEntity;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 
@@ -11,9 +12,9 @@ import org.apache.commons.lang3.builder.ToStringStyle;
  * 会员营期对象 fs_user_course_period
  *
  * @author fs
- * @date 2025-04-11
+ * @date 2025-04-15
  */
-public class FsUserCoursePeriod extends BaseEntity
+public class FsUserCoursePeriod
 {
     private static final long serialVersionUID = 1L;
 
@@ -28,6 +29,10 @@ public class FsUserCoursePeriod extends BaseEntity
     @Excel(name = "公司id")
     private Long companyId;
 
+    /** 公司id */
+    @Excel(name = "公司id,多个用逗号隔开")
+    private List<Long> companyIdList;
+
     /** 课程id */
     @Excel(name = "课程id")
     private Long courseId;
@@ -36,10 +41,45 @@ public class FsUserCoursePeriod extends BaseEntity
     @Excel(name = "视频id")
     private Long videoId;
 
-    /** 开课时间 */
+    /** 训练营id */
+    @Excel(name = "训练营id")
+    private Long trainingCampId;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "创建时间")
+    private Date createTime;
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "更新时间")
+    private Date updateTime;
+
+    /** 课程风格url */
+    @Excel(name = "课程风格url")
+    private String courseStyle;
+
+    /** 直播间风格url */
+    @Excel(name = "直播间风格url")
+    private String liveRoomStyle;
+
+    /** 红包发放方式,1-按课程,每个课程可得一个;2-按营期,每个营期可得一个 */
+    @Excel(name = "红包发放方式,1-按课程,每个课程可得一个;2-按营期,每个营期可得一个")
+    private Long redPacketGrantMethod;
+
+    /** 营期类型,1-多课程营期;2-单课程营期 */
+    @Excel(name = "营期类型,1-多课程营期;2-单课程营期")
+    private Long periodType;
+
+    /** 开营日期-开始时间 */
     @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "开课时间", width = 30, dateFormat = "yyyy-MM-dd")
-    private Date startingTime;
+    @Excel(name = "开营日期-开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date periodStartingTime;
+
+    /** 开营日期-结束时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "开营日期-结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date periodEndTime;
 
     public void setPeriodId(Long periodId)
     {
@@ -73,6 +113,14 @@ public class FsUserCoursePeriod extends BaseEntity
         this.courseId = courseId;
     }
 
+    public List<Long> getCompanyIdList() {
+        return companyIdList;
+    }
+
+    public void setCompanyIdList(List<Long> companyIdList) {
+        this.companyIdList = companyIdList;
+    }
+
     public Long getCourseId()
     {
         return courseId;
@@ -86,14 +134,84 @@ public class FsUserCoursePeriod extends BaseEntity
     {
         return videoId;
     }
-    public void setStartingTime(Date startingTime)
+    public void setTrainingCampId(Long trainingCampId)
+    {
+        this.trainingCampId = trainingCampId;
+    }
+
+    public Long getTrainingCampId()
+    {
+        return trainingCampId;
+    }
+    public void setCourseStyle(String courseStyle)
+    {
+        this.courseStyle = courseStyle;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getCourseStyle()
+    {
+        return courseStyle;
+    }
+    public void setLiveRoomStyle(String liveRoomStyle)
+    {
+        this.liveRoomStyle = liveRoomStyle;
+    }
+
+    public String getLiveRoomStyle()
+    {
+        return liveRoomStyle;
+    }
+    public void setRedPacketGrantMethod(Long redPacketGrantMethod)
+    {
+        this.redPacketGrantMethod = redPacketGrantMethod;
+    }
+
+    public Long getRedPacketGrantMethod()
+    {
+        return redPacketGrantMethod;
+    }
+    public void setPeriodType(Long periodType)
+    {
+        this.periodType = periodType;
+    }
+
+    public Long getPeriodType()
+    {
+        return periodType;
+    }
+    public void setPeriodStartingTime(Date periodStartingTime)
+    {
+        this.periodStartingTime = periodStartingTime;
+    }
+
+    public Date getPeriodStartingTime()
+    {
+        return periodStartingTime;
+    }
+    public void setPeriodEndTime(Date periodEndTime)
     {
-        this.startingTime = startingTime;
+        this.periodEndTime = periodEndTime;
     }
 
-    public Date getStartingTime()
+    public Date getPeriodEndTime()
     {
-        return startingTime;
+        return periodEndTime;
     }
 
     @Override
@@ -104,9 +222,15 @@ public class FsUserCoursePeriod extends BaseEntity
             .append("companyId", getCompanyId())
             .append("courseId", getCourseId())
             .append("videoId", getVideoId())
-            .append("startingTime", getStartingTime())
+            .append("trainingCampId", getTrainingCampId())
             .append("createTime", getCreateTime())
             .append("updateTime", getUpdateTime())
+            .append("courseStyle", getCourseStyle())
+            .append("liveRoomStyle", getLiveRoomStyle())
+            .append("redPacketGrantMethod", getRedPacketGrantMethod())
+            .append("periodType", getPeriodType())
+            .append("periodStartingTime", getPeriodStartingTime())
+            .append("periodEndTime", getPeriodEndTime())
             .toString();
     }
 }

+ 81 - 0
fs-service-system/src/main/java/com/fs/course/domain/FsUserCourseTrainingCamp.java

@@ -0,0 +1,81 @@
+package com.fs.course.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.Date;
+
+/**
+ * 会员训练营对象 fs_user_course_training_camp
+ *
+ * @author fs
+ * @date 2025-04-15
+ */
+public class FsUserCourseTrainingCamp
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long trainingCampId;
+
+    /** 训练营名称 */
+    @Excel(name = "训练营名称")
+    private String trainingCampName;
+
+    /** 序号 */
+    @Excel(name = "序号")
+    private Long orderNumber;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "创建时间")
+    private Date createTime;
+
+    public void setTrainingCampId(Long trainingCampId)
+    {
+        this.trainingCampId = trainingCampId;
+    }
+
+    public Long getTrainingCampId()
+    {
+        return trainingCampId;
+    }
+    public void setTrainingCampName(String trainingCampName)
+    {
+        this.trainingCampName = trainingCampName;
+    }
+
+    public String getTrainingCampName()
+    {
+        return trainingCampName;
+    }
+    public void setOrderNumber(Long orderNumber)
+    {
+        this.orderNumber = orderNumber;
+    }
+
+    public Long getOrderNumber()
+    {
+        return orderNumber;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+            .append("training campId", getTrainingCampId())
+            .append("training campName", getTrainingCampName())
+            .append("orderNumber", getOrderNumber())
+            .append("createTime", getCreateTime())
+            .toString();
+    }
+}

+ 78 - 0
fs-service-system/src/main/java/com/fs/course/domain/FsVideoResource.java

@@ -0,0 +1,78 @@
+package com.fs.course.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("fs_video_resource")
+public class FsVideoResource {
+
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 资源名称
+     */
+    private String resourceName;
+
+    /**
+     * 文件名称
+     */
+    private String fileName;
+
+    /**
+     * 缩略图
+     */
+    private String thumbnail;
+
+    /**
+     * 视频URL
+     */
+    private String videoUrl;
+
+    /**
+     * 线路1
+     */
+    private String line1;
+
+    /**
+     * 线路2
+     */
+    private String line2;
+
+    /**
+     * 线路3
+     */
+    private String line3;
+
+    /**
+     * 时长
+     */
+    private Integer duration;
+    /**
+     * 文件大小
+     */
+    private Long fileSize;
+
+    /**
+     * 文件key
+     */
+    private String fileKey;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 是否已删除 0未删除 1已删除
+     */
+    private Integer isDel;
+}

+ 16 - 9
fs-service-system/src/main/java/com/fs/course/mapper/FsUserCoursePeriodMapper.java

@@ -2,18 +2,19 @@ package com.fs.course.mapper;
 
 import java.util.List;
 import com.fs.course.domain.FsUserCoursePeriod;
+import com.fs.course.vo.FsUserCoursePeriodVO;
 
 /**
  * 会员营期Mapper接口
- * 
+ *
  * @author fs
- * @date 2025-04-11
+ * @date 2025-04-15
  */
-public interface FsUserCoursePeriodMapper 
+public interface FsUserCoursePeriodMapper
 {
     /**
      * 查询会员营期
-     * 
+     *
      * @param periodId 会员营期ID
      * @return 会员营期
      */
@@ -21,7 +22,7 @@ public interface FsUserCoursePeriodMapper
 
     /**
      * 查询会员营期列表
-     * 
+     *
      * @param fsUserCoursePeriod 会员营期
      * @return 会员营期集合
      */
@@ -29,7 +30,7 @@ public interface FsUserCoursePeriodMapper
 
     /**
      * 新增会员营期
-     * 
+     *
      * @param fsUserCoursePeriod 会员营期
      * @return 结果
      */
@@ -37,7 +38,7 @@ public interface FsUserCoursePeriodMapper
 
     /**
      * 修改会员营期
-     * 
+     *
      * @param fsUserCoursePeriod 会员营期
      * @return 结果
      */
@@ -45,7 +46,7 @@ public interface FsUserCoursePeriodMapper
 
     /**
      * 删除会员营期
-     * 
+     *
      * @param periodId 会员营期ID
      * @return 结果
      */
@@ -53,9 +54,15 @@ public interface FsUserCoursePeriodMapper
 
     /**
      * 批量删除会员营期
-     * 
+     *
      * @param periodIds 需要删除的数据ID
      * @return 结果
      */
     public int deleteFsUserCoursePeriodByIds(Long[] periodIds);
+
+    /**
+     * 查询主页分页列表
+     * @return
+     */
+    List<FsUserCoursePeriodVO> selectFsUserCoursePeriodPage(FsUserCoursePeriod fsUserCoursePeriod);
 }

+ 61 - 0
fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseTrainingCampMapper.java

@@ -0,0 +1,61 @@
+package com.fs.course.mapper;
+
+import java.util.List;
+import com.fs.course.domain.FsUserCourseTrainingCamp;
+
+/**
+ * 会员训练营Mapper接口
+ *
+ * @author fs
+ * @date 2025-04-15
+ */
+public interface FsUserCourseTrainingCampMapper
+{
+    /**
+     * 查询会员训练营
+     *
+     * @param trainingCampId 会员训练营ID
+     * @return 会员训练营
+     */
+    public FsUserCourseTrainingCamp selectFsUserCourseTrainingCampById(Long trainingCampId);
+
+    /**
+     * 查询会员训练营列表
+     *
+     * @param fsUserCourseTrainingCamp 会员训练营
+     * @return 会员训练营集合
+     */
+    public List<FsUserCourseTrainingCamp> selectFsUserCourseTrainingCampList(FsUserCourseTrainingCamp fsUserCourseTrainingCamp);
+
+    /**
+     * 新增会员训练营
+     *
+     * @param fsUserCourseTrainingCamp 会员训练营
+     * @return 结果
+     */
+    public int insertFsUserCourseTrainingCamp(FsUserCourseTrainingCamp fsUserCourseTrainingCamp);
+
+    /**
+     * 修改会员训练营
+     *
+     * @param fsUserCourseTrainingCamp 会员训练营
+     * @return 结果
+     */
+    public int updateFsUserCourseTrainingCamp(FsUserCourseTrainingCamp fsUserCourseTrainingCamp);
+
+    /**
+     * 删除会员训练营
+     *
+     * @param trainingCampId 会员训练营ID
+     * @return 结果
+     */
+    public int deleteFsUserCourseTrainingCampById(Long trainingCampId);
+
+    /**
+     * 批量删除会员训练营
+     *
+     * @param trainingCampIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteFsUserCourseTrainingCampByIds(Long[] trainingCampIds);
+}

+ 19 - 0
fs-service-system/src/main/java/com/fs/course/mapper/FsVideoResourceMapper.java

@@ -0,0 +1,19 @@
+package com.fs.course.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.course.domain.FsVideoResource;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+public interface FsVideoResourceMapper extends BaseMapper<FsVideoResource> {
+
+    /**
+     * 查询素材库列表
+     *
+     * @param params    参数
+     * @return  list
+     */
+    List<FsVideoResource> selectVideoResourceListByMap(@Param("params") Map<String, Object> params);
+}

+ 10 - 1
fs-service-system/src/main/java/com/fs/course/param/newfs/FsCourseSortLinkParam.java

@@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 @Data
-@ApiModel(description = "生成课程短链入参")
+@ApiModel(description = "生成课程短链/海报入参")
 public class FsCourseSortLinkParam {
 
     @ApiModelProperty(value = "视频id")
@@ -23,4 +23,13 @@ public class FsCourseSortLinkParam {
     @ApiModelProperty(value = "链接有效时长")
     private Integer effectiveDuration;
 
+    @ApiModelProperty(value = "课程封面,生成海报时必传")
+    private String imgUrl;
+
+    @ApiModelProperty(value = "标题,生成海报时必传")
+    private String title;
+
+    @ApiModelProperty(value = "视频时长,生成海报时必传")
+    private String duration;
+
 }

+ 27 - 0
fs-service-system/src/main/java/com/fs/course/param/newfs/FsUserCourseBeMemberParam.java

@@ -0,0 +1,27 @@
+package com.fs.course.param.newfs;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+@Data
+public class FsUserCourseBeMemberParam implements Serializable {
+
+    @NotNull(message = "用户id不能为空")
+    @ApiModelProperty(value = "授权的用户id")
+    private Long userId;
+
+    @NotNull(message = "销售id不能为空")
+    @ApiModelProperty(value = "销售id")
+    private Long companyUserId;
+
+    @ApiModelProperty(value = "公司id")
+    private Long companyId;
+
+    @ApiModelProperty(value = "标签ids,多个用逗号隔开")
+    private String[] tagIds;
+
+
+}

+ 17 - 9
fs-service-system/src/main/java/com/fs/course/service/IFsUserCoursePeriodService.java

@@ -2,18 +2,19 @@ package com.fs.course.service;
 
 import java.util.List;
 import com.fs.course.domain.FsUserCoursePeriod;
+import com.fs.course.vo.FsUserCoursePeriodVO;
 
 /**
  * 会员营期Service接口
- * 
+ *
  * @author fs
- * @date 2025-04-11
+ * @date 2025-04-15
  */
-public interface IFsUserCoursePeriodService 
+public interface IFsUserCoursePeriodService
 {
     /**
      * 查询会员营期
-     * 
+     *
      * @param periodId 会员营期ID
      * @return 会员营期
      */
@@ -21,7 +22,7 @@ public interface IFsUserCoursePeriodService
 
     /**
      * 查询会员营期列表
-     * 
+     *
      * @param fsUserCoursePeriod 会员营期
      * @return 会员营期集合
      */
@@ -29,7 +30,7 @@ public interface IFsUserCoursePeriodService
 
     /**
      * 新增会员营期
-     * 
+     *
      * @param fsUserCoursePeriod 会员营期
      * @return 结果
      */
@@ -37,7 +38,7 @@ public interface IFsUserCoursePeriodService
 
     /**
      * 修改会员营期
-     * 
+     *
      * @param fsUserCoursePeriod 会员营期
      * @return 结果
      */
@@ -45,7 +46,7 @@ public interface IFsUserCoursePeriodService
 
     /**
      * 批量删除会员营期
-     * 
+     *
      * @param periodIds 需要删除的会员营期ID
      * @return 结果
      */
@@ -53,9 +54,16 @@ public interface IFsUserCoursePeriodService
 
     /**
      * 删除会员营期信息
-     * 
+     *
      * @param periodId 会员营期ID
      * @return 结果
      */
     public int deleteFsUserCoursePeriodById(Long periodId);
+
+    /**
+     * 获取主列表
+     * @param fsUserCoursePeriod 入参
+     * @return vo
+     */
+    List<FsUserCoursePeriodVO> selectFsUserCoursePeriodPage(FsUserCoursePeriod fsUserCoursePeriod);
 }

+ 21 - 0
fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseService.java

@@ -1,5 +1,6 @@
 package com.fs.course.service;
 
+import java.io.File;
 import java.util.List;
 import java.util.Map;
 
@@ -122,4 +123,24 @@ public interface IFsUserCourseService
      * @return
      */
     R createCourseSortLink(FsCourseLinkCreateParam param);
+
+    /**
+     * 生成海报
+     * @param url
+     * @param backgroundImagePath
+     * @param file
+     * @param outputFormat
+     * @param title
+     * @param duration
+     * @return
+     * @throws Exception
+     */
+    String createCourseImageQR(String url, String backgroundImagePath, File file, String outputFormat, String title, String duration) throws Exception;
+
+    /**
+     * 创建 分享成为会员 短链
+     * @param param 入参
+     * @return
+     */
+    R createCourseMemberSortLink(FsCourseLinkCreateParam param);
 }

+ 61 - 0
fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseTrainingCampService.java

@@ -0,0 +1,61 @@
+package com.fs.course.service;
+
+import java.util.List;
+import com.fs.course.domain.FsUserCourseTrainingCamp;
+
+/**
+ * 会员训练营Service接口
+ *
+ * @author fs
+ * @date 2025-04-15
+ */
+public interface IFsUserCourseTrainingCampService
+{
+    /**
+     * 查询会员训练营
+     *
+     * @param trainingCampId 会员训练营ID
+     * @return 会员训练营
+     */
+    public FsUserCourseTrainingCamp selectFsUserCourseTrainingCampById(Long trainingCampId);
+
+    /**
+     * 查询会员训练营列表
+     *
+     * @param fsUserCourseTrainingCamp 会员训练营
+     * @return 会员训练营集合
+     */
+    public List<FsUserCourseTrainingCamp> selectFsUserCourseTrainingCampList(FsUserCourseTrainingCamp fsUserCourseTrainingCamp);
+
+    /**
+     * 新增会员训练营
+     *
+     * @param fsUserCourseTrainingCamp 会员训练营
+     * @return 结果
+     */
+    public int insertFsUserCourseTrainingCamp(FsUserCourseTrainingCamp fsUserCourseTrainingCamp);
+
+    /**
+     * 修改会员训练营
+     *
+     * @param fsUserCourseTrainingCamp 会员训练营
+     * @return 结果
+     */
+    public int updateFsUserCourseTrainingCamp(FsUserCourseTrainingCamp fsUserCourseTrainingCamp);
+
+    /**
+     * 批量删除会员训练营
+     *
+     * @param trainingCampIds 需要删除的会员训练营ID
+     * @return 结果
+     */
+    public int deleteFsUserCourseTrainingCampByIds(Long[] trainingCampIds);
+
+    /**
+     * 删除会员训练营信息
+     *
+     * @param trainingCampId 会员训练营ID
+     * @return 结果
+     */
+    public int deleteFsUserCourseTrainingCampById(Long trainingCampId);
+}

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

@@ -0,0 +1,18 @@
+package com.fs.course.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.course.domain.FsVideoResource;
+
+import java.util.List;
+import java.util.Map;
+
+public interface IFsVideoResourceService extends IService<FsVideoResource> {
+
+    /**
+     * 查询素材库列表
+     *
+     * @param params    参数
+     * @return  list
+     */
+    List<FsVideoResource> selectVideoResourceListByMap(Map<String, Object> params);
+}

+ 15 - 9
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.course.service.impl;
 
 import java.util.List;
 import com.fs.common.utils.DateUtils;
+import com.fs.course.vo.FsUserCoursePeriodVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.course.mapper.FsUserCoursePeriodMapper;
@@ -10,19 +11,19 @@ import com.fs.course.service.IFsUserCoursePeriodService;
 
 /**
  * 会员营期Service业务层处理
- * 
+ *
  * @author fs
- * @date 2025-04-11
+ * @date 2025-04-15
  */
 @Service
-public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService 
+public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
 {
     @Autowired
     private FsUserCoursePeriodMapper fsUserCoursePeriodMapper;
 
     /**
      * 查询会员营期
-     * 
+     *
      * @param periodId 会员营期ID
      * @return 会员营期
      */
@@ -34,7 +35,7 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
 
     /**
      * 查询会员营期列表
-     * 
+     *
      * @param fsUserCoursePeriod 会员营期
      * @return 会员营期
      */
@@ -46,7 +47,7 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
 
     /**
      * 新增会员营期
-     * 
+     *
      * @param fsUserCoursePeriod 会员营期
      * @return 结果
      */
@@ -59,7 +60,7 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
 
     /**
      * 修改会员营期
-     * 
+     *
      * @param fsUserCoursePeriod 会员营期
      * @return 结果
      */
@@ -72,7 +73,7 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
 
     /**
      * 批量删除会员营期
-     * 
+     *
      * @param periodIds 需要删除的会员营期ID
      * @return 结果
      */
@@ -84,7 +85,7 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
 
     /**
      * 删除会员营期信息
-     * 
+     *
      * @param periodId 会员营期ID
      * @return 结果
      */
@@ -93,4 +94,9 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
     {
         return fsUserCoursePeriodMapper.deleteFsUserCoursePeriodById(periodId);
     }
+
+    @Override
+    public List<FsUserCoursePeriodVO> selectFsUserCoursePeriodPage(FsUserCoursePeriod fsUserCoursePeriod) {
+        return fsUserCoursePeriodMapper.selectFsUserCoursePeriodPage(fsUserCoursePeriod);
+    }
 }

+ 236 - 0
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.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.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
@@ -22,11 +23,28 @@ import com.fs.course.vo.*;
 import com.fs.course.vo.newfs.FsUserCourseListVO;
 import com.fs.his.vo.OptionsVO;
 import com.fs.system.service.ISysConfigService;
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.QRCodeWriter;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.net.URL;
 import java.util.*;
+import java.util.List;
 
 /**
  * 课程Service业务层处理
@@ -60,6 +78,7 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
 
     private static final String realLink = "/courseH5/pages/course/learning?course=";
     private static final String shortLink = "/courseH5/pages/course/learning?s=";
+    private static final String userRealLink = "/pages/user/users/becomeVIP?";
 
     /**
      * 查询课程
@@ -414,10 +433,227 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
         String courseJson = JSON.toJSONString(courseMap);
 
         link.setRealLink(realLink + courseJson);
+        String random = generateRandomString();
+        link.setLink(random);
+        link.setCreateTime(new Date());
+
+        //获取过期时间
+        Calendar calendar = getExpireDay(param, config, link.getCreateTime());
+        link.setUpdateTime(calendar.getTime());
+        int i = fsCourseLinkMapper.insertFsCourseLink(link);
+        if (i > 0){
+            String domainName = getDomainName(param.getCompanyUserId(), config);
+            String sortLink = domainName + shortLink + link.getLink();
+            return R.ok().put("url", sortLink).put("link", random);
+        }
+        return R.error("生成链接失败!");
+    }
+
+
+    @Override
+    public String createCourseImageQR(String url, String backgroundImagePath, File file,
+                                      String outputFormat, String title, String duration) throws Exception {
+        // 读取并缩放背景图片
+        BufferedImage backgroundImage = createScaledBackgroundImage(backgroundImagePath);
+        int scaledWidth = backgroundImage.getWidth();
+        int scaledHeight = backgroundImage.getHeight();
+
+        // 创建最终的合成图片,确保底部区域有足够空间
+        int bottomHeight = 200; // 增加底部区域高度,确保内容完全显示
+        int totalHeight = scaledHeight + bottomHeight;
+        BufferedImage combined = new BufferedImage(scaledWidth, totalHeight, BufferedImage.TYPE_INT_ARGB);
+        Graphics2D graphics = initializeGraphics(combined);
+
+        // 绘制背景和底部白色区域
+        graphics.drawImage(backgroundImage, 0, 0, null);
+        graphics.setColor(Color.WHITE);
+        graphics.fillRect(0, scaledHeight, scaledWidth, bottomHeight);
+
+        // 绘制推荐区域(图片和文字)
+        drawRecommendationArea(graphics, file, scaledHeight);
+
+        // 绘制二维码
+        drawQRCode(graphics, url, scaledWidth, totalHeight);
+
+        // 绘制标题和时长
+        drawTitleAndDuration(graphics, title, duration, scaledHeight);
+
+        graphics.dispose();
+
+        // 转换为Base64
+        return convertToBase64(combined, outputFormat);
+    }
+
+    /**
+     * 读取并缩放背景图片
+     */
+    private BufferedImage createScaledBackgroundImage(String backgroundImagePath) throws IOException {
+        // 设置固定的目标尺寸
+        final int TARGET_WIDTH = 600;
+        final int TARGET_HEIGHT = 300; // 固定背景图片高度为300像素
+
+        URL imagePath = new URL(backgroundImagePath);
+        BufferedImage originalBackground = ImageIO.read(imagePath);
+
+        // 计算缩放比例,以高度为基准
+        double scale = (double) TARGET_HEIGHT / originalBackground.getHeight();
+        int scaledWidth = (int) (originalBackground.getWidth() * scale);
+
+        // 创建固定大小的背景图片
+        BufferedImage backgroundImage = new BufferedImage(TARGET_WIDTH, TARGET_HEIGHT, BufferedImage.TYPE_INT_ARGB);
+        Graphics2D g2d = backgroundImage.createGraphics();
+        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+
+        // 计算居中位置
+        int x = (TARGET_WIDTH - scaledWidth) / 2;
+
+        // 绘制缩放后的图片
+        g2d.drawImage(originalBackground, x, 0, scaledWidth, TARGET_HEIGHT, null);
+        g2d.dispose();
+
+        return backgroundImage;
+    }
+
+    /**
+     * 初始化图形上下文
+     */
+    private Graphics2D initializeGraphics(BufferedImage combined) {
+        Graphics2D graphics = combined.createGraphics();
+        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+        graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+        return graphics;
+    }
+
+    /**
+     * 绘制推荐区域
+     */
+    private void drawRecommendationArea(Graphics2D graphics, File file, int scaledHeight) throws IOException {
+        // 读取并绘制推荐图片
+        BufferedImage referenceImg = ImageIO.read(file);
+        int refHeight = 40;
+        int refWidth = 40;
+        int refY = scaledHeight + 20;
+        int refX = 30;
+        graphics.drawImage(referenceImg, refX, refY, refWidth, refHeight, null);
+
+        // 设置并绘制推荐文字
+        Font recommendFont = new Font("微软雅黑", Font.BOLD, 16);
+        graphics.setFont(recommendFont);
+
+        // 绘制"云联融智"
+        int textX = refX + refWidth + 10;
+        int textY = refY + 25;
+        graphics.setColor(new Color(51, 51, 51));
+        graphics.drawString("云联融智", textX, textY);
+
+        // 绘制"为您推荐"
+        FontMetrics metrics = graphics.getFontMetrics(recommendFont);
+        int brandWidth = metrics.stringWidth("云联融智");
+        int textX1 = textX + brandWidth + 5;
+        graphics.setColor(new Color(102, 102, 102));
+        graphics.drawString("为您推荐", textX1, textY);
+//        FontMetrics metrics = graphics.getFontMetrics(recommendFont);
+        int reWidth = metrics.stringWidth("为您推荐");
+    }
+
+
+    /**
+     * 生成二维码图片
+     */
+    private static BufferedImage generateQrCodeImage(String text, int width, int height) throws Exception {
+        QRCodeWriter qrCodeWriter = new QRCodeWriter();
+        Map<EncodeHintType, Object> hints = new HashMap<>();
+        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
+        hints.put(EncodeHintType.MARGIN, 1);
+        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);
+        return MatrixToImageWriter.toBufferedImage(bitMatrix);
+    }
+
+    /**
+     * 绘制二维码
+     */
+    private void drawQRCode(Graphics2D graphics, String url, int scaledWidth, int totalHeight) throws Exception {
+        BufferedImage qrCodeImage = generateQrCodeImage(url, 200, 200);
+        int qrSize = 100;
+        int qrMarginRight = 25;
+        int qrMarginBottom = 30;
+        int qrX = scaledWidth - qrSize - qrMarginRight;
+        int qrY = totalHeight - qrSize - qrMarginBottom;
+        graphics.drawImage(qrCodeImage, qrX, qrY, qrSize, qrSize, null);
+    }
+
+    /**
+     * 绘制标题和时长
+     */
+    private void drawTitleAndDuration(Graphics2D graphics, String title, String duration, int scaledHeight) {
+        Font titleFont = new Font("微软雅黑", Font.BOLD, 18);
+        Font descFont = new Font("微软雅黑", Font.PLAIN, 14);
+
+        int contentX = 30;
+        int titleY = scaledHeight + 85;
+        int descY = titleY + 25;
+
+        graphics.setFont(titleFont);
+        graphics.setColor(new Color(51, 51, 51));
+        graphics.drawString(title, contentX, titleY);
+
+        graphics.setFont(descFont);
+        graphics.setColor(new Color(102, 102, 102));
+        if(StringUtils.isNotBlank(duration)){
+            // 将秒转化为分钟
+            BigDecimal bigDecimal = new BigDecimal(duration);
+            bigDecimal = bigDecimal.divide(new BigDecimal(60), 2, RoundingMode.HALF_UP);
+            String minutes = bigDecimal.toString();
+            graphics.drawString("播放时长:" + minutes + "分钟", contentX, descY);
+        } else {
+            graphics.drawString("播放时长:" + "暂无", contentX, descY);
+        }
+
+    }
+
+    /**
+     * 将图片转换为Base64字符串
+     */
+    private String convertToBase64(BufferedImage image, String outputFormat) throws IOException {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        ImageIO.write(image, outputFormat, outputStream);
+        byte[] imageBytes = outputStream.toByteArray();
+        String s = Base64.getEncoder().encodeToString(imageBytes);
+        StringBuilder result = new StringBuilder();
+        if(StringUtils.isNotEmpty(s)){
+            result.append("data:image/png;base64,").append(s);
+        }
+        return result.toString();
+    }
+
+    @Override
+    public R createCourseMemberSortLink(FsCourseLinkCreateParam param) {
+        // todo 需要调整路径
+        String json = configService.selectConfigByKey("company.user");
+        JSONObject object = JSON.parseObject(json);
+        String realLinkDomainName = object.get("realLinkDomainName").toString();
+        Integer linkExpireTime = Integer.parseInt(object.get("linkExpireTime").toString());
+
+        //新增链接表信息
+        FsCourseLink link = new FsCourseLink();
+        BeanUtils.copyProperties(param, link);
+        link.setLinkType(0);
+        link.setIsRoom(0);
+
+        FsCourseRealLink courseMap = new FsCourseRealLink();
+        BeanUtils.copyProperties(link, courseMap);
+        String courseJson = JSON.toJSONString(courseMap);
+
+        link.setRealLink(userRealLink + courseJson);
         link.setLink(generateRandomString());
         link.setCreateTime(new Date());
 
         //获取过期时间
+        CourseConfig config = new CourseConfig();
+        config.setRealLinkDomainName(realLinkDomainName);
+        config.setVideoLinkExpireDate(linkExpireTime);
         Calendar calendar = getExpireDay(param, config, link.getCreateTime());
         link.setUpdateTime(calendar.getTime());
         int i = fsCourseLinkMapper.insertFsCourseLink(link);

+ 95 - 0
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseTrainingCampServiceImpl.java

@@ -0,0 +1,95 @@
+package com.fs.course.service.impl;
+
+import java.util.List;
+import com.fs.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.course.mapper.FsUserCourseTrainingCampMapper;
+import com.fs.course.domain.FsUserCourseTrainingCamp;
+import com.fs.course.service.IFsUserCourseTrainingCampService;
+
+/**
+ * 会员训练营Service业务层处理
+ *
+ * @author fs
+ * @date 2025-04-15
+ */
+@Service
+public class FsUserCourseTrainingCampServiceImpl implements IFsUserCourseTrainingCampService
+{
+    @Autowired
+    private FsUserCourseTrainingCampMapper fsUserCourseTrainingCampMapper;
+
+    /**
+     * 查询会员训练营
+     *
+     * @param trainingCampId 会员训练营ID
+     * @return 会员训练营
+     */
+    @Override
+    public FsUserCourseTrainingCamp selectFsUserCourseTrainingCampById(Long trainingCampId)
+    {
+        return fsUserCourseTrainingCampMapper.selectFsUserCourseTrainingCampById(trainingCampId);
+    }
+
+    /**
+     * 查询会员训练营列表
+     *
+     * @param fsUserCourseTrainingCamp 会员训练营
+     * @return 会员训练营
+     */
+    @Override
+    public List<FsUserCourseTrainingCamp> selectFsUserCourseTrainingCampList(FsUserCourseTrainingCamp fsUserCourseTrainingCamp)
+    {
+        return fsUserCourseTrainingCampMapper.selectFsUserCourseTrainingCampList(fsUserCourseTrainingCamp);
+    }
+
+    /**
+     * 新增会员训练营
+     *
+     * @param fsUserCourseTrainingCamp 会员训练营
+     * @return 结果
+     */
+    @Override
+    public int insertFsUserCourseTrainingCamp(FsUserCourseTrainingCamp fsUserCourseTrainingCamp)
+    {
+        fsUserCourseTrainingCamp.setCreateTime(DateUtils.getNowDate());
+        return fsUserCourseTrainingCampMapper.insertFsUserCourseTrainingCamp(fsUserCourseTrainingCamp);
+    }
+
+    /**
+     * 修改会员训练营
+     *
+     * @param fsUserCourseTrainingCamp 会员训练营
+     * @return 结果
+     */
+    @Override
+    public int updateFsUserCourseTrainingCamp(FsUserCourseTrainingCamp fsUserCourseTrainingCamp)
+    {
+        return fsUserCourseTrainingCampMapper.updateFsUserCourseTrainingCamp(fsUserCourseTrainingCamp);
+    }
+
+    /**
+     * 批量删除会员训练营
+     *
+     * @param trainingCampIds 需要删除的会员训练营ID
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserCourseTrainingCampByIds(Long[] trainingCampIds)
+    {
+        return fsUserCourseTrainingCampMapper.deleteFsUserCourseTrainingCampByIds(trainingCampIds);
+    }
+
+    /**
+     * 删除会员训练营信息
+     *
+     * @param trainingCampId 会员训练营ID
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserCourseTrainingCampById(Long trainingCampId)
+    {
+        return fsUserCourseTrainingCampMapper.deleteFsUserCourseTrainingCampById(trainingCampId);
+    }
+}

+ 25 - 0
fs-service-system/src/main/java/com/fs/course/service/impl/FsVideoResourceServiceImpl.java

@@ -0,0 +1,25 @@
+package com.fs.course.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.course.domain.FsVideoResource;
+import com.fs.course.mapper.FsVideoResourceMapper;
+import com.fs.course.service.IFsVideoResourceService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class FsVideoResourceServiceImpl extends ServiceImpl<FsVideoResourceMapper, FsVideoResource> implements IFsVideoResourceService {
+
+    /**
+     * 查询素材库列表
+     *
+     * @param params    参数
+     * @return  list
+     */
+    @Override
+    public List<FsVideoResource> selectVideoResourceListByMap(Map<String, Object> params) {
+        return baseMapper.selectVideoResourceListByMap(params);
+    }
+}

+ 84 - 0
fs-service-system/src/main/java/com/fs/course/vo/FsUserCoursePeriodVO.java

@@ -0,0 +1,84 @@
+package com.fs.course.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 会员营期分页列表 vo
+ * @date 2025-04-15
+ */
+@Data
+public class FsUserCoursePeriodVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 营期id */
+    private Long periodId;
+
+    /** 营期名称 */
+    @Excel(name = "营期名称")
+    private String periodName;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    @Excel(name = "公司名称")
+    private Long companyName;
+
+    /** 课程id */
+    @Excel(name = "课程id")
+    private Long courseId;
+
+    /** 视频id */
+    @Excel(name = "视频id")
+    private Long videoId;
+
+    /** 训练营id */
+    @Excel(name = "训练营id")
+    private Long trainingCampId;
+
+    /** 训练营id */
+    @Excel(name = "所属训练营")
+    private Long trainingCampName;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "创建时间")
+    private Date createTime;
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "更新时间")
+    private Date updateTime;
+
+    /** 课程风格url */
+    @Excel(name = "课程风格url")
+    private String courseStyle;
+
+    /** 直播间风格url */
+    @Excel(name = "直播间风格url")
+    private String liveRoomStyle;
+
+    /** 红包发放方式,1-按课程,每个课程可得一个;2-按营期,每个营期可得一个 */
+    @Excel(name = "红包发放方式,1-按课程,每个课程可得一个;2-按营期,每个营期可得一个")
+    private Long redPacketGrantMethod;
+
+    /** 营期类型,1-多课程营期;2-单课程营期 */
+    @Excel(name = "营期类型,1-多课程营期;2-单课程营期")
+    private Long periodType;
+
+    /** 开营日期-开始时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "开营日期-开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date periodStartingTime;
+
+    /** 开营日期-结束时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "开营日期-结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date periodEndTime;
+
+}

+ 9 - 0
fs-service-system/src/main/java/com/fs/store/service/IFsUserService.java

@@ -4,8 +4,10 @@ import java.util.List;
 import java.util.Map;
 
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.company.vo.CompanyQueryVo;
+import com.fs.course.param.newfs.FsUserCourseBeMemberParam;
 import com.fs.course.vo.newfs.FsCourseAnalysisVO;
 import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.vo.QwFsUserVO;
@@ -226,4 +228,11 @@ public interface IFsUserService
      */
     CompanyUserSummaryCountVO companyUserSummaryCount(Long userId, String companyUserId);
 
+    /**
+     * 成为销售的会员
+     * @param param
+     * @return 是否成功
+     */
+    ResponseResult<Boolean> becomeMember(FsUserCourseBeMemberParam param);
+
 }

+ 56 - 0
fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java

@@ -12,13 +12,18 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.utils.DateUtils;
 import com.fs.company.cache.ICompanyUserCacheService;
+import com.fs.company.domain.CompanyTagUser;
 import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyTagUserMapper;
+import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.company.vo.CompanyQueryVo;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
+import com.fs.course.param.newfs.FsUserCourseBeMemberParam;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
 import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
 import com.fs.course.vo.newfs.FsCourseAnalysisVO;
@@ -41,6 +46,7 @@ import com.fs.store.service.IFsUserBillService;
 import com.fs.store.vo.FSUserVO;
 import com.fs.store.vo.FsCompanyUserListQueryVO;
 import com.fs.store.vo.FsUserTuiVO;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.http.util.Asserts;
 import com.fs.store.vo.h5.FsUserPageListVO;
@@ -67,6 +73,7 @@ import static com.fs.store.enums.BillDetailEnum.CATEGORY_3;
  * @date 2022-03-15
  */
 @Service
+@Slf4j
 public class FsUserServiceImpl implements IFsUserService
 {
     @Autowired
@@ -87,6 +94,12 @@ public class FsUserServiceImpl implements IFsUserService
     @Autowired
     private FsUserCourseVideoMapper userCourseVideoMapper;
 
+    @Autowired
+    private CompanyUserMapper companyUserMapper;
+
+    @Autowired
+    private CompanyTagUserMapper  companyTagUserMapper;
+
     /**
      * 查询用户
      *
@@ -648,4 +661,47 @@ public class FsUserServiceImpl implements IFsUserService
         vo.setTodayUserRedPacketAmount(newUserRedPacketCount.getTodayUserRedPacketAmount());
         return vo;
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public ResponseResult<Boolean> becomeMember(FsUserCourseBeMemberParam param) {
+        //查询用户
+        FsUser fsUser = fsUserMapper.selectFsUserById(param.getUserId());
+        if (Objects.isNull(fsUser)){
+            return ResponseResult.fail(401,"未授权");
+        }
+        if (fsUser.getCompanyUserId() != null){
+            return ResponseResult.fail(500,"该用户已成为其他销售会员");
+        }
+
+        //判断该销售是否存在
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
+        if (Objects.isNull(companyUser)){
+            return ResponseResult.fail(500,"销售不存在");
+        }
+
+        // 关联销售
+        fsUser.setCompanyId(param.getCompanyId());
+        fsUser.setCompanyUserId(param.getCompanyUserId());
+        fsUserMapper.updateFsUser(fsUser);
+
+        //关联会员标签,先删除再新增
+        Map<String, Object> map = new HashMap<>();
+        map.put("userId", param.getUserId());
+        map.put("companyId", fsUser.getCompanyId());
+        map.put("companyUserId", fsUser.getCompanyUserId());
+        companyTagUserMapper.deleteCompanyTagUserByMap(map);
+
+        // 不为空则添加新标签
+        if (Objects.nonNull(param.getTagIds()) && param.getTagIds().length > 0) {
+            CompanyTagUser companyTagUser = new CompanyTagUser();
+            companyTagUser.setUserId(param.getUserId());
+            companyTagUser.setCompanyId(fsUser.getCompanyId());
+            companyTagUser.setCompanyUserId(fsUser.getCompanyUserId());
+            companyTagUser.setTagIds(String.join(",", param.getTagIds()));
+            companyTagUser.setCreateTime(new Date());
+            companyTagUserMapper.insertCompanyTagUser(companyTagUser);
+        }
+        return ResponseResult.ok(Boolean.TRUE);
+    }
 }

+ 76 - 13
fs-service-system/src/main/resources/mapper/course/FsUserCoursePeriodMapper.xml

@@ -3,38 +3,83 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.fs.course.mapper.FsUserCoursePeriodMapper">
-    
+
     <resultMap type="FsUserCoursePeriod" id="FsUserCoursePeriodResult">
         <result property="periodId"    column="period_id"    />
         <result property="periodName"    column="period_name"    />
         <result property="companyId"    column="company_id"    />
         <result property="courseId"    column="course_id"    />
         <result property="videoId"    column="video_id"    />
-        <result property="startingTime"    column="starting_time"    />
+        <result property="trainingCampId"    column="training_camp_id"    />
         <result property="createTime"    column="create_time"    />
         <result property="updateTime"    column="update_time"    />
+        <result property="courseStyle"    column="course_style"    />
+        <result property="liveRoomStyle"    column="live_room_style"    />
+        <result property="redPacketGrantMethod"    column="red_packet_grant_method"    />
+        <result property="periodType"    column="period_type"    />
+        <result property="periodStartingTime"    column="period_starting_time"    />
+        <result property="periodEndTime"    column="period_end_time"    />
     </resultMap>
 
     <sql id="selectFsUserCoursePeriodVo">
-        select period_id, period_name, company_id, course_id, video_id, starting_time, create_time, update_time from fs_user_course_period
+        select period_id, period_name, company_id, course_id, video_id, training_camp_id, create_time, update_time, course_style, live_room_style, red_packet_grant_method, period_type, period_starting_time, period_end_time from fs_user_course_period
     </sql>
 
     <select id="selectFsUserCoursePeriodList" parameterType="FsUserCoursePeriod" resultMap="FsUserCoursePeriodResult">
         <include refid="selectFsUserCoursePeriodVo"/>
-        <where>  
+        <where>
             <if test="periodName != null  and periodName != ''"> and period_name like concat('%', #{periodName}, '%')</if>
             <if test="companyId != null "> and company_id = #{companyId}</if>
             <if test="courseId != null "> and course_id = #{courseId}</if>
             <if test="videoId != null "> and video_id = #{videoId}</if>
-            <if test="startingTime != null "> and starting_time = #{startingTime}</if>
+            <if test="trainingCampId != null "> and training_camp_id = #{trainingCampId}</if>
+            <if test="courseStyle != null  and courseStyle != ''"> and course_style = #{courseStyle}</if>
+            <if test="liveRoomStyle != null  and liveRoomStyle != ''"> and live_room_style = #{liveRoomStyle}</if>
+            <if test="redPacketGrantMethod != null "> and red_packet_grant_method = #{redPacketGrantMethod}</if>
+            <if test="periodType != null "> and period_type = #{periodType}</if>
+            <if test="periodStartingTime != null "> and period_starting_time = #{periodStartingTime}</if>
+            <if test="periodEndTime != null "> and period_end_time = #{periodEndTime}</if>
+        </where>
+    </select>
+
+    <select id="selectFsUserCoursePeriodPage" parameterType="FsUserCoursePeriod" resultType="FsUserCoursePeriodVO">
+        SELECT
+        period_id,
+        period_name,
+        fs_user_course_period.company_id,
+        course_id,
+        video_id,
+        training_camp_id,
+        fs_user_course_period.create_time,
+        fs_user_course_period.update_time,
+        course_style,
+        live_room_style,
+        red_packet_grant_method,
+        period_type,
+        period_starting_time,
+        GROUP_CONCAT( company.company_name ) AS companyName
+        FROM
+        fs_user_course_period
+        LEFT JOIN company ON fs_user_course_period.company_id = company.company_id
+        <where>
+            <if test="periodName != null  and periodName != ''"> and period_name like concat('%', #{periodName}, '%')</if>
+            <if test="companyIdList != null and companyIdList.size() > 0 ">
+                and fs_user_course_period.company_id in
+                <foreach item="companyId" index="index" collection="companyIdList"
+                         open="(" separator="," close=")">
+                    #{companyId}
+                </foreach>
+            </if>
+            <if test="periodStartingTime != null "> and period_starting_time = #{periodStartingTime}</if>
+            <if test="periodEndTime != null "> and period_end_time = #{periodEndTime}</if>
         </where>
     </select>
-    
+
     <select id="selectFsUserCoursePeriodById" parameterType="Long" resultMap="FsUserCoursePeriodResult">
         <include refid="selectFsUserCoursePeriodVo"/>
         where period_id = #{periodId}
     </select>
-        
+
     <insert id="insertFsUserCoursePeriod" parameterType="FsUserCoursePeriod">
         insert into fs_user_course_period
         <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -43,9 +88,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">company_id,</if>
             <if test="courseId != null">course_id,</if>
             <if test="videoId != null">video_id,</if>
-            <if test="startingTime != null">starting_time,</if>
+            <if test="trainingCampId != null">training_camp_id,</if>
             <if test="createTime != null">create_time,</if>
             <if test="updateTime != null">update_time,</if>
+            <if test="courseStyle != null">course_style,</if>
+            <if test="liveRoomStyle != null">live_room_style,</if>
+            <if test="redPacketGrantMethod != null">red_packet_grant_method,</if>
+            <if test="periodType != null">period_type,</if>
+            <if test="periodStartingTime != null">period_starting_time,</if>
+            <if test="periodEndTime != null">period_end_time,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="periodId != null">#{periodId},</if>
@@ -53,9 +104,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">#{companyId},</if>
             <if test="courseId != null">#{courseId},</if>
             <if test="videoId != null">#{videoId},</if>
-            <if test="startingTime != null">#{startingTime},</if>
+            <if test="trainingCampId != null">#{trainingCampId},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="updateTime != null">#{updateTime},</if>
+            <if test="courseStyle != null">#{courseStyle},</if>
+            <if test="liveRoomStyle != null">#{liveRoomStyle},</if>
+            <if test="redPacketGrantMethod != null">#{redPacketGrantMethod},</if>
+            <if test="periodType != null">#{periodType},</if>
+            <if test="periodStartingTime != null">#{periodStartingTime},</if>
+            <if test="periodEndTime != null">#{periodEndTime},</if>
          </trim>
     </insert>
 
@@ -66,9 +123,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">company_id = #{companyId},</if>
             <if test="courseId != null">course_id = #{courseId},</if>
             <if test="videoId != null">video_id = #{videoId},</if>
-            <if test="startingTime != null">starting_time = #{startingTime},</if>
+            <if test="trainingCampId != null">training_camp_id = #{trainingCampId},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="courseStyle != null">course_style = #{courseStyle},</if>
+            <if test="liveRoomStyle != null">live_room_style = #{liveRoomStyle},</if>
+            <if test="redPacketGrantMethod != null">red_packet_grant_method = #{redPacketGrantMethod},</if>
+            <if test="periodType != null">period_type = #{periodType},</if>
+            <if test="periodStartingTime != null">period_starting_time = #{periodStartingTime},</if>
+            <if test="periodEndTime != null">period_end_time = #{periodEndTime},</if>
         </trim>
         where period_id = #{periodId}
     </update>
@@ -78,10 +141,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </delete>
 
     <delete id="deleteFsUserCoursePeriodByIds" parameterType="String">
-        delete from fs_user_course_period where period_id in 
+        delete from fs_user_course_period where period_id in
         <foreach item="periodId" collection="array" open="(" separator="," close=")">
             #{periodId}
         </foreach>
     </delete>
-    
-</mapper>
+
+</mapper>

+ 68 - 0
fs-service-system/src/main/resources/mapper/course/FsUserCourseTrainingCampMapper.xml

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.course.mapper.FsUserCourseTrainingCampMapper">
+
+    <resultMap type="FsUserCourseTrainingCamp" id="FsUserCourseTrainingCampResult">
+        <result property="trainingCampId"    column="training_camp_id"    />
+        <result property="trainingCampName"    column="training_camp_name"    />
+        <result property="orderNumber"    column="order_number"    />
+        <result property="createTime"    column="create_time"    />
+    </resultMap>
+
+    <sql id="selectFsUserCourseTrainingCampVo">
+        select training_camp_id, training_camp_name, order_number, create_time from fs_user_course_training_camp
+    </sql>
+
+    <select id="selectFsUserCourseTrainingCampList" parameterType="FsUserCourseTrainingCamp" resultMap="FsUserCourseTrainingCampResult">
+        <include refid="selectFsUserCourseTrainingCampVo"/>
+        <where>
+            <if test="training campName != null  and trainingCampName != ''"> and training_camp_name like concat('%', #{trainingCampName}, '%')</if>
+            <if test="orderNumber != null "> and order_number = #{orderNumber}</if>
+        </where>
+    </select>
+
+    <select id="selectFsUserCourseTrainingCampById" parameterType="Long" resultMap="FsUserCourseTrainingCampResult">
+        <include refid="selectFsUserCourseTrainingCampVo"/>
+        where training_camp_id = #{trainingCampId}
+    </select>
+
+    <insert id="insertFsUserCourseTrainingCamp" parameterType="FsUserCourseTrainingCamp">
+        insert into fs_user_course_training_camp
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="trainingCampId != null">training_camp_id,</if>
+            <if test="trainingCampName != null">training_camp_name,</if>
+            <if test="orderNumber != null">order_number,</if>
+            <if test="createTime != null">create_time,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="trainingCampId != null">#{trainingCampId},</if>
+            <if test="trainingCampName != null">#{trainingCampName},</if>
+            <if test="orderNumber != null">#{orderNumber},</if>
+            <if test="createTime != null">#{createTime},</if>
+         </trim>
+    </insert>
+
+    <update id="updateFsUserCourseTrainingCamp" parameterType="FsUserCourseTrainingCamp">
+        update fs_user_course_training_camp
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="trainingCampName != null">training_camp_name = #{trainingCampName},</if>
+            <if test="orderNumber != null">order_number = #{orderNumber},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+        </trim>
+        where training_camp_id = #{trainingCampId}
+    </update>
+
+    <delete id="deleteFsUserCourseTrainingCampById" parameterType="Long">
+        delete from fs_user_course_training_camp where training_camp_id = #{trainingCampId}
+    </delete>
+
+    <delete id="deleteFsUserCourseTrainingCampByIds" parameterType="String">
+        delete from fs_user_course_training_camp where training_camp_id in
+        <foreach item="trainingCampId" collection="array" open="(" separator="," close=")">
+            #{trainingCampId}
+        </foreach>
+    </delete>
+
+</mapper>

+ 16 - 0
fs-service-system/src/main/resources/mapper/course/FsVideoResourceMapper.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.course.mapper.FsVideoResourceMapper">
+
+    <select id="selectVideoResourceListByMap" resultType="com.fs.course.domain.FsVideoResource">
+        select
+            rr.*
+        from fs_video_resource rr
+        where rr.is_del = 0
+        <if test="params.resourceName != null and params.resourceName != ''">
+            and rr.resource_name like concat('%', #{params.resourceName}, '%')
+        </if>
+    </select>
+</mapper>

+ 13 - 0
fs-user-app/src/main/java/com/fs/app/controller/CourseWxH5Controller.java

@@ -12,12 +12,14 @@ import com.fs.course.param.FsCourseQuestionAnswerUParam;
 import com.fs.course.param.FsCourseSendRewardUParam;
 import com.fs.course.param.FsUserCourseVideoFinishUParam;
 import com.fs.course.param.newfs.FsUserCourseAddCompanyUserParam;
+import com.fs.course.param.newfs.FsUserCourseBeMemberParam;
 import com.fs.course.param.newfs.FsUserCourseVideoLinkParam;
 import com.fs.course.param.newfs.FsUserCourseVideoUParam;
 import com.fs.course.service.*;
 import com.fs.course.vo.FsUserCourseVideoH5VO;
 import com.fs.course.vo.newfs.FsUserCourseVideoDetailsVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoLinkDetailsVO;
+import com.fs.store.service.IFsUserService;
 import com.fs.system.service.ISysConfigService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -51,6 +53,9 @@ public class CourseWxH5Controller extends AppBaseController {
     @Autowired
     private IFsCourseQuestionBankService questionBankService;
 
+    @Autowired
+    private IFsUserService fsUserService;
+
 
     @Login
     @ApiOperation("判断是否添加客服(是否关联销售)")
@@ -124,4 +129,12 @@ public class CourseWxH5Controller extends AppBaseController {
         logger.error("zyp \n【h5看课中途报错】:{}",msg);
     }
 
+    @Login
+    @ApiOperation("会员关联绑定销售")
+    @PostMapping("/beMember")
+    public ResponseResult<Boolean> becomeMember(@Valid @RequestBody FsUserCourseBeMemberParam param) {
+        return fsUserService.becomeMember(param);
+    }
+
+
 }