yys 6 napja
szülő
commit
d4896230a6
21 módosított fájl, 476 hozzáadás és 29 törlés
  1. 7 1
      fs-service/src/main/java/com/fs/course/domain/FsUserCourseVideo.java
  2. 8 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  3. 6 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  4. 148 3
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  5. 2 2
      fs-service/src/main/java/com/fs/gtPush/service/impl/uniPush2ServiceImpl.java
  6. 1 1
      fs-service/src/main/java/com/fs/gtPush/service/uniPush2Service.java
  7. 3 0
      fs-service/src/main/java/com/fs/his/vo/OptionsVO.java
  8. 13 0
      fs-service/src/main/java/com/fs/im/param/FsCourseSendParam.java
  9. 2 2
      fs-service/src/main/java/com/fs/im/service/OpenIMService.java
  10. 16 10
      fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java
  11. 105 0
      fs-service/src/main/java/com/fs/qw/dto/QwUserCompanyDTO.java
  12. 3 0
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java
  13. 3 0
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  14. 3 0
      fs-service/src/main/java/com/fs/qw/service/IQwUserService.java
  15. 2 0
      fs-service/src/main/java/com/fs/qw/service/impl/AsyncSopTestService.java
  16. 6 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java
  17. 1 1
      fs-service/src/main/resources/mapper/his/FsPackageCateMapper.xml
  18. 3 1
      fs-service/src/main/resources/mapper/qw/QwUserMapper.xml
  19. 12 4
      fs-user-app/src/main/java/com/fs/app/controller/AppBaseController.java
  20. 125 1
      fs-user-app/src/main/java/com/fs/app/controller/CourseController.java
  21. 7 3
      fs-user-app/src/main/java/com/fs/app/controller/PackageController.java

+ 7 - 1
fs-service/src/main/java/com/fs/course/domain/FsUserCourseVideo.java

@@ -80,7 +80,7 @@ public class FsUserCourseVideo extends BaseEntity
     private Integer uploadType;
 
     private BigDecimal redPacketMoney;
-
+    private Integer isPause;
     /**
      * 随机红包配置
      */
@@ -133,4 +133,10 @@ public class FsUserCourseVideo extends BaseEntity
      * 0横屏 1竖屏(默认0)
      */
     private Integer screenType;
+
+
+    /**
+     * 是否公开课
+     */
+    private Integer openClass;
 }

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

@@ -151,6 +151,14 @@ public interface FsUserCourseVideoMapper extends BaseMapper<FsUserCourseVideo> {
     @Select("select video_id dict_value, title dict_label  from fs_user_course_video where course_id=#{id} and is_del = 0 order by course_sort")
     List<OptionsVO> selectFsUserCourseVodeAllList(Long id);
 
+    @Select("<script>" +
+            "select video_id dict_value, title dict_label ,is_Pause,open_class from fs_user_course_video " +
+            "where course_id=#{id} and is_del = 0 " +
+            "<if test='title != null'> and title like concat('%', #{title}, '%') </if>"+
+            " order by course_sort  "+
+            "</script>")
+    List<OptionsVO> selectFsUserCourseVodeAllList(@Param("id")Long id, @Param("title")String title);
+
     @Select({"<script> " +
             "select v.*,p.red_packet_money company_red_packet_money from fs_user_course_video v " +
             "LEFT JOIN fs_user_course_video_red_package p on p.video_id= v.video_id and p.company_id =#{maps.companyId} and p.data_type = 1 " +

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

@@ -18,8 +18,10 @@ import com.fs.course.vo.newfs.FsUserVideoListVO;
 import com.fs.his.domain.FsUser;
 import com.fs.his.vo.OptionsVO;
 import com.fs.qw.param.FsUserCourseRedPageParam;
+import com.fs.sop.dto.QwCreateLinkByAppDTO;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -267,4 +269,8 @@ public interface IFsUserCourseVideoService extends IService<FsUserCourseVideo> {
     Map<String, Object> claimSignReward(Long userId);
 
     R withdrawal(FsCourseSendRewardUParam param);
+
+    QwCreateLinkByAppDTO createLinkByApp(String corpId, Date sendTime, Integer courseId, Integer videoId, String qwUserId, String companyUserId, String companyId, Long externalId, String qwUserName, Long fsUserId, String courseName, String videoTitle, String thumbnail);
+    Long addWatchLogIfNeeded(Integer videoId, Integer courseId, Long fsUserId, String qwUserId, String companyUserId, String companyId, Long externalId,  Date createTime);
+
 }

+ 148 - 3
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -95,6 +95,7 @@ import com.fs.qwApi.service.QwApiService;
 import com.fs.reward.domain.FsRewardGoods;
 import com.fs.reward.mapper.FsRewardGoodsMapper;
 import com.fs.sop.domain.SopUserLogsInfo;
+import com.fs.sop.dto.QwCreateLinkByAppDTO;
 import com.fs.sop.mapper.SopUserLogsInfoMapper;
 import com.fs.sop.service.ISopUserLogsInfoService;
 import com.fs.system.mapper.SysDictDataMapper;
@@ -149,7 +150,10 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
     private String signProjectName;
     @Value("${isNewWxMerchant}")
     private Boolean isNewWxMerchant;
-
+    private static final String appRealLink = "/pages/courseAnswer/index?link=";
+    private static final String appLink = "https://userapp.cqtyt.com/jumpapp/pages/index/index?link=";
+    @Autowired
+    private FsCourseWatchLogMapper fsCourseWatchLogMapper;
     @Autowired
     private OpenIMService openIMService;
     @Autowired
@@ -157,9 +161,11 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
     @Autowired
     private FsCourseRewardMapper courseRewardMapper;
     @Autowired
+    private FsCourseSopAppLinkMapper fsCourseSopAppLinkMapper;
+    @Autowired
     private FsRewardGoodsMapper rewardGoodsMapper;
     private static final Logger logger = LoggerFactory.getLogger(FsUserCourseVideoServiceImpl.class);
-
+    private static final String APP_LINK_PREFIX = "/appcourse/pages/course/learning?course=";
     private static final String miniappRealLink = "/pages_course/video.html?course=";
     private static final String REAL_LINK_PREFIX = "/courseH5/pages/course/learning?course=";
     private static final String SHORT_LINK_PREFIX = "/courseH5/pages/course/learning?s=";
@@ -4187,7 +4193,7 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
                                 insetCompanyFsUser.setBindType(1); //看课绑定的
                                 try {
                                     companyCompanyFsuserMapper.insertCompanyCompanyUser(insetCompanyFsUser);
-                                    openIMService.checkAndImportFriendByDianBo(insetCompanyFsUser.getCompanyUserId(), insetCompanyFsUser.getUserId().toString(), StringUtils.isNotEmpty(param.getCorpId()) ? param.getCorpId() : "", true);
+                                    openIMService.checkAndImportFriendByDianBo(insetCompanyFsUser.getCompanyUserId(), insetCompanyFsUser.getUserId().toString(), StringUtils.isNotEmpty(param.getCorpId()) ? param.getCorpId() : "");
                                 } catch (Exception e) {
                                     logger.info("新增客服绑定报错:{}", e.getMessage());
                                 }
@@ -5716,5 +5722,144 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         return draw(param, user, watchLog, 5);
     }
 
+    @Override
+    public Long addWatchLogIfNeeded(Integer videoId, Integer courseId,
+                                    Long fsUserId, String qwUserId, String companyUserId,
+                                    String companyId, Long externalId,  Date createTime) {
+
+        try {
+            FsCourseWatchLog watchLog = new FsCourseWatchLog();
+            watchLog.setVideoId(videoId != null ? videoId.longValue() : null);
+            watchLog.setQwExternalContactId(externalId);
+            watchLog.setSendType(2);
+            watchLog.setQwUserId(Long.valueOf(qwUserId));
+            //watchLog.setSopId(sopId);
+            watchLog.setDuration(0L);
+            watchLog.setCourseId(courseId != null ? courseId.longValue() : null);
+            watchLog.setCompanyUserId(companyUserId != null ? Long.valueOf(companyUserId) : null);
+            watchLog.setCompanyId(companyId != null ? Long.valueOf(companyId) : null);
+            watchLog.setCreateTime(createTime);
+            watchLog.setUpdateTime(createTime);
+            watchLog.setLogType(3);
+            watchLog.setUserId(fsUserId);
+//            watchLog.setWatchType(watchType);
+            //watchLog.setCampPeriodTime(convertStringToDate(startTime, "yyyy-MM-dd"));
+            //watchLog.setSopPeriodId(sopPeriodId);
+
+            int i = fsCourseWatchLogMapper.insertOrUpdateFsCourseWatchLog(watchLog);
+            return watchLog.getLogId();
+        } catch (Exception e) {
+            log.error("一键群发失败-插入观看记录失败:" + e.getMessage());
+            return null;
+        }
+    }
+
+    @Override
+    public QwCreateLinkByAppDTO createLinkByApp(String corpId,
+                                                Date sendTime, Integer courseId, Integer videoId, String qwUserId,
+                                                String companyUserId, String companyId, Long externalId,
+                                                String qwUserName, Long fsUserId, String courseName, String videoTitle, String thumbnail) {
+
+        FsCourseLink link = createFsCourseLink(corpId, sendTime, courseId, videoId, qwUserId,
+                companyUserId, companyId, externalId, 4, null);
+
+        FsCourseRealLink courseMap = new FsCourseRealLink();
+        BeanUtils.copyProperties(link, courseMap);
+
+        String courseJson = JSON.toJSONString(courseMap);
+        String realLinkFull = APP_LINK_PREFIX + courseJson;
+        link.setRealLink(realLinkFull);
+
+        Date updateTime = createUpdateTime(sendTime);
+
+        link.setUpdateTime(updateTime);
+
+        String sortLink = appLink + link.getLink() + "&videoId=" + videoId;
+
+        String appMsgLink = appRealLink + link.getLink();
+
+        QwCreateLinkByAppDTO byAppDTO = new QwCreateLinkByAppDTO();
+        byAppDTO.setSortLink(sortLink);
+        byAppDTO.setAppMsgLink(appMsgLink);
+
+        //异步生成app链接记录
+        createFsCourseSopAppLink(link.getLink(), sendTime, updateTime, companyId, companyUserId, qwUserId,
+                qwUserName, corpId, courseId, courseName, thumbnail, videoId,
+                videoTitle, appMsgLink, externalId);
+
+        //异步给app用户发送消息
+        //asyncSopTestService.asyncSendMsgBySopAppLink(externalId, setting.getLinkTitle(), setting.getLinkDescribe(), appMsgLink);
+
+//        asyncSopTestService.asyncSendMsgBySopAppLinkNormalIMSingle(setting, externalId,Long.parseLong(companyUserId),fsUserId);
+        //存短链-
+        fsCourseLinkMapper.insertFsCourseLink(link);
+
+        return byAppDTO;
+    }
+    public FsCourseLink createFsCourseLink(String corpId, Date sendTime, Integer courseId, Integer videoId, String qwUserId,
+                                           String companyUserId, String companyId, Long externalId, Integer type, String chatId) {
+        // 手动创建 FsCourseLink 对象,避免使用 BeanUtils.copyProperties
+        FsCourseLink link = new FsCourseLink();
+        link.setCompanyId(Long.parseLong(companyId));
+        link.setQwUserId(Long.valueOf(qwUserId));
+        link.setCompanyUserId(Long.parseLong(companyUserId));
+        link.setVideoId(videoId.longValue());
+        link.setCorpId(corpId);
+        link.setCourseId(courseId.longValue());
+        link.setChatId(chatId);
+        link.setQwExternalId(externalId);
+        link.setLinkType(type); //小程序
+        link.setUNo(UUID.randomUUID().toString());
+        String randomString = generateRandomStringWithLock();
+        if (StringUtil.strIsNullOrEmpty(randomString)) {
+            link.setLink(UUID.randomUUID().toString().replace("-", ""));
+        } else {
+            link.setLink(randomString);
+        }
+
+        link.setCreateTime(sendTime);
+
+        return link;
+    }
+
+    public void createFsCourseSopAppLink(String link, Date sendTime, Date updateTime, String companyId,
+                                         String companyUserId,String qwUserId,String qwUserName,String corpId,
+                                         Integer courseId,String linkTile,String linkImageUrl,Integer videoId,
+                                         String linkDescribe,String appMsgLink,Long externalId){
+
+        FsCourseSopAppLink sopAppLink=new FsCourseSopAppLink();
+        sopAppLink.setLink(link);
+        sopAppLink.setCreateTime(sendTime);
+        sopAppLink.setUpdateTime(updateTime);
+        sopAppLink.setCompanyId(Long.parseLong(companyId));
+        sopAppLink.setCompanyUserId(Long.parseLong(companyUserId));
+        sopAppLink.setQwUserId(Long.parseLong(qwUserId));
+        sopAppLink.setQwUserName(qwUserName);
+        sopAppLink.setCorpId(corpId);
+        sopAppLink.setCourseId(Long.valueOf(courseId));
+        sopAppLink.setCourseTitle(linkTile);
+        sopAppLink.setCourseUrl(linkImageUrl);
+        sopAppLink.setVideoId(Long.valueOf(videoId));
+        sopAppLink.setVideoTitle(linkDescribe);
+        sopAppLink.setAppRealLink(appMsgLink);
+        sopAppLink.setQwExternalId(externalId);
+
+        fsCourseSopAppLinkMapper.insertFsCourseSopAppLink(sopAppLink);
+
+    }
+
+    private Date createUpdateTime(Date sendTime) {
+        LocalDateTime sendDateTime = sendTime.toInstant()
+                .atZone(ZoneId.systemDefault())
+                .toLocalDateTime();
+
+        LocalDateTime expireDateTime = sendDateTime
+                .toLocalDate()
+                .atTime(23, 59, 59);
+
+        return Date.from(expireDateTime
+                .atZone(ZoneId.systemDefault())
+                .toInstant());
+    }
 }
 

+ 2 - 2
fs-service/src/main/java/com/fs/gtPush/service/impl/uniPush2ServiceImpl.java

@@ -82,7 +82,7 @@ public class uniPush2ServiceImpl implements uniPush2Service {
         return JSONUtil.toBean(result, PushResult.class);
     }
     @Override
-    public OpenImResponseDTO pushSopAppLinkMsgByExternalIM(String cropId, String linkTile, String linkDescribe, String linkImageUrl, String link, Long companyUserId, Long fsUserId) throws JsonProcessingException {
+    public OpenImResponseDTO pushSopAppLinkMsgByExternalIM(String cropId, String linkTile, String linkDescribe, String linkImageUrl, String link, Long companyUserId, Long fsUserId,String linkType) throws JsonProcessingException {
 
         if (companyUserId == null || fsUserId == null || fsUserId == 0) {
             OpenImResponseDTO errorResponse = new OpenImResponseDTO();
@@ -109,7 +109,7 @@ public class uniPush2ServiceImpl implements uniPush2Service {
 //            return errorResponse;
 //        }
 
-        OpenImResponseDTO openImResponseDTO = openIMService.sendCourse(fsUserId, companyUserId, link, linkDescribe, linkImageUrl, cropId);
+        OpenImResponseDTO openImResponseDTO = openIMService.sendCourse(fsUserId, companyUserId, link, linkDescribe, linkImageUrl, cropId,linkType);
         return openImResponseDTO;
 
     }

+ 1 - 1
fs-service/src/main/java/com/fs/gtPush/service/uniPush2Service.java

@@ -13,7 +13,7 @@ public interface uniPush2Service {
 
     PushReqBean getParam(Long userId,String purl,String title,String content,Float type,Integer desType,String imJsonString);
 //    void pushSopAppLinkMsgByExternalIM(String cropId,String linkTile,String linkDescribe,String linkImageUrl,String link,Long companyUserId,Long fsUserId) throws JsonProcessingException;
-    OpenImResponseDTO pushSopAppLinkMsgByExternalIM(String cropId, String linkTile, String linkDescribe, String linkImageUrl, String link, Long companyUserId, Long fsUserId) throws JsonProcessingException;
+    OpenImResponseDTO pushSopAppLinkMsgByExternalIM(String cropId, String linkTile, String linkDescribe, String linkImageUrl, String link, Long companyUserId, Long fsUserId,String linkType) throws JsonProcessingException;
     OpenImResponseDTO pushSopAppLiveCardMsgByExternalIM(String cropId, String title, String appRealLink, Long liveId, Long companyUserId, Long fsUserId, Long companyId, Long externalId, Long qwUserKey) throws JsonProcessingException;
     void pushIm(Long userId, Long businessId, String purl, String title, String content, Float type, Integer desType,String imJsonString);
 }

+ 3 - 0
fs-service/src/main/java/com/fs/his/vo/OptionsVO.java

@@ -8,4 +8,7 @@ public class OptionsVO implements Serializable {
     Long dictValue;
     String dictLabel;
     String dictImgUrl;
+    Integer isPause;
+    String remark;
+    Integer openClass;
 }

+ 13 - 0
fs-service/src/main/java/com/fs/im/param/FsCourseSendParam.java

@@ -0,0 +1,13 @@
+package com.fs.im.param;
+
+import lombok.Data;
+
+@Data
+public class FsCourseSendParam {
+    private Long userId;
+    private Integer courseId;
+    private Integer videoId;
+    private Long companyUserId;
+    private Long qwUserId;
+    private String corpId;
+}

+ 2 - 2
fs-service/src/main/java/com/fs/im/service/OpenIMService.java

@@ -33,9 +33,9 @@ public interface OpenIMService {
     OpenImResponseDTO isFriend(String userID1, String userID2);
     R accountCheck(String userId, String type);
     void checkAndImportFriend(Long companyUserId,String fsUserId);
-    OpenImResponseDTO sendCourse(Long userId,Long companyUserId,String url,String title,String linkImageUrl,String cropId) throws JsonProcessingException;
+    OpenImResponseDTO sendCourse(Long userId,Long companyUserId,String url,String title,String linkImageUrl,String cropId,String linkType) throws JsonProcessingException;
     OpenImResponseDTO sendLive(Long userId, Long companyUserId, String appRealLink, String title, Long liveId, String cropId, Long companyId) throws JsonProcessingException;
-    void checkAndImportFriendByDianBo(Long companyUserId,String fsUserId,String cropId, boolean isUpdate);
+    void checkAndImportFriendByDianBo(Long companyUserId,String fsUserId,String cropId);
 
     OpenImResponseDTO updateUserInfo(CompanyUser companyUser);
 

+ 16 - 10
fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java

@@ -520,17 +520,21 @@ public class OpenIMServiceImpl implements OpenIMService {
         log.info("发送消息返回内容:\n{}", result);
         return responseDTO;
     }
+
+
+
     @Override
-    public OpenImResponseDTO sendCourse(Long userId,Long companyUserId,String url,String title,String linkImageUrl,String cropId) throws JsonProcessingException {
+    public OpenImResponseDTO sendCourse(Long userId,Long companyUserId,String url,String title,String linkImageUrl,String cropId,String linkType) throws JsonProcessingException {
         ObjectMapper objectMapper = new ObjectMapper();
         //userId = 61l;
         objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略null字段
-        checkAndImportFriendByDianBo(companyUserId,userId.toString(),cropId,true);
+        checkAndImportFriendByDianBo(companyUserId,userId.toString(),cropId);
         OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
         OpenImMsgDTO.ImData imData = new OpenImMsgDTO.ImData();
+
         PayloadDTO payload = new PayloadDTO();
         PayloadDTO.Extension extension = new PayloadDTO.Extension();
-        payload.setData("course");
+        payload.setData(linkType);
         extension.setTitle(title);
         extension.setAppRealLink(url);
         extension.setSendTime(new Date());
@@ -551,12 +555,15 @@ public class OpenIMServiceImpl implements OpenIMService {
         openImMsgDTO.setOfflinePushInfo(offlinePushInfo);
         openImMsgDTO.setContent(content);
 
+
+
         openImMsgDTO.setSendID("C"+companyUserId);
         openImMsgDTO.setRecvID("U"+userId);
+        openImMsgDTO.setSenderNickname(StringUtils.isNotEmpty(companyUser.getImNickName())?companyUser.getImNickName():companyUser.getNickName());
         openImMsgDTO.setContentType(110);
         openImMsgDTO.setSessionType(1);
         // 输出格式化JSON日志
-        log.info("课程消息: {}", JSON.toJSONString(openImMsgDTO));
+        log.info("课程消息:\n{}", objectMapper.writeValueAsString(openImMsgDTO));
         OpenImResponseDTO openImResponseDTO = openIMSendMsg(openImMsgDTO);
         openImMsgDTO = null;
         content = null;
@@ -569,7 +576,7 @@ public class OpenIMServiceImpl implements OpenIMService {
         CompanyUser companyUser = companyUserMapper.selectCompanyUserById(companyUserId);
         ObjectMapper objectMapper = new ObjectMapper();
         objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
-        checkAndImportFriendByDianBo(companyUserId, userId.toString(), cropId, true);
+        checkAndImportFriendByDianBo(companyUserId, userId.toString(), cropId);
         OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
         OpenImMsgDTO.ImData imData = new OpenImMsgDTO.ImData();
         PayloadDTO payload = new PayloadDTO();
@@ -1109,7 +1116,7 @@ public class OpenIMServiceImpl implements OpenIMService {
 
     @Async
     @Override
-    public void checkAndImportFriendByDianBo(Long companyUserId,String fsUserId,String cropId, boolean isUpdate) {
+    public void checkAndImportFriendByDianBo(Long companyUserId,String fsUserId,String cropId) {
         try {
             // 注册账号
             accountCheck("C" + companyUserId, "2");
@@ -1119,15 +1126,14 @@ public class OpenIMServiceImpl implements OpenIMService {
             ArrayList<String> userIds = new ArrayList<>();
             userIds.add("U" + fsUserId);
             importFriend("C" + companyUserId, userIds);
-            if(isUpdate){
-                updateFriendByDianBo("C" + companyUserId, userIds,cropId);
-            }
+            updateFriendByDianBo("C" + companyUserId, userIds,cropId);
         } catch (Exception e) {
             log.error("异步执行IM注册/添加好友失败:", e);
         }
     }
 
 
+
     @Override
     @Transactional
     public OpenImResponseDTO openIMBatchSendMsg(OpenImBatchMsgDTO openImBatchMsgDTO) {
@@ -1162,7 +1168,7 @@ public class OpenIMServiceImpl implements OpenIMService {
         //注册和添加好友
         for (String userId : userIds) {
             String uId = userId.substring(1);
-            checkAndImportFriendByDianBo(batchSendCourseDTO.getCompanyUserId(), uId,null,false);
+            checkAndImportFriendByDianBo(batchSendCourseDTO.getCompanyUserId(), uId,null);
         }
 
         //组装发课消息数据

+ 105 - 0
fs-service/src/main/java/com/fs/qw/dto/QwUserCompanyDTO.java

@@ -0,0 +1,105 @@
+package com.fs.qw.dto;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+@Data
+public class QwUserCompanyDTO extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 企微用户id */
+    @Excel(name = "企微用户id")
+    private String qwUserId;
+
+    /** 企微用户名 */
+    @Excel(name = "企微用户名")
+    private String qwUserName;
+
+    /** 所属部门id */
+    @Excel(name = "所属部门id")
+    private String department;
+
+    /** openid */
+    @Excel(name = "openid")
+    private String openid;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 公司员工id */
+    @Excel(name = "公司员工id")
+    private Long companyUserId;
+
+    /** 企微id */
+    @Excel(name = "企微id")
+    private String corpId;
+
+    /** 0 未绑定 1 已绑定 */
+    @Excel(name = "0 未绑定 1 已绑定")
+    private Integer status;
+
+    /** 是否删除 */
+    @Excel(name = "是否删除")
+    private Integer isDel;
+
+    @Excel(name = "	SOP消息文本-员工昵称")
+    private String welcomeText;
+
+    /** 欢迎语图片 */
+    @Excel(name = "欢迎语图片")
+    private String welcomeImage;
+
+    /** 用来设置完课备注咯 */
+    private Integer isSendMsg;
+
+    private  String appKey;
+    private String contactWay; //添加好友渠道活码
+
+
+    private String configId; //渠道活码配置id,删除时需用到
+
+    private  String qwHookId;//企业微信HOOK ID
+
+    /**
+     * 绑定的AI客服角色
+     *
+     */
+    private  Long fastGptRoleId;
+    /**
+     * 登录状态
+     */
+    private  Long loginStatus;
+    /**
+     * 工具状态
+     */
+    private  Long toolStatus;
+    /**
+     * 二维码
+     */
+    private  String loginCodeUrl;
+
+    private  String version;
+    private  String unionid;
+
+    private String vid;
+    private String uid;
+
+    private Integer ipadStatus;
+
+    private Long serverId;
+    private Integer serverStatus;
+    /** 发送消息类型0侧边栏1pad,2掉线通知 */
+    private Integer sendMsgType;
+    /** 是否获取视频号消息(0否1是) */
+    private Integer videoGetStatus;
+
+    /** 头像 **/
+    private String avatar;
+
+    private String companyName;
+}

+ 3 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java

@@ -679,4 +679,7 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
             "</foreach>" +
             "</script>")
     public int batchUpdateQwExternalContactMandatoryRegistration(@Param("map") List<QwMandatoryRegistrParam> batchList);
+
+    @Select("SELECT * FROM qw_external_contact WHERE company_user_id = #{companyUserId} AND qw_user_id = #{qwUserId} AND fs_user_id = #{userId} and status = 0 limit 1")
+    QwExternalContact selectQwExternalContactByCompanyUserIdQwUserIdUserId(@Param("companyUserId") String companyUserId, @Param("qwUserId") String qwUserId, @Param("userId") String userId);
 }

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

@@ -7,6 +7,7 @@ import com.fs.qw.domain.QwUser;
 import com.fs.qw.domain.QwUserGroup;
 import com.fs.qw.domain.QwWorkTask;
 import com.fs.qw.dto.QwUserByToolDTO;
+import com.fs.qw.dto.QwUserCompanyDTO;
 import com.fs.qw.dto.QwUserDTO;
 import com.fs.qw.dto.QwUserKeyDTO;
 import com.fs.qw.param.*;
@@ -535,4 +536,6 @@ public interface QwUserMapper extends BaseMapper<QwUser>
     QwUserVO getQwUserCompanyInfo(@Param("qwUserId") Long qwUserId);
 
     List<Long> selectIdByCompanyUserId(@Param("companyUserId")Long companyUserId);
+
+    List<QwUserCompanyDTO> selectQwUserCompanyDTOByCompanyUserId(Long companyUserId);
 }

+ 3 - 0
fs-service/src/main/java/com/fs/qw/service/IQwUserService.java

@@ -4,6 +4,7 @@ import com.fs.common.core.domain.R;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.domain.QwUserGroup;
 import com.fs.qw.domain.QwWorkTask;
+import com.fs.qw.dto.QwUserCompanyDTO;
 import com.fs.qw.dto.QwUserKeyDTO;
 import com.fs.qw.param.*;
 import com.fs.qw.vo.*;
@@ -228,4 +229,6 @@ public interface IQwUserService
     R getQwUser(String qwUserKey);
 
     QwUserVO getQwUserCompanyInfo(Long qwUserId);
+
+    List<QwUserCompanyDTO> selectQwUserCompanyDTOByCompanyUserId(Long companyUserId);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/qw/service/impl/AsyncSopTestService.java

@@ -528,6 +528,7 @@ public class AsyncSopTestService {
             item.setSendRemarks("APP发送失败");
 
             try {
+                String linkType="course";
                 OpenImResponseDTO resp =
                         push2Service.pushSopAppLinkMsgByExternalIM(
                                 cropId,
@@ -537,6 +538,7 @@ public class AsyncSopTestService {
                                 item.getAppLinkUrl(),
                                 companyUserId,
                                 fsUserId
+                                ,linkType
                         );
                 if (resp != null && resp.getErrCode() != null && resp.getErrCode() == 0) {
                     item.setSendStatus(1);

+ 6 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java

@@ -33,6 +33,7 @@ import com.fs.ipad.vo.WxGetSessionRoomListVo;
 import com.fs.ipad.vo.WxRoomUserListVo;
 import com.fs.qw.domain.*;
 import com.fs.qw.dto.QwUserByToolDTO;
+import com.fs.qw.dto.QwUserCompanyDTO;
 import com.fs.qw.dto.QwUserKeyDTO;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.mapper.QwWorkTaskMapper;
@@ -337,6 +338,11 @@ public class QwUserServiceImpl implements IQwUserService
         }
     }
 
+    @Override
+    public List<QwUserCompanyDTO> selectQwUserCompanyDTOByCompanyUserId(Long companyUserId){
+        return qwUserMapper.selectQwUserCompanyDTOByCompanyUserId(companyUserId);
+    }
+
 
     /**
      * 登录企业微信(获取登录二维码-发起登录)

+ 1 - 1
fs-service/src/main/resources/mapper/his/FsPackageCateMapper.xml

@@ -24,7 +24,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="cateCode != null "> and cate_code = #{cateCode}</if>
             <if test="type != null "> and type = #{type}</if>
             <if test="cateName != null  and cateName != ''"> and cate_name like concat('%', #{cateName}, '%')</if>
-            <if test="companyPackageCates != null  and companyPackageCates != ''">
+            <if test="companyPackageCates != null and companyPackageCates.size() > 0">
                 AND cate_code IN
                 <foreach collection="companyPackageCates" item="item" open="(" separator="," close=")">
                     #{item}

+ 3 - 1
fs-service/src/main/resources/mapper/qw/QwUserMapper.xml

@@ -381,6 +381,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectIdByCompanyUserId" resultType="java.lang.Long">
         select id from qw_user where company_user_id = #{companyUserId}
     </select>
-
+    <select id="selectQwUserCompanyDTOByCompanyUserId" resultType="com.fs.qw.dto.QwUserCompanyDTO">
+        select * from qw_user where company_user_id = #{companyUserId}
+    </select>
 
 </mapper>

+ 12 - 4
fs-user-app/src/main/java/com/fs/app/controller/AppBaseController.java

@@ -45,11 +45,19 @@ public class AppBaseController {
 	}
 	public Long getCompanyUserId( )
 	{
-		Long companyUesrId=redisCache.getCacheObject("company-user-token:"+ ServletUtils.getRequest().getHeader("companyUserToken"));
-		if(companyUesrId== null){
-			throw  new CustomException("未登录",403);
+		String token = ServletUtils.getRequest().getHeader("companyUserToken");
+		if (StringUtils.isEmpty(token)) {
+			throw new CustomException("未登录", 403);
 		}
-		return companyUesrId;
+		Long companyUserId = redisCache.getCacheObject("company-user-token:" + token);
+		if (companyUserId != null) {
+			return companyUserId;
+		}
+		Claims claims = jwtUtils.getClaimByToken(token);
+		if (claims != null && !jwtUtils.isTokenExpired(claims.getExpiration())) {
+			return Long.parseLong(claims.getSubject());
+		}
+		throw new CustomException("未登录", 403);
 	}
 
 	/**

+ 125 - 1
fs-user-app/src/main/java/com/fs/app/controller/CourseController.java

@@ -1,18 +1,34 @@
 package com.fs.app.controller;
 
 
+import cn.hutool.core.util.ObjectUtil;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.app.annotation.Login;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyUserService;
 import com.fs.course.domain.*;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
+import com.fs.course.mapper.FsUserCourseMapper;
+import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.param.*;
 import com.fs.course.service.*;
 import com.fs.course.vo.*;
 import com.fs.his.vo.OptionsVO;
+import com.fs.im.param.FsCourseSendParam;
+import com.fs.im.service.OpenIMService;
+import com.fs.qw.domain.QwCompany;
+import com.fs.qw.domain.QwExternalContact;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.dto.QwUserCompanyDTO;
+import com.fs.qw.mapper.QwExternalContactMapper;
+import com.fs.qw.service.IQwCompanyService;
+import com.fs.qw.service.IQwUserService;
+import com.fs.sop.dto.QwCreateLinkByAppDTO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.jsonwebtoken.Claims;
@@ -20,6 +36,7 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.Synchronized;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.transaction.annotation.Transactional;
@@ -60,7 +77,15 @@ public class CourseController extends  AppBaseController{
     @Autowired
     private FsCourseWatchLogMapper fsCourseWatchLogMapper;
 
-//    @Cacheable(value="getCourseCate" )
+    @Autowired
+    private IQwUserService qwUserService;
+    @Autowired
+    private QwExternalContactMapper qwExternalContactMapper;
+    @Autowired
+    private IQwCompanyService qwCompanyService;
+    @Autowired
+    private FsUserCourseVideoMapper fsUserCourseVideoMapper;
+    //    @Cacheable(value="getCourseCate" )
     @ApiOperation("获取分类")
     @GetMapping("/getCourseCate")
     public R getCourseCate(@RequestParam(value = "isShow",required = false) Integer isShow){
@@ -453,4 +478,103 @@ public class CourseController extends  AppBaseController{
         return courseWatchLogService.decryptLinkV2(param.getUrl());
     }
 
+    @Autowired
+    private ICompanyUserService companyUserService;
+    @Autowired
+    private FsUserCourseMapper fsUserCourseMapper;
+
+    @GetMapping("/getCourseListByCompany")
+    public R getCourseListByCompany() {
+        Long userId=getCompanyUserId();
+        if(userId==null){
+            return R.error(403,"用户失效");
+        }
+        CompanyUser companyUser = companyUserService.selectCompanyUserById(userId);
+        List<OptionsVO> optionsVOS = fsUserCourseMapper.selectFsUserCourseByCompany(companyUser.getCompanyId());
+        if (!CollectionUtils.isEmpty(optionsVOS)) {
+            optionsVOS.forEach(item -> {
+                if (StringUtils.isNotEmpty(item.getRemark())) {
+                    item.setDictLabel(item.getRemark());
+                }
+            });
+        }
+        return R.ok().put("list", optionsVOS);
+    }
+
+
+    //app手动发课前根据销售id查询绑定的qw_user列表
+    @GetMapping("/getQwUserListByCompanyUserId")
+    public R getQwUserListByCompanyUserId(Long userId) {
+
+        if (userId == null) {
+            return R.error("userId不能为空");
+        }
+
+        Long companyUserId = getCompanyUserId();
+        if (companyUserId == null) {
+            return R.error(403, "用户失效");
+        }
+
+        List<QwUserCompanyDTO> qwUsers = qwUserService.selectQwUserCompanyDTOByCompanyUserId(companyUserId);
+
+        Iterator<QwUserCompanyDTO> iterator = qwUsers.iterator();
+
+        while (iterator.hasNext()) {
+
+            QwUserCompanyDTO qwUser = iterator.next();
+
+            QwExternalContact contact = qwExternalContactMapper.selectQwExternalContactByCompanyUserIdQwUserIdUserId(companyUserId.toString(), qwUser.getId().toString(), userId.toString());
+
+            if (contact == null) {
+                iterator.remove();
+                continue;
+            }
+
+            QwCompany qwCompany = qwCompanyService.selectQwCompanyByCorpId(qwUser.getCorpId());
+            if (qwCompany != null) {
+                qwUser.setCompanyName(qwCompany.getCorpName());
+            }
+        }
+
+        return R.ok().put("data", qwUsers);
+    }
+
+    @GetMapping(value = "/getVideoListByCourse/{id}")
+    public R videoList(@PathVariable("id") Long id,String title)
+    { Long userId=getCompanyUserId();
+        if(userId==null){
+            return R.error(403,"用户失效");
+        }
+        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id,title);
+        return R.ok().put("list", optionsVOS);
+    }
+
+    @Autowired
+    private IFsUserCourseVideoService fsUserCourseVideoService;
+    @Autowired
+    private OpenIMService openIMService;
+    @PostMapping("/sendCourse")
+    public R sendCourse(@RequestBody FsCourseSendParam param) throws JsonProcessingException {
+        CompanyUser companyUser = companyUserService.selectCompanyUserById(param.getCompanyUserId());
+        Date dataTime = new Date();
+        QwExternalContact qwExternalContact = qwExternalContactMapper.selectQwExternalContactByCompanyUserIdQwUserIdUserId(param.getCompanyUserId().toString(), param.getQwUserId().toString(), param.getUserId().toString());
+        if (qwExternalContact==null){
+            return R.error("当前用户未和所选企微绑定");
+        }
+        QwUser qwUser = qwUserService.selectQwUserById(param.getQwUserId());
+        FsUserCourse fsUserCourse = courseService.selectFsUserCourseByCourseId(param.getCourseId().longValue());
+        FsUserCourseVideo fsUserCourseVideo = fsUserCourseVideoService.selectFsUserCourseVideoByVideoId(param.getVideoId().longValue());
+        if (ObjectUtil.isNotEmpty(fsUserCourseVideo)&&fsUserCourseVideo.getIsPause()!=0){
+            return R.error("课程已关闭,不可发送");
+        }
+        courseVideoService.addWatchLogIfNeeded(param.getVideoId(), param.getCourseId(), param.getUserId(), String.valueOf(param.getQwUserId()),
+                param.getCompanyUserId().toString(), companyUser.getCompanyId().toString(), qwExternalContact.getId(), dataTime);
+
+        QwCreateLinkByAppDTO linkByApp = courseVideoService.createLinkByApp(param.getCorpId(), dataTime, param.getCourseId(), param.getVideoId(),
+                String.valueOf(param.getQwUserId()), param.getCompanyUserId().toString(), companyUser.getCompanyId().toString(), qwExternalContact.getId(), qwUser.getQwUserName(), qwExternalContact.getFsUserId(),fsUserCourse.getCourseName(),fsUserCourseVideo.getTitle(),fsUserCourseVideo.getThumbnail());
+        String linkType="course";
+        openIMService.sendCourse(param.getUserId(),param.getCompanyUserId(),linkByApp.getAppMsgLink(),fsUserCourseVideo.getTitle(),fsUserCourseVideo.getThumbnail(),param.getCorpId(),linkType);
+        return R.ok();
+    }
+
 }

+ 7 - 3
fs-user-app/src/main/java/com/fs/app/controller/PackageController.java

@@ -45,6 +45,7 @@ import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.net.URL;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
@@ -93,10 +94,13 @@ public class PackageController extends AppBaseController {
             param.setCompanyUserId(companyUserId);
         } catch (Exception e) {
             log.info("获取套餐分类:销售未登录");
-        } finally {
-            List<FsPackageCate> cates = packageCateService.selectFsPackageCateList(param);
-            return R.ok().put("data", cates);
         }
+        if (Integer.valueOf(2).equals(param.getType())
+                && (param.getCompanyPackageCates() == null || param.getCompanyPackageCates().isEmpty())) {
+            return R.ok().put("data", Collections.emptyList());
+        }
+        List<FsPackageCate> cates = packageCateService.selectFsPackageCateList(param);
+        return R.ok().put("data", cates);
 
     }