吴树波 2 тижнів тому
батько
коміт
b8f75d6e00
20 змінених файлів з 874 додано та 135 видалено
  1. 3 2
      fs-common/src/main/java/com/fs/common/constant/FsConstants.java
  2. 4 2
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseFinishTempController.java
  3. 112 0
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseFinishTempParentController.java
  4. 24 0
      fs-company/src/main/java/com/fs/framework/redis/RedisConfiguration.java
  5. 68 0
      fs-company/src/main/java/com/fs/framework/redis/RedisKeyExpirationListener.java
  6. 1 0
      fs-generator/src/main/resources/vm/java/serviceImpl.java.vm
  7. 3 0
      fs-service/src/main/java/com/fs/course/config/CourseConfig.java
  8. 7 0
      fs-service/src/main/java/com/fs/course/domain/FsCourseFinishTemp.java
  9. 48 0
      fs-service/src/main/java/com/fs/course/domain/FsCourseFinishTempParent.java
  10. 9 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseFinishTempMapper.java
  11. 61 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseFinishTempParentMapper.java
  12. 61 0
      fs-service/src/main/java/com/fs/course/service/IFsCourseFinishTempParentService.java
  13. 11 1
      fs-service/src/main/java/com/fs/course/service/IFsCourseFinishTempService.java
  14. 126 0
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseFinishTempParentServiceImpl.java
  15. 65 10
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseFinishTempServiceImpl.java
  16. 12 2
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java
  17. 12 0
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  18. 152 118
      fs-service/src/main/java/com/fs/qw/service/impl/QwFriendWelcomeServiceImpl.java
  19. 12 0
      fs-service/src/main/resources/mapper/course/FsCourseFinishTempMapper.xml
  20. 83 0
      fs-service/src/main/resources/mapper/course/FsCourseFinishTempParentMapper.xml

+ 3 - 2
fs-common/src/main/java/com/fs/common/constant/FsConstants.java

@@ -1,12 +1,13 @@
 package com.fs.common.constant;
 
 
-public interface FsConstants
-{
+public interface FsConstants {
     String REDIS_INQUIRY_ORDER_OUTTIME_UNPAY = "inquiry:order:unpay:";
     String REDIS_INQUIRY_ORDER_OUTTIME_UNRECEIVE = "inquiry:order:unreceive:";
     String REDIS_PACKAGE_ORDER_UNPAY = "package:order:unpay:";
     String REDIS_CHAT_SESSION = "chat:session:";
     String REDIS_CHAT_NEXTCURSOR = "chat:nextcursor:";
     String REDIS_QW_appKey_Active = "qwActive:";
+
+    String FRIEND_WELCOME_VIDEO_KEY = "friend:welcome:";
 }

+ 4 - 2
fs-company/src/main/java/com/fs/company/controller/course/FsCourseFinishTempController.java

@@ -37,9 +37,10 @@ public class FsCourseFinishTempController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(FsCourseFinishTemp fsCourseFinishTemp)
     {
+        startPage();
+
         LoginUser loginUser = SecurityUtils.getLoginUser();
         fsCourseFinishTemp.setCompanyId(loginUser.getCompany().getCompanyId());
-        startPage();
         List<FsCourseFinishTempListVO> list = fsCourseFinishTempService.selectFsCourseFinishTempListVO(fsCourseFinishTemp);
         return getDataTable(list);
     }
@@ -65,7 +66,8 @@ public class FsCourseFinishTempController extends BaseController
     @GetMapping(value = "/{id}")
     public AjaxResult getInfo(@PathVariable("id") Long id)
     {
-        return AjaxResult.success(fsCourseFinishTempService.selectFsCourseFinishTempById(id));
+//        return AjaxResult.success(fsCourseFinishTempService.selectFsCourseFinishTempById(id));
+        return AjaxResult.success(fsCourseFinishTempService.selectFsCourseFinishTempByIdVO(id));
     }
 
     /**

+ 112 - 0
fs-company/src/main/java/com/fs/company/controller/course/FsCourseFinishTempParentController.java

@@ -0,0 +1,112 @@
+package com.fs.company.controller.course;
+
+import java.util.List;
+
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.security.SecurityUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.course.domain.FsCourseFinishTempParent;
+import com.fs.course.service.IFsCourseFinishTempParentService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 完课模板Controller
+ * 
+ * @author 吴树波
+ * @date 2025-05-22
+ */
+@RestController
+@RequestMapping("/course/courseFinishTempParent")
+public class FsCourseFinishTempParentController extends BaseController
+{
+    @Autowired
+    private IFsCourseFinishTempParentService fsCourseFinishTempParentService;
+
+    /**
+     * 查询完课模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsCourseFinishTempParent fsCourseFinishTempParent)
+    {
+        startPage();
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsCourseFinishTempParent.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<FsCourseFinishTempParent> list = fsCourseFinishTempParentService.selectFsCourseFinishTempParentList(fsCourseFinishTempParent);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出完课模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:export')")
+    @Log(title = "完课模板", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsCourseFinishTempParent fsCourseFinishTempParent)
+    {
+        List<FsCourseFinishTempParent> list = fsCourseFinishTempParentService.selectFsCourseFinishTempParentList(fsCourseFinishTempParent);
+        ExcelUtil<FsCourseFinishTempParent> util = new ExcelUtil<FsCourseFinishTempParent>(FsCourseFinishTempParent.class);
+        return util.exportExcel(list, "完课模板数据");
+    }
+
+    /**
+     * 获取完课模板详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsCourseFinishTempParentService.selectFsCourseFinishTempParentById(id));
+    }
+
+    /**
+     * 新增完课模板
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:add')")
+    @Log(title = "完课模板", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsCourseFinishTempParent fsCourseFinishTempParent){
+
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsCourseFinishTempParent.setCompanyId(loginUser.getCompany().getCompanyId());
+        return toAjax(fsCourseFinishTempParentService.insertFsCourseFinishTempParent(fsCourseFinishTempParent));
+    }
+
+    /**
+     * 修改完课模板
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:edit')")
+    @Log(title = "完课模板", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsCourseFinishTempParent fsCourseFinishTempParent)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsCourseFinishTempParent.setCompanyId(loginUser.getCompany().getCompanyId());
+        return toAjax(fsCourseFinishTempParentService.updateFsCourseFinishTempParent(fsCourseFinishTempParent));
+    }
+
+    /**
+     * 删除完课模板
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:remove')")
+    @Log(title = "完课模板", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsCourseFinishTempParentService.deleteFsCourseFinishTempParentByIds(ids));
+    }
+}

+ 24 - 0
fs-company/src/main/java/com/fs/framework/redis/RedisConfiguration.java

@@ -0,0 +1,24 @@
+package com.fs.framework.redis;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+
+@Configuration
+public class RedisConfiguration {
+    @Autowired
+    private RedisConnectionFactory redisConnectionFactory;
+
+    @Bean
+    public RedisMessageListenerContainer redisMessageListenerContainer() {
+        RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
+        redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
+        return redisMessageListenerContainer;
+    }
+
+
+
+}

+ 68 - 0
fs-company/src/main/java/com/fs/framework/redis/RedisKeyExpirationListener.java

@@ -0,0 +1,68 @@
+package com.fs.framework.redis;
+
+import com.alibaba.fastjson.JSON;
+import com.fs.common.constant.FsConstants;
+import com.fs.qw.service.IQwFriendWelcomeService;
+import com.fs.qw.service.impl.QwFriendWelcomeServiceImpl;
+import com.fs.qw.vo.QwFriendWelcomeDayPart;
+import com.fs.qw.vo.QwFriendWelcomeVO;
+import com.fs.qwApi.param.SendWelcomeMsgParam;
+import com.fs.qwApi.service.QwApiService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.connection.Message;
+import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+import org.springframework.stereotype.Component;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+@Slf4j
+@Component
+public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
+
+    @Autowired
+    private IQwFriendWelcomeService qwFriendWelcomeService;
+    @Autowired
+    private QwApiService qwApiService;
+
+    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
+        super(listenerContainer);
+    }
+
+    /**
+     * 针对redis数据失效事件,进行数据处理
+     * @param message
+     * @param pattern
+     */
+    @Override
+    public void onMessage(Message message, byte[] pattern) {
+        //过期的key
+        String key = new String(message.getBody(),StandardCharsets.UTF_8);
+        // 好友欢迎语过期判断
+        if(key.contains(FsConstants.FRIEND_WELCOME_VIDEO_KEY)) {
+            key = key.replace(FsConstants.FRIEND_WELCOME_VIDEO_KEY, "");
+            Long id = Long.parseLong(key.split(":")[0]);
+            QwFriendWelcomeVO vo = qwFriendWelcomeService.selectQwFriendWelcomeById(id);
+            List<SendWelcomeMsgParam.Attachment> list = JSON.parseArray(vo.getAttachments(), SendWelcomeMsgParam.Attachment.class);
+            list.forEach(e -> this.build(e, vo));
+            if (vo.getIsDayparting().equals("1")) {
+                List<QwFriendWelcomeDayPart.Schedule> schedules = JSON.parseArray(vo.getDaypartingItemlist(), QwFriendWelcomeDayPart.Schedule.class);
+                schedules.forEach(schedule -> {
+                    schedule.getAttachments().forEach(e -> this.build(e, vo));
+                });
+            }
+        }
+    }
+
+    public void build(SendWelcomeMsgParam.Attachment e, QwFriendWelcomeVO vo){
+        if(e.getMsgtype().equals("video")) {
+            try {
+                QwFriendWelcomeServiceImpl.uploadVideo(qwApiService, e, vo.getCorpId());
+            } catch (Exception ex) {
+                log.error("欢迎语视频重新上传失败", ex);
+            }
+        }
+    }
+}

+ 1 - 0
fs-generator/src/main/resources/vm/java/serviceImpl.java.vm

@@ -7,6 +7,7 @@ import com.fs.common.utils.DateUtils;
 #break
 #end
 #end
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 #if($table.sub)

+ 3 - 0
fs-service/src/main/java/com/fs/course/config/CourseConfig.java

@@ -28,6 +28,9 @@ public class CourseConfig implements Serializable {
     private BigDecimal moneyPri;//充值手续费百分比
     private BigDecimal redPackageMoney;//充值手续费百分比
     private List<DisabledTimeVo> disabledTimeList;//充值手续费百分比
+    private Integer completionMode; // 完课模式
+    private Integer minutesNum; //多少分钟算完课
+
 
     @Data
     public static class DisabledTimeVo{

+ 7 - 0
fs-service/src/main/java/com/fs/course/domain/FsCourseFinishTemp.java

@@ -30,6 +30,10 @@ public class FsCourseFinishTemp extends BaseEntity
     @Excel(name = "规则")
     private String setting;
 
+    /** 规则 */
+    @Excel(name = "规则")
+    private String chatSetting;
+
     /** 公司id */
     @Excel(name = "公司id")
     private Long companyId;
@@ -45,8 +49,11 @@ public class FsCourseFinishTemp extends BaseEntity
     /** 归属销售id(对多) */
     @Excel(name = "归属销售id(对多)")
     private String companyUserIds;
+    private Long parentId;
 
     /** 删除标志 */
     @Excel(name = "删除标志")
     private Long isDel;
+    @Excel(name = "删除标志")
+    private Integer isAllCompanyUser;
 }

+ 48 - 0
fs-service/src/main/java/com/fs/course/domain/FsCourseFinishTempParent.java

@@ -0,0 +1,48 @@
+package com.fs.course.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 完课模板对象 fs_course_finish_temp_parent
+ *
+ * @author 吴树波
+ * @date 2025-05-22
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsCourseFinishTempParent extends BaseEntity{
+
+    /** id */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** 名称 */
+    @Excel(name = "名称")
+    private String name;
+
+    /** 课程ID */
+    @Excel(name = "课程ID")
+    private Long courseId;
+
+    /** 公司ID */
+    @Excel(name = "公司ID")
+    private Long companyId;
+
+
+    @TableField(exist = false)
+    private Long status;
+    @TableField(exist = false)
+    private String setting;
+    @TableField(exist = false)
+    private String chatSetting;
+    @TableField(exist = false)
+    private String companyUserIds;
+    @TableField(exist = false)
+    private Integer isAllCompanyUser;
+}

+ 9 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseFinishTempMapper.java

@@ -3,6 +3,7 @@ package com.fs.course.mapper;
 import java.util.List;
 import com.fs.course.domain.FsCourseFinishTemp;
 import com.fs.course.vo.FsCourseFinishTempListVO;
+import com.fs.course.vo.FsCourseFinishTempVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
@@ -70,6 +71,9 @@ public interface FsCourseFinishTempMapper
             "<if test = ' maps.name !=null and maps.name!=\"\" '> " +
             "and t.name like concat('%', #{maps.name}, '%') " +
             "</if>" +
+            "<if test = ' maps.parentId !=null'> " +
+            "and t.parent_id = #{maps.parentId} " +
+            "</if>" +
             "<if test = ' maps.courseId !=null  '> " +
             "and t.course_id = #{maps.courseId} " +
             "</if>" +
@@ -102,4 +106,9 @@ public interface FsCourseFinishTempMapper
             "    ORDER BY create_time DESC\n" +
             "    LIMIT 1\n")
     FsCourseFinishTemp selectFsCourseFinishTempByCompanyId(@Param("userId") Long companyUserId,@Param("companyId") Long companyId, @Param("videoId")Long videoId);
+
+    @Select("SELECT * FROM fs_course_finish_temp WHERE id = #{id}")
+    public FsCourseFinishTempVO selectFsCourseFinishTempByIdVO(Long id);
+
+    void deleteByParentIds(@Param("ids") Long[] ids);
 }

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

@@ -0,0 +1,61 @@
+package com.fs.course.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.course.domain.FsCourseFinishTempParent;
+
+/**
+ * 完课模板Mapper接口
+ * 
+ * @author 吴树波
+ * @date 2025-05-22
+ */
+public interface FsCourseFinishTempParentMapper extends BaseMapper<FsCourseFinishTempParent>{
+    /**
+     * 查询完课模板
+     * 
+     * @param id 完课模板主键
+     * @return 完课模板
+     */
+    FsCourseFinishTempParent selectFsCourseFinishTempParentById(Long id);
+
+    /**
+     * 查询完课模板列表
+     * 
+     * @param fsCourseFinishTempParent 完课模板
+     * @return 完课模板集合
+     */
+    List<FsCourseFinishTempParent> selectFsCourseFinishTempParentList(FsCourseFinishTempParent fsCourseFinishTempParent);
+
+    /**
+     * 新增完课模板
+     * 
+     * @param fsCourseFinishTempParent 完课模板
+     * @return 结果
+     */
+    int insertFsCourseFinishTempParent(FsCourseFinishTempParent fsCourseFinishTempParent);
+
+    /**
+     * 修改完课模板
+     * 
+     * @param fsCourseFinishTempParent 完课模板
+     * @return 结果
+     */
+    int updateFsCourseFinishTempParent(FsCourseFinishTempParent fsCourseFinishTempParent);
+
+    /**
+     * 删除完课模板
+     * 
+     * @param id 完课模板主键
+     * @return 结果
+     */
+    int deleteFsCourseFinishTempParentById(Long id);
+
+    /**
+     * 批量删除完课模板
+     * 
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsCourseFinishTempParentByIds(Long[] ids);
+}

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

@@ -0,0 +1,61 @@
+package com.fs.course.service;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.course.domain.FsCourseFinishTempParent;
+
+/**
+ * 完课模板Service接口
+ * 
+ * @author 吴树波
+ * @date 2025-05-22
+ */
+public interface IFsCourseFinishTempParentService extends IService<FsCourseFinishTempParent>{
+    /**
+     * 查询完课模板
+     * 
+     * @param id 完课模板主键
+     * @return 完课模板
+     */
+    FsCourseFinishTempParent selectFsCourseFinishTempParentById(Long id);
+
+    /**
+     * 查询完课模板列表
+     * 
+     * @param fsCourseFinishTempParent 完课模板
+     * @return 完课模板集合
+     */
+    List<FsCourseFinishTempParent> selectFsCourseFinishTempParentList(FsCourseFinishTempParent fsCourseFinishTempParent);
+
+    /**
+     * 新增完课模板
+     * 
+     * @param fsCourseFinishTempParent 完课模板
+     * @return 结果
+     */
+    int insertFsCourseFinishTempParent(FsCourseFinishTempParent fsCourseFinishTempParent);
+
+    /**
+     * 修改完课模板
+     * 
+     * @param fsCourseFinishTempParent 完课模板
+     * @return 结果
+     */
+    int updateFsCourseFinishTempParent(FsCourseFinishTempParent fsCourseFinishTempParent);
+
+    /**
+     * 批量删除完课模板
+     * 
+     * @param ids 需要删除的完课模板主键集合
+     * @return 结果
+     */
+    int deleteFsCourseFinishTempParentByIds(Long[] ids);
+
+    /**
+     * 删除完课模板信息
+     * 
+     * @param id 完课模板主键
+     * @return 结果
+     */
+    int deleteFsCourseFinishTempParentById(Long id);
+}

+ 11 - 1
fs-service/src/main/java/com/fs/course/service/IFsCourseFinishTempService.java

@@ -1,8 +1,10 @@
 package com.fs.course.service;
 
-import java.util.List;
 import com.fs.course.domain.FsCourseFinishTemp;
 import com.fs.course.vo.FsCourseFinishTempListVO;
+import com.fs.course.vo.FsCourseFinishTempVO;
+
+import java.util.List;
 
 /**
  * 完课模板Service接口
@@ -19,6 +21,7 @@ public interface IFsCourseFinishTempService
      * @return 完课模板
      */
     public FsCourseFinishTemp selectFsCourseFinishTempById(Long id);
+    public FsCourseFinishTempVO selectFsCourseFinishTempByIdVO(Long id);
 
     /**
      * 查询完课模板列表
@@ -61,4 +64,11 @@ public interface IFsCourseFinishTempService
      * @return 结果
      */
     public int deleteFsCourseFinishTempById(Long id);
+
+    void deleteByParentIds(Long[] ids);
+
+    /**
+     * 将所有的CompanyUserId更新为 企业微信账号
+     */
+//    public void updateFsCourseFinishTempByCompanyUserId();
 }

+ 126 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCourseFinishTempParentServiceImpl.java

@@ -0,0 +1,126 @@
+package com.fs.course.service.impl;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.fs.common.utils.DateUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.course.domain.FsCourseFinishTemp;
+import com.fs.course.domain.FsUserCourse;
+import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.service.IFsCourseFinishTempService;
+import com.fs.course.service.IFsUserCourseService;
+import com.fs.course.service.IFsUserCourseVideoService;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.course.mapper.FsCourseFinishTempParentMapper;
+import com.fs.course.domain.FsCourseFinishTempParent;
+import com.fs.course.service.IFsCourseFinishTempParentService;
+
+/**
+ * 完课模板Service业务层处理
+ * 
+ * @author 吴树波
+ * @date 2025-05-22
+ */
+@Service
+@AllArgsConstructor
+public class FsCourseFinishTempParentServiceImpl extends ServiceImpl<FsCourseFinishTempParentMapper, FsCourseFinishTempParent> implements IFsCourseFinishTempParentService {
+
+    private final IFsUserCourseService fsUserCourseService;
+    private final IFsUserCourseVideoService fsUserCourseVideoService;
+    private final IFsCourseFinishTempService fsCourseFinishTempService;
+
+    /**
+     * 查询完课模板
+     * 
+     * @param id 完课模板主键
+     * @return 完课模板
+     */
+    @Override
+    public FsCourseFinishTempParent selectFsCourseFinishTempParentById(Long id)
+    {
+        return baseMapper.selectFsCourseFinishTempParentById(id);
+    }
+
+    /**
+     * 查询完课模板列表
+     * 
+     * @param fsCourseFinishTempParent 完课模板
+     * @return 完课模板
+     */
+    @Override
+    public List<FsCourseFinishTempParent> selectFsCourseFinishTempParentList(FsCourseFinishTempParent fsCourseFinishTempParent)
+    {
+        return baseMapper.selectFsCourseFinishTempParentList(fsCourseFinishTempParent);
+    }
+
+    /**
+     * 新增完课模板
+     * 
+     * @param fsCourseFinishTempParent 完课模板
+     * @return 结果
+     */
+    @Override
+    public int insertFsCourseFinishTempParent(FsCourseFinishTempParent fsCourseFinishTempParent){
+        Long courseId = fsCourseFinishTempParent.getCourseId();
+        FsUserCourseVideo fsUserCourseVideo = new FsUserCourseVideo();
+        fsUserCourseVideo.setCourseId(courseId);
+        List<FsUserCourseVideo> videoList = fsUserCourseVideoService.selectFsUserCourseVideoListByCourseId(fsUserCourseVideo);
+        int insert = baseMapper.insert(fsCourseFinishTempParent);
+        fsCourseFinishTempParent.setCreateTime(DateUtils.getNowDate());
+        videoList.forEach(e -> {
+            FsCourseFinishTemp temp = new FsCourseFinishTemp();
+            temp.setName(e.getFileName());
+            temp.setStatus(fsCourseFinishTempParent.getStatus());
+            temp.setSetting(fsCourseFinishTempParent.getSetting());
+            temp.setChatSetting(fsCourseFinishTempParent.getChatSetting());
+            temp.setCompanyId(fsCourseFinishTempParent.getCompanyId());
+            temp.setCourseId(e.getCourseId());
+            temp.setVideoId(e.getVideoId());
+            temp.setCompanyUserIds(fsCourseFinishTempParent.getCompanyUserIds());
+            temp.setIsAllCompanyUser(fsCourseFinishTempParent.getIsAllCompanyUser());
+            temp.setParentId(fsCourseFinishTempParent.getId());
+            fsCourseFinishTempService.insertFsCourseFinishTemp(temp);
+        });
+        return insert;
+    }
+
+    /**
+     * 修改完课模板
+     * 
+     * @param fsCourseFinishTempParent 完课模板
+     * @return 结果
+     */
+    @Override
+    public int updateFsCourseFinishTempParent(FsCourseFinishTempParent fsCourseFinishTempParent)
+    {
+        fsCourseFinishTempParent.setUpdateTime(DateUtils.getNowDate());
+        return baseMapper.updateById(fsCourseFinishTempParent);
+    }
+
+    /**
+     * 批量删除完课模板
+     * 
+     * @param ids 需要删除的完课模板主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsCourseFinishTempParentByIds(Long[] ids){
+        int i = baseMapper.deleteFsCourseFinishTempParentByIds(ids);
+        fsCourseFinishTempService.deleteByParentIds(ids);
+        return i;
+    }
+
+    /**
+     * 删除完课模板信息
+     * 
+     * @param id 完课模板主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsCourseFinishTempParentById(Long id){
+        return deleteFsCourseFinishTempParentByIds(new Long[]{id});
+    }
+}

+ 65 - 10
fs-service/src/main/java/com/fs/course/service/impl/FsCourseFinishTempServiceImpl.java

@@ -1,24 +1,25 @@
 package com.fs.course.service.impl;
 
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Consumer;
-
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.fs.common.utils.DateUtils;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.course.domain.FsCourseFinishTemp;
+import com.fs.course.mapper.FsCourseFinishTempMapper;
+import com.fs.course.service.IFsCourseFinishTempService;
 import com.fs.course.vo.FsCourseFinishTempListVO;
+import com.fs.course.vo.FsCourseFinishTempVO;
 import com.fs.fastGpt.domain.FastGptChatReplaceWords;
 import com.fs.fastGpt.mapper.FastGptChatReplaceWordsMapper;
-import com.fs.fastgptApi.util.AudioUtils;
-import com.fs.fastgptApi.vo.AudioVO;
+import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.vo.QwSopCourseFinishTempSetting;
-import com.fs.qw.vo.QwSopTempSetting;
+import com.fs.qw.vo.QwUserVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.fs.course.mapper.FsCourseFinishTempMapper;
-import com.fs.course.domain.FsCourseFinishTemp;
-import com.fs.course.service.IFsCourseFinishTempService;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Consumer;
 
 /**
  * 完课模板Service业务层处理
@@ -35,6 +36,12 @@ public class FsCourseFinishTempServiceImpl implements IFsCourseFinishTempService
     @Autowired
     private FastGptChatReplaceWordsMapper fastGptChatReplaceWordsMapper;
 
+    @Autowired
+    private QwUserMapper qwUserMapper;
+
+    @Autowired
+    private CompanyUserMapper companyUserMapper;
+
     /**
      * 查询完课模板
      *
@@ -47,6 +54,19 @@ public class FsCourseFinishTempServiceImpl implements IFsCourseFinishTempService
         return fsCourseFinishTempMapper.selectFsCourseFinishTempById(id);
     }
 
+    @Override
+    public FsCourseFinishTempVO selectFsCourseFinishTempByIdVO(Long id) {
+        FsCourseFinishTempVO fsCourseFinishTemp = fsCourseFinishTempMapper.selectFsCourseFinishTempByIdVO(id);
+
+        String companyUserIds = fsCourseFinishTemp.getCompanyUserIds();
+        List<String> qwUserIdsList = Arrays.asList(companyUserIds.split(","));
+
+        List<QwUserVO> qwUserByIds = qwUserMapper.getQwUserByIdsNoCropId(qwUserIdsList);
+        fsCourseFinishTemp.setUserSelectList(qwUserByIds);
+
+        return fsCourseFinishTemp;
+    }
+
     /**
      * 查询完课模板列表
      *
@@ -72,6 +92,7 @@ public class FsCourseFinishTempServiceImpl implements IFsCourseFinishTempService
 
         //清理一下违禁词
         fsCourseFinishTemp.setSetting(JSON.toJSONString(processAndReplaceCrouseContent(fsCourseFinishTemp.getSetting())));
+        fsCourseFinishTemp.setChatSetting(JSON.toJSONString(processAndReplaceCrouseContent(fsCourseFinishTemp.getChatSetting())));
 
         return fsCourseFinishTempMapper.insertFsCourseFinishTemp(fsCourseFinishTemp);
     }
@@ -149,6 +170,40 @@ public class FsCourseFinishTempServiceImpl implements IFsCourseFinishTempService
         return fsCourseFinishTempMapper.deleteFsCourseFinishTempById(id);
     }
 
+    @Override
+    public void deleteByParentIds(Long[] ids) {
+        fsCourseFinishTempMapper.deleteByParentIds(ids);
+    }
+
+//    @Override
+//    public void updateFsCourseFinishTempByCompanyUserId() {
+//        List<FsCourseFinishTemp> fsCourseFinishTemps = fsCourseFinishTempMapper.selectFsCourseFinishTempByCompanyList();
+//        fsCourseFinishTemps.forEach(item -> {
+//            List<String> qwUserList = new ArrayList<>();
+//            if (!StringUtil.strIsNullOrEmpty(item.getCompanyUserIds())) {
+//                // 分割 companyUserIds 并清理空格
+//                Arrays.stream(item.getCompanyUserIds().split("\\s*,\\s*"))
+//                        .forEach(userId -> {
+//                            if (!StringUtil.strIsNullOrEmpty(userId)){
+//                                CompanyUser companyUser = companyUserMapper.selectCompanyUserById(Long.valueOf(userId.trim()));
+//                                if (companyUser != null && !StringUtil.strIsNullOrEmpty(companyUser.getQwUserId())) {
+//                                    // 分割 qwUserId 并清理空格
+//                                    List<String> cleanedQwUserIds = Arrays.stream(companyUser.getQwUserId().split("\\s*,\\s*"))
+//                                            .map(String::trim)
+//                                            .filter(s -> !s.isEmpty())  // 过滤空字符串
+//                                            .collect(Collectors.toList());
+//                                    qwUserList.addAll(cleanedQwUserIds);
+//                                }
+//                            }
+//                        });
+//                String join = String.join(",", qwUserList);
+//                item.setCompanyUserIds(join);
+//                fsCourseFinishTempMapper.updateFsCourseFinishTemp(item);
+//
+//            }
+//        });
+//    }
+
 
     @Override
     public List<FsCourseFinishTempListVO> selectFsCourseFinishTempListVO(FsCourseFinishTemp fsCourseFinishTemp) {

+ 12 - 2
fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java

@@ -324,9 +324,19 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
             //取对应视频的时长
             Long videoDuration = getVideoDuration(videoId);
             if (videoDuration != null && videoDuration != 0) {
+                boolean complete = false;
+                // 判断百分比
+                if(config.getCompletionMode() == 1 && config.getAnswerRate() != null){
+                    long percentage = (duration * 100 / videoDuration);
+                    complete = percentage >= config.getAnswerRate();
+                }
+                // 判断分钟数
+                if(config.getCompletionMode() == 2 && config.getMinutesNum() != null){
+                    int i = config.getMinutesNum() * 60;
+                    complete = videoDuration > i;
+                }
                 //判断是否完课
-                long percentage = (duration * 100 / videoDuration);
-                if (percentage >= config.getAnswerRate()) {
+                if (complete) {
                     watchLog.setLogType(2); // 设置状态为“已完成”
                     watchLog.setFinishTime(new Date());
                     String heartbeatKey ="h5user:watch:heartbeat:" + qwUserId+ ":" + externalId + ":" + videoId;

+ 12 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java

@@ -355,4 +355,16 @@ public interface QwUserMapper extends BaseMapper<QwUser>
 
     @Select("select company_id from qw_user where corp_id = #{corpId} and qw_user_id = #{qwUserid}")
     Long getQwUserCompanyId(@Param("corpId") String corpId, @Param("qwUserid") String qwUserid);
+
+    @Select("<script>" +
+            "select cu.user_name,cu.nick_name,cu.user_id,qu.qw_user_id ,qu.qw_user_name,qu.id from company_user cu " +
+            "LEFT JOIN  qw_user qu " +
+            "ON qu.company_user_id=cu.user_id  " +
+            "where cu.del_flag = 0 and  cu.qw_user_id is not null " +
+            "AND qu.id IN " +
+            "<foreach collection='qwUserIds' item='id' open='(' separator=',' close=')'> " +
+            "#{id} " +
+            "</foreach> " +
+            "</script>")
+    public List<QwUserVO> getQwUserByIdsNoCropId(@Param("qwUserIds") List<String> qwUserIds);
 }

+ 152 - 118
fs-service/src/main/java/com/fs/qw/service/impl/QwFriendWelcomeServiceImpl.java

@@ -1,8 +1,10 @@
 package com.fs.qw.service.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.fs.common.constant.FsConstants;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCacheT;
+import com.fs.common.exception.base.BaseException;
 import com.fs.qw.domain.QwFriendWelcome;
 import com.fs.qw.mapper.QwFriendWelcomeItemMapper;
 import com.fs.qw.mapper.QwFriendWelcomeMapper;
@@ -14,7 +16,6 @@ import com.fs.qw.vo.QwFriendWelcomeVO;
 import com.fs.qw.vo.QwUserVO;
 import com.fs.qwApi.Result.QwUploadImgResult;
 import com.fs.qwApi.Result.QwUploadResult;
-import com.fs.qwApi.param.QwWelcomeVideoParam;
 import com.fs.qwApi.param.SendWelcomeMsgParam;
 import com.fs.qwApi.service.QwApiService;
 import com.fs.voice.utils.StringUtil;
@@ -30,6 +31,7 @@ import java.net.URL;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 /**
  * 好友欢迎语Service业务层处理
@@ -38,13 +40,12 @@ import java.util.List;
  * @date 2024-07-20
  */
 @Service
-public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
-{
+public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService {
     @Autowired
     private QwFriendWelcomeMapper qwFriendWelcomeMapper;
 
     @Autowired
-    private QwFriendWelcomeItemMapper  qwFriendWelcomeItemMapper;
+    private QwFriendWelcomeItemMapper qwFriendWelcomeItemMapper;
 
     @Autowired
     private QwUserMapper qwUserMapper;
@@ -53,7 +54,7 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
     private QwApiService qwApiService;
 
     @Autowired
-    private RedisCacheT<QwWelcomeVideoParam> redisCache;
+    private RedisCacheT<Long> redisCache;
 
     /**
      * 查询好友欢迎语
@@ -62,8 +63,7 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
      * @return 好友欢迎语
      */
     @Override
-    public QwFriendWelcomeVO selectQwFriendWelcomeById(Long id)
-    {
+    public QwFriendWelcomeVO selectQwFriendWelcomeById(Long id) {
         QwFriendWelcomeVO qwFriendWelcomeVO = qwFriendWelcomeMapper.selectQwFriendWelcomeByIdVO(id);
 
         // 假设 qwFriendWelcomeVO 是已经初始化的对象
@@ -75,7 +75,7 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
         // 将字符串转换为列表
         List<String> qwUserIdsList = Arrays.asList(sanitizedQwUserIds.split(","));
 
-        List<QwUserVO> qwUserByIds = qwUserMapper.getQwUserByIds(qwUserIdsList,qwFriendWelcomeVO.getCorpId());
+        List<QwUserVO> qwUserByIds = qwUserMapper.getQwUserByIds(qwUserIdsList, qwFriendWelcomeVO.getCorpId());
         qwFriendWelcomeVO.setUserSelectList(qwUserByIds);
 
         return qwFriendWelcomeVO;
@@ -88,8 +88,7 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
      * @return 好友欢迎语
      */
     @Override
-    public List<QwFriendWelcome> selectQwFriendWelcomeListVO(QwFriendWelcomeParam qwFriendWelcomeParam)
-    {
+    public List<QwFriendWelcome> selectQwFriendWelcomeListVO(QwFriendWelcomeParam qwFriendWelcomeParam) {
         return qwFriendWelcomeMapper.selectQwFriendWelcomeListVO(qwFriendWelcomeParam);
     }
 
@@ -105,56 +104,53 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
      * @return 结果
      */
     @Override
-    public R insertQwFriendWelcomeVO(QwFriendWelcomeParam qwFriendWelcomeParam){
+    public R insertQwFriendWelcomeVO(QwFriendWelcomeParam qwFriendWelcomeParam) {
         List<SendWelcomeMsgParam.Attachment> attachmentsAll = JSON.parseArray(qwFriendWelcomeParam.getAttachments(), SendWelcomeMsgParam.Attachment.class);
-
-        if(attachmentsAll!=null && !attachmentsAll.isEmpty()){
-
+        boolean video = false;
+        if (attachmentsAll != null && !attachmentsAll.isEmpty()) {
+            String corpId = qwFriendWelcomeParam.getCorpId();
             for (SendWelcomeMsgParam.Attachment attachment : attachmentsAll) {
 
-                if (attachment.getMsgtype().equals("image")){
+                if (attachment.getMsgtype().equals("image")) {
 
                     try {
                         QwUploadImgResult uploadimg = qwApiService.uploadimgs(attachment.getImage().getPic_url(), qwFriendWelcomeParam.getCorpId());
-                        if (uploadimg.getErrcode()==0) {
+                        if (uploadimg.getErrcode() == 0) {
                             attachment.getImage().setPic_url(uploadimg.getUrl());
-                        }else {
-                            return R.error("图片image上传失败:"+uploadimg.getErrMsg());
+                        } else {
+                            return R.error("图片image上传失败:" + uploadimg.getErrMsg());
                         }
                     } catch (Exception e) {
-                        return R.error("图片image上传出错:"+e);
+                        return R.error("图片image上传出错:" + e);
 //                        throw new RuntimeException("insertQwFriendWelcomeVO-attachment/image:"+e);
                     }
                 }
-
-                if (attachment.getMsgtype().equals("video")){
-
+                if (attachment.getMsgtype().equals("video")) {
+                    if(!video){
+                        video = true;
+                    }
                     try {
-                        QwUploadResult result = qwApiService.upload(new File(""), "video", qwFriendWelcomeParam.getCorpId());
-                        if (result.getErrCode()==0) {
-                            attachment.getVideo().setMedia_id(result.getMediaId());
-                        }else {
-                            return R.error("视频上传失败:"+result.getErrMsg());
-                        }
+                        uploadVideo(qwApiService, attachment, corpId);
+                    } catch (BaseException e) {
+                        return R.error(e.getMessage());
                     } catch (Exception e) {
-                        return R.error("视频上传出错:"+e);
+                        return R.error("视频上传出错:" + e);
                     }
                 }
-
-                if (attachment.getMsgtype().equals("link")){
+                if (attachment.getMsgtype().equals("link")) {
                     String LinkPicUrl = attachment.getLink().getPicurl();
-                    if (LinkPicUrl!=null && !LinkPicUrl.isEmpty()){
+                    if (LinkPicUrl != null && !LinkPicUrl.isEmpty()) {
                         try {
                             QwUploadImgResult uploadimg = qwApiService.uploadimgs(LinkPicUrl, qwFriendWelcomeParam.getCorpId());
-                            if (uploadimg.getErrcode()==0){
+                            if (uploadimg.getErrcode() == 0) {
                                 attachment.getLink().setPicurl(uploadimg.getUrl());
-                            }else {
-                                return R.error("图片link上传失败:"+uploadimg.getErrMsg());
+                            } else {
+                                return R.error("图片link上传失败:" + uploadimg.getErrMsg());
                             }
 
 
                         } catch (Exception e) {
-                            return R.error("图片link上传出错:"+e);
+                            return R.error("图片link上传出错:" + e);
 //                            throw new RuntimeException("insertQwFriendWelcomeVO-attachment/link:"+e);
                         }
                     }
@@ -165,50 +161,50 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
             qwFriendWelcomeParam.setAttachments(JSON.toJSONString(attachmentsAll));
         }
 
-        if (qwFriendWelcomeParam.getIsDayparting()==1){
+        if (qwFriendWelcomeParam.getIsDayparting() == 1) {
             List<QwFriendWelcomeDayPart.Schedule> schedules = JSON.parseArray(qwFriendWelcomeParam.getDaypartingItemlist(), QwFriendWelcomeDayPart.Schedule.class);
-            if(schedules!=null && !schedules.isEmpty()){
+            if (schedules != null && !schedules.isEmpty()) {
 
                 for (QwFriendWelcomeDayPart.Schedule schedule : schedules) {
-
-                    for (SendWelcomeMsgParam.Attachment attachment: schedule.getAttachments() ) {
-                        if (attachment.getMsgtype().equals("image")){
+                    String corpId = qwFriendWelcomeParam.getCorpId();
+                    for (SendWelcomeMsgParam.Attachment attachment : schedule.getAttachments()) {
+                        if (attachment.getMsgtype().equals("image")) {
                             try {
-                                QwUploadImgResult uploadimg = qwApiService.uploadimgs(attachment.getImage().getPic_url(), qwFriendWelcomeParam.getCorpId());
-                                if (uploadimg.getErrcode()==0) {
+                                QwUploadImgResult uploadimg = qwApiService.uploadimgs(attachment.getImage().getPic_url(), corpId);
+                                if (uploadimg.getErrcode() == 0) {
                                     attachment.getImage().setPic_url(uploadimg.getUrl());
-                                }else {
-                                    return R.error("分时段图片image上传失败:"+uploadimg.getErrMsg());
+                                } else {
+                                    return R.error("分时段图片image上传失败:" + uploadimg.getErrMsg());
                                 }
                             } catch (Exception e) {
-                                return R.error("分时段图片image上传出错:"+e);
+                                return R.error("分时段图片image上传出错:" + e);
                             }
                         }
-                        if (attachment.getMsgtype().equals("video")){
+                        if (attachment.getMsgtype().equals("video")) {
+                            if(!video){
+                                video = true;
+                            }
                             try {
-                                QwUploadResult result = qwApiService.upload(new File(""), "video", qwFriendWelcomeParam.getCorpId());
-                                if (result.getErrCode()==0) {
-                                    attachment.getVideo().setMedia_id(result.getMediaId());
-                                }else {
-                                    return R.error("视频上传失败:"+result.getErrMsg());
-                                }
+                                uploadVideo(qwApiService, attachment, corpId);
+                            } catch (BaseException e) {
+                                return R.error(e.getMessage());
                             } catch (Exception e) {
-                                return R.error("视频上传出错:"+e);
+                                return R.error("视频上传出错:" + e);
                             }
                         }
-                        if (attachment.getMsgtype().equals("link")){
+                        if (attachment.getMsgtype().equals("link")) {
                             String linkPicurl = attachment.getLink().getPicurl();
-                            if (linkPicurl!=null && !linkPicurl.isEmpty()){
+                            if (linkPicurl != null && !linkPicurl.isEmpty()) {
                                 try {
-                                    QwUploadImgResult uploadimg = qwApiService.uploadimgs(linkPicurl, qwFriendWelcomeParam.getCorpId());
-                                    if (uploadimg.getErrcode()==0){
+                                    QwUploadImgResult uploadimg = qwApiService.uploadimgs(linkPicurl, corpId);
+                                    if (uploadimg.getErrcode() == 0) {
                                         attachment.getLink().setPicurl(uploadimg.getUrl());
-                                    }else {
-                                        return R.error("分时段图片link上传失败:"+uploadimg.getErrMsg());
+                                    } else {
+                                        return R.error("分时段图片link上传失败:" + uploadimg.getErrMsg());
                                     }
 
                                 } catch (Exception e) {
-                                    return R.error("分时段图片link上传出错:"+e);
+                                    return R.error("分时段图片link上传出错:" + e);
                                 }
                             }
                         }
@@ -218,16 +214,27 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
             }
             qwFriendWelcomeParam.setDaypartingItemlist(JSON.toJSONString(schedules));
         }
-
         int i = qwFriendWelcomeMapper.insertQwFriendWelcomeVO(qwFriendWelcomeParam);
-        if (i>0){
+        if(video){
+            redisCache.setCacheObject(FsConstants.FRIEND_WELCOME_VIDEO_KEY + qwFriendWelcomeParam.getId(), qwFriendWelcomeParam.getId(), 60, TimeUnit.HOURS);
+        }
+        if (i > 0) {
             return R.ok("新增成功");
-        }else {
+        } else {
             return R.error("新增失败");
         }
 
     }
 
+    public static void uploadVideo(QwApiService qwApiService, SendWelcomeMsgParam.Attachment attachment, String corpId) throws Exception {
+        QwUploadResult result = qwApiService.upload(urlToFile(attachment.getVideo().getUrl()), "video", corpId);
+        if (result.getErrCode() == 0) {
+            attachment.getVideo().setMedia_id(result.getMediaId());
+        } else {
+            throw new BaseException("视频上传失败:" + result.getErrMsg());
+        }
+    }
+
     /**
      * 修改好友欢迎语
      *
@@ -235,44 +242,55 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
      * @return 结果
      */
     @Override
-    public R updateQwFriendWelcome(QwFriendWelcome qwFriendWelcome)
-    {
+    public R updateQwFriendWelcome(QwFriendWelcome qwFriendWelcome) {
         List<SendWelcomeMsgParam.Attachment> attachmentsAll = JSON.parseArray(qwFriendWelcome.getAttachments(), SendWelcomeMsgParam.Attachment.class);
-
-        if(attachmentsAll!=null && !attachmentsAll.isEmpty()){
+        boolean video = false;
+        if (attachmentsAll != null && !attachmentsAll.isEmpty()) {
 
             for (SendWelcomeMsgParam.Attachment attachment : attachmentsAll) {
+                String corpId = qwFriendWelcome.getCorpId();
+                if (attachment.getMsgtype().equals("image") && !attachment.getImage().getPic_url().contains("https://wework.qpic.cn")) {
 
-                if (attachment.getMsgtype().equals("image")&&!attachment.getImage().getPic_url().contains("https://wework.qpic.cn")){
-
-                        try {
-                            QwUploadImgResult uploadimg = qwApiService.uploadimgs(attachment.getImage().getPic_url(), qwFriendWelcome.getCorpId());
-                            if (uploadimg.getErrcode()==0){
-                                attachment.getImage().setPic_url(uploadimg.getUrl());
-                            }else {
-                                return  R.error("上传好友欢迎语图片image失败:"+uploadimg.getErrMsg());
-                            }
-
-                        } catch (Exception e) {
-                            return  R.error("上传好友欢迎语图片出错:"+e);
+                    try {
+                        QwUploadImgResult uploadimg = qwApiService.uploadimgs(attachment.getImage().getPic_url(), corpId);
+                        if (uploadimg.getErrcode() == 0) {
+                            attachment.getImage().setPic_url(uploadimg.getUrl());
+                        } else {
+                            return R.error("上传好友欢迎语图片image失败:" + uploadimg.getErrMsg());
                         }
 
+                    } catch (Exception e) {
+                        return R.error("上传好友欢迎语图片出错:" + e);
+                    }
+
 
                 }
+                if (attachment.getMsgtype().equals("video")) {
+                    if(!video){
+                        video = true;
+                    }
+                    try {
+                        uploadVideo(qwApiService, attachment, corpId);
+                    } catch (BaseException e) {
+                        return R.error(e.getMessage());
+                    } catch (Exception e) {
+                        return R.error("视频上传出错:" + e);
+                    }
+                }
 
-                if (attachment.getMsgtype().equals("link")){
+                if (attachment.getMsgtype().equals("link")) {
                     String LinkPicUrl = attachment.getLink().getPicurl();
-                    if (LinkPicUrl!=null && !LinkPicUrl.isEmpty()&&!LinkPicUrl.contains("https://wework.qpic.cn")){
+                    if (LinkPicUrl != null && !LinkPicUrl.isEmpty() && !LinkPicUrl.contains("https://wework.qpic.cn")) {
                         try {
-                            QwUploadImgResult uploadimg = qwApiService.uploadimgs(LinkPicUrl, qwFriendWelcome.getCorpId());
-                            if (uploadimg.getErrcode()==0){
+                            QwUploadImgResult uploadimg = qwApiService.uploadimgs(LinkPicUrl, corpId);
+                            if (uploadimg.getErrcode() == 0) {
                                 attachment.getLink().setPicurl(uploadimg.getUrl());
-                            }else {
-                                return  R.error("上传好友欢迎语图片link失败:"+uploadimg.getErrMsg());
+                            } else {
+                                return R.error("上传好友欢迎语图片link失败:" + uploadimg.getErrMsg());
                             }
 
                         } catch (Exception e) {
-                            return  R.error("上传好友欢迎语图片link出错:"+e);
+                            return R.error("上传好友欢迎语图片link出错:" + e);
                         }
                     }
 
@@ -282,38 +300,50 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
             qwFriendWelcome.setAttachments(JSON.toJSONString(attachmentsAll));
         }
 
-        if (qwFriendWelcome.getIsDayparting().equals("1")){
+        if (qwFriendWelcome.getIsDayparting().equals("1")) {
             List<QwFriendWelcomeDayPart.Schedule> schedules = JSON.parseArray(qwFriendWelcome.getDaypartingItemlist(), QwFriendWelcomeDayPart.Schedule.class);
-            if(schedules!=null && !schedules.isEmpty()){
+            if (schedules != null && !schedules.isEmpty()) {
 
                 for (QwFriendWelcomeDayPart.Schedule schedule : schedules) {
-
-                    for(SendWelcomeMsgParam.Attachment attachment:schedule.getAttachments()){
-                        if (attachment.getMsgtype().equals("image")&&!attachment.getImage().getPic_url().contains("https://wework.qpic.cn")){
+                    String corpId = qwFriendWelcome.getCorpId();
+                    for (SendWelcomeMsgParam.Attachment attachment : schedule.getAttachments()) {
+                        if (attachment.getMsgtype().equals("image") && !attachment.getImage().getPic_url().contains("https://wework.qpic.cn")) {
                             try {
-                                QwUploadImgResult uploadimg = qwApiService.uploadimgs(attachment.getImage().getPic_url(), qwFriendWelcome.getCorpId());
-                                if (uploadimg.getErrcode()==0){
+                                QwUploadImgResult uploadimg = qwApiService.uploadimgs(attachment.getImage().getPic_url(), corpId);
+                                if (uploadimg.getErrcode() == 0) {
                                     attachment.getImage().setPic_url(uploadimg.getUrl());
-                                }else {
-                                    return  R.error("上传分时段好友欢迎语图片image失败:"+uploadimg.getErrMsg());
+                                } else {
+                                    return R.error("上传分时段好友欢迎语图片image失败:" + uploadimg.getErrMsg());
                                 }
                             } catch (Exception e) {
-                                return  R.error("上传分时段好友欢迎语图片image出错:"+e);
+                                return R.error("上传分时段好友欢迎语图片image出错:" + e);
+                            }
+                        }
+                        if (attachment.getMsgtype().equals("video")) {
+                            if(!video){
+                                video = true;
+                            }
+                            try {
+                                uploadVideo(qwApiService, attachment, corpId);
+                            } catch (BaseException e) {
+                                return R.error(e.getMessage());
+                            } catch (Exception e) {
+                                return R.error("视频上传出错:" + e);
                             }
                         }
-                        if (attachment.getMsgtype().equals("link")){
+                        if (attachment.getMsgtype().equals("link")) {
                             String linkPicurl = attachment.getLink().getPicurl();
-                            if (linkPicurl!=null && !linkPicurl.isEmpty()&&!linkPicurl.contains("https://wework.qpic.cn")){
+                            if (linkPicurl != null && !linkPicurl.isEmpty() && !linkPicurl.contains("https://wework.qpic.cn")) {
                                 try {
-                                    QwUploadImgResult uploadimg = qwApiService.uploadimgs(linkPicurl, qwFriendWelcome.getCorpId());
-                                    if (uploadimg.getErrcode()==0){
+                                    QwUploadImgResult uploadimg = qwApiService.uploadimgs(linkPicurl, corpId);
+                                    if (uploadimg.getErrcode() == 0) {
                                         attachment.getLink().setPicurl(uploadimg.getUrl());
-                                    }else {
-                                        return  R.error("上传分时段好友欢迎语图片link失败:"+uploadimg.getErrMsg());
+                                    } else {
+                                        return R.error("上传分时段好友欢迎语图片link失败:" + uploadimg.getErrMsg());
                                     }
 
                                 } catch (Exception e) {
-                                    return  R.error("上传分时段好友欢迎语图片link出错:"+ e);
+                                    return R.error("上传分时段好友欢迎语图片link出错:" + e);
                                 }
                             }
                         }
@@ -323,7 +353,11 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
             }
             qwFriendWelcome.setDaypartingItemlist(JSON.toJSONString(schedules));
         }
-
+        String key = FsConstants.FRIEND_WELCOME_VIDEO_KEY + qwFriendWelcome.getId();
+        redisCache.deleteObject(key);
+        if(video){
+            redisCache.setCacheObject(key, qwFriendWelcome.getId(), 60, TimeUnit.HOURS);
+        }
         return R.ok().put("msg", qwFriendWelcomeMapper.updateQwFriendWelcome(qwFriendWelcome));
     }
 
@@ -334,8 +368,7 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
      * @return 结果
      */
     @Override
-    public int deleteQwFriendWelcomeByIds(Long[] ids)
-    {
+    public int deleteQwFriendWelcomeByIds(Long[] ids) {
         return qwFriendWelcomeMapper.deleteQwFriendWelcomeByIds(ids);
     }
 
@@ -346,24 +379,23 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
      * @return 结果
      */
     @Override
-    public int deleteQwFriendWelcomeById(Long id)
-    {
+    public int deleteQwFriendWelcomeById(Long id) {
         return qwFriendWelcomeMapper.deleteQwFriendWelcomeById(id);
     }
 
     /**
-     *  url转临时文件filr
+     * url转临时文件filr
      */
     public static File urlToFile(String fileUrl) throws Exception {
 
         // 从URL中提取文件名,文件后缀
         String fileExtension = getFileExtension(new File(fileUrl).getName());
-        String fileName = extractFileName(new URL(fileUrl))+new Date().getTime();
-        File tempFile=null;
-        if (!StringUtil.strIsNullOrEmpty(fileExtension)){
+        String fileName = extractFileName(new URL(fileUrl)) + new Date().getTime();
+        File tempFile = null;
+        if (!StringUtil.strIsNullOrEmpty(fileExtension)) {
             // 创建一个临时文件
-            tempFile = File.createTempFile(fileName, "."+fileExtension);
-        }else {
+            tempFile = File.createTempFile(fileName, "." + fileExtension);
+        } else {
             tempFile = File.createTempFile(fileName, null);
         }
 
@@ -388,8 +420,9 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
 
         return tempFile;
     }
+
     /**
-     *  获取文件名
+     * 获取文件名
      */
     private static String extractFileName(URL url) throws Exception {
         String path = url.getPath();
@@ -410,7 +443,7 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
     }
 
     /**
-     *  获取文件名后缀
+     * 获取文件名后缀
      */
 
     public static String getFileExtension(String fileName) {
@@ -421,5 +454,6 @@ public class QwFriendWelcomeServiceImpl implements IQwFriendWelcomeService
         return ""; // 如果没有扩展名,返回空字符串
     }
 
-    public static void uploadFileImage(MultipartFile file, String filePath){}
+    public static void uploadFileImage(MultipartFile file, String filePath) {
+    }
 }

+ 12 - 0
fs-service/src/main/resources/mapper/course/FsCourseFinishTempMapper.xml

@@ -56,6 +56,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyUserIds != null">company_user_ids,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="isDel != null">is_del,</if>
+            <if test="chatSetting != null">chat_setting,</if>
+            <if test="parentId != null">parent_id,</if>
+            <if test="isAllCompanyUser != null">is_all_company_user,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="name != null">#{name},</if>
@@ -69,6 +72,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyUserIds != null">#{companyUserIds},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="isDel != null">#{isDel},</if>
+            <if test="chatSetting != null">#{chatSetting},</if>
+            <if test="parentId != null">#{parentId},</if>
+            <if test="isAllCompanyUser != null">#{isAllCompanyUser},</if>
          </trim>
     </insert>
 
@@ -100,4 +106,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{id}
         </foreach>
     </delete>
+    <delete id="deleteByParentIds">
+        update fs_course_finish_temp set is_del = 1 where parent_id in
+        <foreach item="id" collection="ids" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
 </mapper>

+ 83 - 0
fs-service/src/main/resources/mapper/course/FsCourseFinishTempParentMapper.xml

@@ -0,0 +1,83 @@
+<?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.FsCourseFinishTempParentMapper">
+    
+    <resultMap type="FsCourseFinishTempParent" id="FsCourseFinishTempParentResult">
+        <result property="id"    column="id"    />
+        <result property="name"    column="name"    />
+        <result property="courseId"    column="course_id"    />
+        <result property="companyId"    column="company_id"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="updateBy"    column="update_by"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remark"    column="remark"    />
+    </resultMap>
+
+    <sql id="selectFsCourseFinishTempParentVo">
+        select * from fs_course_finish_temp_parent
+    </sql>
+
+    <select id="selectFsCourseFinishTempParentList" parameterType="FsCourseFinishTempParent" resultMap="FsCourseFinishTempParentResult">
+        <include refid="selectFsCourseFinishTempParentVo"/>
+        <where>  
+            <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
+            <if test="courseId != null "> and course_id = #{courseId}</if>
+            <if test="companyId != null "> and company_id = #{companyId}</if>
+        </where>
+    </select>
+    
+    <select id="selectFsCourseFinishTempParentById" parameterType="Long" resultMap="FsCourseFinishTempParentResult">
+        <include refid="selectFsCourseFinishTempParentVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertFsCourseFinishTempParent" parameterType="FsCourseFinishTempParent" useGeneratedKeys="true" keyProperty="id">
+        insert into fs_course_finish_temp_parent
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="name != null">name,</if>
+            <if test="courseId != null">course_id,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="name != null">#{name},</if>
+            <if test="courseId != null">#{courseId},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <update id="updateFsCourseFinishTempParent" parameterType="FsCourseFinishTempParent">
+        update fs_course_finish_temp_parent
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="name != null">name = #{name},</if>
+            <if test="courseId != null">course_id = #{courseId},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="createBy != null">create_by = #{createBy},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteFsCourseFinishTempParentById" parameterType="Long">
+        delete from fs_course_finish_temp_parent where id = #{id}
+    </delete>
+
+    <delete id="deleteFsCourseFinishTempParentByIds" parameterType="String">
+        delete from fs_course_finish_temp_parent where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>