Преглед изворни кода

feat:IM发课定时任务

caoliqin пре 3 недеља
родитељ
комит
35da75b56d

+ 41 - 0
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -12,6 +12,7 @@ import com.fs.company.domain.CompanyVoiceCaller;
 import com.fs.company.mapper.*;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.vo.RedPacketMoneyVO;
+import com.fs.course.dto.BatchSendCourseAllDTO;
 import com.fs.course.mapper.FsCourseRedPacketLogMapper;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.course.service.ITencentCloudCosService;
@@ -42,6 +43,7 @@ import com.fs.his.utils.ConfigUtil;
 import com.fs.his.vo.FsSubOrderResultVO;
 import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
 import com.fs.qw.domain.QwCompany;
 import com.fs.qw.service.*;
 import com.fs.qwApi.service.QwApiService;
@@ -52,12 +54,14 @@ import org.apache.commons.lang3.StringUtils;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @Component("task")
 public class Task {
@@ -152,6 +156,10 @@ public class Task {
     private IQwCompanyService qwCompanyService;
     @Autowired
     private IQwUserService qwUserService;
+    @Autowired
+    private OpenIMService openIMService;
+    @Autowired
+    public RedisTemplate redisTemplate;
 
     public void addQwUserName(){
         QwCompany qwCompany = new QwCompany();
@@ -1064,4 +1072,37 @@ public class Task {
         }
         return null;
     }
+
+
+    /**
+     * 定时任务-im会员定时发课,每一分钟执行一次
+     */
+    public void sendOpenImCourse(){
+        String redisKey = "openIm:batchSendMsg";
+        Map<String, BatchSendCourseAllDTO> cacheMap = redisCache.getCacheMap(redisKey);
+        if(cacheMap == null || cacheMap.isEmpty()){
+            logger.info("=====================会员IM定时发课,不存在对应的redisKey==================");
+            return;
+        }
+        List<Map.Entry<String, BatchSendCourseAllDTO>> toSendMap = cacheMap.entrySet().parallelStream().filter((v) -> {
+            String[] split = v.getKey().split(":");
+            long timestamp = Long.parseLong(split[3]);
+            return timestamp < System.currentTimeMillis();
+        }).collect(Collectors.toList());
+
+        if(toSendMap.isEmpty()){
+            logger.info("=====================会员IM定时发课,不存在可执行的发课任务==================");
+            return;
+        }
+        for (Map.Entry<String, BatchSendCourseAllDTO> entry : toSendMap) {
+            //执行发送消息任务
+            BatchSendCourseAllDTO batchSendCourseAllDTO = entry.getValue();
+            openIMService.batchSendMsgTask(batchSendCourseAllDTO.getBatchSendCourseDTO(), batchSendCourseAllDTO.getOpenImBatchMsgDTO(), batchSendCourseAllDTO.getProject(), 1);
+
+            // 执行结束,删除
+            this.redisTemplate.<String, BatchSendCourseAllDTO>opsForHash().delete(redisKey, entry.getKey());
+
+        }
+
+    }
 }

+ 46 - 4
fs-admin/src/main/java/com/fs/web/controller/common/CommonController.java

@@ -3,16 +3,15 @@ package com.fs.web.controller.common;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-
 import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.file.OssException;
-import com.fs.course.service.IHuaweiObsService;
-import com.fs.course.service.IHuaweiVodService;
+import com.fs.course.dto.BatchSendCourseAllDTO;;
 import com.fs.course.service.ITencentCloudCosService;
-import com.fs.course.service.impl.HuaweiObsServiceImpl;
 import com.fs.framework.config.ServerConfig;
 import com.fs.his.domain.FsExportTask;
 import com.fs.his.service.IFsExportTaskService;
+import com.fs.im.service.OpenIMService;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
 
@@ -22,6 +21,7 @@ import com.huaweicloud.sdk.vod.v1.model.BaseInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -36,6 +36,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 
 import static com.fs.course.service.impl.HuaweiObsServiceImpl.fileUrlMap;
 import static com.fs.course.service.impl.HuaweiObsServiceImpl.uploadProgress;
@@ -60,6 +61,17 @@ public class CommonController
     private ITencentCloudCosService tencentCloudCosService;
     @Autowired
     private IFsExportTaskService exportTaskService;
+
+    @Autowired
+    private OpenIMService openIMService;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    org.slf4j.Logger logger= LoggerFactory.getLogger(getClass());
     @GetMapping(value = "common/getTask/{taskId}")
     public R getTask(@PathVariable("taskId") Long taskId)
     {
@@ -227,7 +239,37 @@ public class CommonController
         return tencentCloudCosService.getKeyAndCredentials();
     }
 
+    /**
+     * 测试接口
+     */
+    @PostMapping("/common/im/testTask")
+    public void testIMTask(){
+        String redisKey = "openIm:batchSendMsg";
+        Map<String, BatchSendCourseAllDTO> cacheMap = redisCache.getCacheMap(redisKey);
+        if(cacheMap == null || cacheMap.isEmpty()){
+            logger.info("=====================会员IM定时发课,不存在对应的redisKey==================");
+            return;
+        }
+        List<Map.Entry<String, BatchSendCourseAllDTO>> toSendMap = cacheMap.entrySet().parallelStream().filter((v) -> {
+            String[] split = v.getKey().split(":");
+            long timestamp = Long.parseLong(split[3]);
+            return timestamp < System.currentTimeMillis();
+        }).collect(Collectors.toList());
+
+        if(toSendMap.isEmpty()){
+            logger.info("=====================会员IM定时发课,不存在可执行的发课任务==================");
+            return;
+        }
+        for (Map.Entry<String, BatchSendCourseAllDTO> entry : toSendMap) {
+            //执行发送消息任务
+            BatchSendCourseAllDTO batchSendCourseAllDTO = entry.getValue();
+            openIMService.batchSendMsgTask(batchSendCourseAllDTO.getBatchSendCourseDTO(), batchSendCourseAllDTO.getOpenImBatchMsgDTO(), batchSendCourseAllDTO.getProject(), 1);
+
+            // 执行结束,删除
+            this.redisTemplate.<String, BatchSendCourseAllDTO>opsForHash().delete(redisKey, entry.getKey());
 
+        }
 
+    }
 
 }

+ 28 - 0
fs-service/src/main/java/com/fs/course/dto/BatchSendCourseAllDTO.java

@@ -0,0 +1,28 @@
+package com.fs.course.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.im.dto.OpenImBatchMsgDTO;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 批量发课-定时任务入参(存入redis)
+ */
+@Data
+@Accessors(chain = true)
+public class BatchSendCourseAllDTO {
+
+    @ApiModelProperty(value = "前端点击发送时的入参")
+    private BatchSendCourseDTO batchSendCourseDTO;
+
+    @ApiModelProperty(value = "发IM消息时的参数")
+    private OpenImBatchMsgDTO openImBatchMsgDTO;
+
+    @ApiModelProperty(value = "课程所属项目")
+    private Long project;
+
+}

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

@@ -51,4 +51,14 @@ public interface OpenIMService {
      */
     OpenImResponseDTO batchSendCourse(BatchSendCourseDTO batchSendCourseDTO) throws JsonProcessingException;
 
+    /**
+     * 会有批量发课-任务
+     * @param batchSendCourseDTO
+     * @param openImBatchMsgDTO
+     * @param project
+     * @param sendType
+     * @return
+     */
+    OpenImResponseDTO batchSendMsgTask(BatchSendCourseDTO batchSendCourseDTO, OpenImBatchMsgDTO openImBatchMsgDTO, Long project, Integer sendType);
+
 }

+ 42 - 18
fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java

@@ -18,6 +18,7 @@ import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.domain.FsUserCompanyUser;
 import com.fs.course.domain.FsUserCourse;
+import com.fs.course.dto.BatchSendCourseAllDTO;
 import com.fs.course.dto.BatchSendCourseDTO;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
 import com.fs.course.mapper.FsUserCompanyUserMapper;
@@ -1089,6 +1090,7 @@ public class OpenIMServiceImpl implements OpenIMService {
         extension.setAppRealLink(batchSendCourseDTO.getUrl());
         extension.setSendTime(new Date());
         FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(batchSendCourseDTO.getCourseId());
+        Long project = fsUserCourse != null ? fsUserCourse.getProject() : null;
         extension.setCourseUrl(fsUserCourse != null ? fsUserCourse.getImgUrl() : null);
 
         PayloadDTO payload = new PayloadDTO();
@@ -1127,7 +1129,34 @@ public class OpenIMServiceImpl implements OpenIMService {
         openImBatchMsgDTO.setOfflinePushInfo(offlinePushInfo);
         openImBatchMsgDTO.setIsSendAll(false);
 
-        log.info("批量发送课程消息: \n{}", JSON.toJSONString(openImBatchMsgDTO));
+        OpenImResponseDTO openImResponseDTO = new OpenImResponseDTO();
+        // 保存发送时间到缓存中
+        if(batchSendCourseDTO.getSendTime() != null && batchSendCourseDTO.getSendTime().compareTo(new Date()) > 0) {
+            // 定时发送
+            for (String userId : userIds) {
+                String redisKey = "openIm:batchSendMsg";
+                Map<String, Object> redisMap = new HashMap<>();
+                BatchSendCourseAllDTO batchSendCourseAllDTO = new BatchSendCourseAllDTO();
+                batchSendCourseAllDTO.setBatchSendCourseDTO(batchSendCourseDTO).setOpenImBatchMsgDTO(openImBatchMsgDTO).setProject(project);
+                redisMap.put(batchSendCourseDTO.getCourseId()+":"+batchSendCourseDTO.getVideoId()+":"+userId+":"+batchSendCourseDTO.getSendTime().getTime()
+                        , batchSendCourseAllDTO);
+                redisCache.setCacheMap(redisKey, redisMap);
+            }
+            openImResponseDTO.setErrCode(0);
+            openImResponseDTO.setErrMsg("计划发送创建成功,待消息发送");
+        } else {
+            // 实时发送
+            openImResponseDTO = this.batchSendMsgTask(batchSendCourseDTO, openImBatchMsgDTO, project, 2);
+            openImResponseDTO.setErrMsg("实时发送成功");
+        }
+        return openImResponseDTO;
+    }
+
+    @Override
+    @Transactional
+    public OpenImResponseDTO batchSendMsgTask(BatchSendCourseDTO batchSendCourseDTO, OpenImBatchMsgDTO openImBatchMsgDTO, Long project, Integer sendType) {
+
+         log.info("批量发送课程消息: \n{}", JSON.toJSONString(openImBatchMsgDTO));
         OpenImResponseDTO openImResponseDTO = openIMBatchSendMsg(openImBatchMsgDTO);
 //        openImBatchMsgDTO = null;
 //        content = null;
@@ -1139,14 +1168,14 @@ public class OpenIMServiceImpl implements OpenIMService {
             List<OpenImBatchResponseDataDTO.Results> results = openImBatchResponseDataDTO.getResults();
 
             // 生成发送记录
-            this.batchInsertSendLogs(openImBatchMsgDTO, openImResponseDTO, openImBatchResponseDataDTO, planSendTimeStamp);
+            this.batchInsertSendLogs(openImBatchMsgDTO, openImResponseDTO, openImBatchResponseDataDTO, sendType);
 
             // 生成看课记录
-            this.batchInsertWatchLogs(batchSendCourseDTO, results, fsUserCourse);
+            this.batchInsertWatchLogs(batchSendCourseDTO, results, project);
 
         } else {
             // 生成发送记录
-            this.batchInsertSendLogs(openImBatchMsgDTO, openImResponseDTO, null, planSendTimeStamp);
+            this.batchInsertSendLogs(openImBatchMsgDTO, openImResponseDTO, null, sendType);
             log.error("发送消息失败,结果:{}", openImResponseDTO);
             throw new ServiceException("发送消息失败");
         }
@@ -1166,10 +1195,10 @@ public class OpenIMServiceImpl implements OpenIMService {
         return fsUserCompanyUsers.stream().map(v -> "U" + v.getUserId()).collect(Collectors.toList());
     }
 
-    private void batchInsertSendLogs(OpenImBatchMsgDTO openImBatchMsgDTO, OpenImResponseDTO openImResponseDTO, OpenImBatchResponseDataDTO openImBatchResponseDataDTO, long planSendTimeStamp) {
+    private void batchInsertSendLogs(OpenImBatchMsgDTO openImBatchMsgDTO, OpenImResponseDTO openImResponseDTO, OpenImBatchResponseDataDTO openImBatchResponseDataDTO, Integer sendType) {
         List<ImSendLog> list = new LinkedList<>();
         if(openImResponseDTO.getErrCode() != 0){
-            ImSendLog imSendLog = createImsendLog(openImBatchMsgDTO, planSendTimeStamp);
+            ImSendLog imSendLog = createImsendLog(openImBatchMsgDTO, openImBatchMsgDTO.getSendTime());
             imSendLog.setStatus(1);
             imSendLog.setResultMessage(JSON.toJSONString(openImResponseDTO.getErrMsg()));
             imSendLog.setExceptionInfo(JSON.toJSONString(openImResponseDTO.getErrDlt()));
@@ -1177,24 +1206,20 @@ public class OpenIMServiceImpl implements OpenIMService {
         } else {
             if(openImBatchResponseDataDTO.getFailedUserIDs() != null) {
                 for (String failedUserID : openImBatchResponseDataDTO.getFailedUserIDs()) {
-                    ImSendLog imSendLog = createImsendLog(openImBatchMsgDTO, planSendTimeStamp);
+                    ImSendLog imSendLog = createImsendLog(openImBatchMsgDTO, openImBatchMsgDTO.getSendTime());
                     imSendLog.setRecvId(failedUserID);
                     imSendLog.setStatus(1);
-                    imSendLog.setResultMessage(JSON.toJSONString(openImBatchResponseDataDTO.getResults()));
+                    imSendLog.setResultMessage(JSON.toJSONString(openImBatchResponseDataDTO));
                     list.add(imSendLog);
                 }
             }
             for (OpenImBatchResponseDataDTO.Results result : openImBatchResponseDataDTO.getResults()) {
-                ImSendLog imSendLog = createImsendLog(openImBatchMsgDTO, planSendTimeStamp);
+                ImSendLog imSendLog = createImsendLog(openImBatchMsgDTO, openImBatchMsgDTO.getSendTime());
                 imSendLog.setRecvId(result.getRecvID());
                 imSendLog.setActualSendTime(new Date(result.getSendTime()));
-                if(planSendTimeStamp == result.getSendTime()){
-                    imSendLog.setSendType(2);
-                } else {
-                    imSendLog.setSendType(1);
-                }
+                imSendLog.setSendType(sendType);
                 imSendLog.setStatus(0);
-                imSendLog.setResultMessage(JSON.toJSONString(openImBatchResponseDataDTO.getResults()));
+                imSendLog.setResultMessage(JSON.toJSONString(openImBatchResponseDataDTO));
                 list.add(imSendLog);
             }
         }
@@ -1212,8 +1237,7 @@ public class OpenIMServiceImpl implements OpenIMService {
         return imSendLog;
     }
 
-    @Transactional
-    public void batchInsertWatchLogs(BatchSendCourseDTO batchSendCourseDTO, List<OpenImBatchResponseDataDTO.Results> results, FsUserCourse fsUserCourse) {
+    public void batchInsertWatchLogs(BatchSendCourseDTO batchSendCourseDTO, List<OpenImBatchResponseDataDTO.Results> results, Long project) {
         List<FsCourseWatchLog> watchLogsInsertList = new LinkedList<>();
         for (OpenImBatchResponseDataDTO.Results result : results) {
             FsCourseWatchLog fsCourseWatchLog = new FsCourseWatchLog();
@@ -1224,7 +1248,7 @@ public class OpenIMServiceImpl implements OpenIMService {
             fsCourseWatchLog.setDuration(0L);
             fsCourseWatchLog.setCreateTime(new Date());
             fsCourseWatchLog.setLogType(3);
-            fsCourseWatchLog.setProject(fsUserCourse != null ? fsUserCourse.getProject() : null);
+            fsCourseWatchLog.setProject(project);
             watchLogsInsertList.add(fsCourseWatchLog);
         }
         courseWatchLogMapper.insertFsCourseWatchLogBatch(watchLogsInsertList);

+ 4 - 2
fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml

@@ -312,7 +312,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         reward_type,
         sop_id,
         camp_period_time,
-        project
+        project,
+        period_id
         )
         VALUES
         <foreach collection="watchLogs" item="log" separator=",">
@@ -332,7 +333,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{log.rewardType},
             #{log.sopId},
             #{log.campPeriodTime},
-            #{log.project}
+            #{log.project},
+            #{log.periodId}
             )
         </foreach>
         ON DUPLICATE KEY UPDATE