wangyunpeng 1 день назад
Родитель
Сommit
8f657bdc88

+ 186 - 103
api-module/src/main/java/com/tzld/piaoquan/api/job/wecom/thirdpart/WeComSendMsgJob.java

@@ -1,8 +1,8 @@
 package com.tzld.piaoquan.api.job.wecom.thirdpart;
 
 import com.alibaba.fastjson.JSONObject;
-import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.tzld.piaoquan.api.common.enums.wecom.ConfigTaskContentTypeEnum;
 import com.tzld.piaoquan.api.common.enums.wecom.MsgSendStatusEnum;
 import com.tzld.piaoquan.api.component.VideoApiService;
 import com.tzld.piaoquan.api.dao.mapper.contentplatform.ext.ContentPlatformPlanMapperExt;
@@ -10,11 +10,10 @@ import com.tzld.piaoquan.api.dao.mapper.wecom.thirdpart.ThirdPartWeComMsgMapper;
 import com.tzld.piaoquan.api.dao.mapper.wecom.thirdpart.ThirdPartWeComRoomMapper;
 import com.tzld.piaoquan.api.model.param.wecom.thirdpart.*;
 import com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformVideo;
-import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComMsg;
-import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComMsgExample;
-import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComRoom;
-import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComStaff;
+import com.tzld.piaoquan.api.model.po.wecom.thirdpart.*;
 import com.tzld.piaoquan.api.model.vo.contentplatform.WxVideoV2VO;
+import com.tzld.piaoquan.api.service.wecom.thirdparty.WeComThirdPartyAccountService;
+import com.tzld.piaoquan.api.service.wecom.thirdparty.WeComThirdPartyRoomService;
 import com.tzld.piaoquan.api.service.wecom.thirdparty.WeComThirdPartyService;
 import com.tzld.piaoquan.api.util.CdnUtil;
 import com.tzld.piaoquan.growth.common.model.po.CgiReplyBucketData;
@@ -38,6 +37,7 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -47,6 +47,10 @@ public class WeComSendMsgJob {
     @Autowired
     WeComThirdPartyService weComThirdPartyService;
     @Autowired
+    WeComThirdPartyAccountService weComThirdPartyAccountService;
+    @Autowired
+    WeComThirdPartyRoomService weComThirdPartyRoomService;
+    @Autowired
     MessageAttachmentService messageAttachmentService;
     @Autowired
     VideoApiService videoApiService;
@@ -64,20 +68,6 @@ public class WeComSendMsgJob {
     private Double videoMinScore;
     @Value("${send.room.msg.duplicate.days:7}")
     private Integer duplicateDays;
-    @Value("${send.room.msg.video.num:2}")
-    private Integer videoNum;
-    @ApolloJsonValue("${send.room.msg.test.roomList:[]}")
-    private List<String> testRoomList;
-    @ApolloJsonValue("${send.room.msg.video.source.staff.config:{}}")
-    private Map<Long, JSONObject> videoSourceStaffConfig;
-    @ApolloJsonValue("${send.room.msg.staff.put.scene.config:{}}")
-    private Map<Long, String> staffPutSceneConfig;
-    @ApolloJsonValue("${send.room.msg.staff.channel.config:{}}")
-    private Map<Long, String> staffChannelConfig;
-    @ApolloJsonValue("${send.room.msg.auto.open.staff:[]}")
-    private List<Long> autoOpenStaffList;
-    @Value("${send.room.msg.random.time:20}")
-    private Integer randomTimeRange;
 
     private final static ExecutorService pool = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.SECONDS,
             new LinkedBlockingQueue<>(),
@@ -88,24 +78,68 @@ public class WeComSendMsgJob {
     public ReturnT<String> autoSendAppMsg(String param) {
         List<ThirdPartWeComStaff> activeStaffList = weComThirdPartyService.getActiveStaffList();
         String time = DateUtil.getCurrentDateStr("HH:mm");
+        List<Long> staffIdList = activeStaffList.stream().map(ThirdPartWeComStaff::getId).collect(Collectors.toList());
+        List<ThirdPartWeComStaffConfig> staffConfigList = weComThirdPartyAccountService.getStaffConfigListByStaffIds(staffIdList);
+        Map<Long, ThirdPartWeComStaffConfig> staffConfigMap = staffConfigList.stream().collect(Collectors.toMap(ThirdPartWeComStaffConfig::getStaffId, a -> a));
         for (ThirdPartWeComStaff staff : activeStaffList) {
+            ThirdPartWeComStaffConfig staffConfig = staffConfigMap.get(staff.getId());
+            if (Objects.isNull(staffConfig) || staffConfig.getSwitchFlag() != 1) {
+                continue;
+            }
             List<ThirdPartWeComRoom> roomList = weComThirdPartyService.getStaffRoomList(staff.getId());
+            List<Long> roomIds = roomList.stream().map(ThirdPartWeComRoom::getId).collect(Collectors.toList());
+            List<ThirdPartWeComRoomConfig> roomConfigList = weComThirdPartyRoomService.getRoomConfigListByRoomIds(roomIds);
+            Map<Long, ThirdPartWeComRoomConfig> roomConfigMap = roomConfigList.stream().collect(Collectors.toMap(ThirdPartWeComRoomConfig::getRoomId, a -> a));
+            List<String> configIds = roomConfigList.stream().map(ThirdPartWeComRoomConfig::getId).map(String::valueOf).collect(Collectors.toList());
+            List<ThirdPartWeComRoomConfigTask> roomConfigTaskList = weComThirdPartyRoomService.getRoomConfigTasks(configIds);
+            Map<String, List<ThirdPartWeComRoomConfigTask>> roomConfigTaskMap = roomConfigTaskList.stream()
+                    .filter(o -> o.getSwitchFlag() == 1).collect(Collectors.groupingBy(ThirdPartWeComRoomConfigTask::getConfigId));
             for (ThirdPartWeComRoom room : roomList) {
                 if (room.getSendStatus() != 1) {
                     continue;
                 }
                 pool.execute(() -> {
-                    List<String> timeList = getRoomSendTime(room);
-                    if (timeList.contains(time)) {
-                        // 选取视频
-                        List<CgiReplyBucketData> cgiReplyBucketDataList = getCgiReplyBucketData(room.getThirdRoomId(), staff);
-                        for (CgiReplyBucketData cgiReplyBucketData : cgiReplyBucketDataList) {
-                            // build发送体
-                            SendAppMsgRequest request = buildSendAppMsgRequest(cgiReplyBucketData, staff, room);
-                            // 发送消息
-                            CommonResponse<SendAppMsgResponse> response = weComThirdPartyService.sendAppMsg(staff, room, request);
-                            // 存储消息
-                            saveWeComMsg(staff.getId(), cgiReplyBucketData.getMiniVideoId(), request, response);
+                    ThirdPartWeComRoomConfig roomConfig = roomConfigMap.get(room.getId());
+                    if (roomConfig == null) {
+                        return;
+                    }
+                    List<ThirdPartWeComRoomConfigTask> taskList = roomConfigTaskMap.getOrDefault(roomConfig.getId(), new ArrayList<>());
+                    if (taskList.isEmpty()) {
+                        return;
+                    }
+                    List<String> configTaskIds = taskList.stream().map(ThirdPartWeComRoomConfigTask::getId).collect(Collectors.toList());
+                    List<ThirdPartWeComRoomConfigTaskContent> taskContentList = weComThirdPartyRoomService.getRoomConfigTaskContents(configTaskIds);
+                    Map<String, List<ThirdPartWeComRoomConfigTaskContent>> taskContentMap = taskContentList.stream()
+                            .collect(Collectors.groupingBy(ThirdPartWeComRoomConfigTaskContent::getTaskId));
+                    for (ThirdPartWeComRoomConfigTask configTask : taskList) {
+                        List<String> timeList = getRoomSendTime(room, roomConfig, configTask);
+                        if (timeList.contains(time)) {
+                            // 选取视频
+                            List<ThirdPartWeComRoomConfigTaskContent> contentList = taskContentMap.get(configTask.getId());
+                            if (Objects.isNull(contentList) || contentList.isEmpty()) {
+                                continue;
+                            }
+                            contentList = contentList.stream().sorted(Comparator.comparing(ThirdPartWeComRoomConfigTaskContent::getSeq)).collect(Collectors.toList());
+                            for (ThirdPartWeComRoomConfigTaskContent configTaskContent : contentList) {
+                                if (ConfigTaskContentTypeEnum.TEXT.getVal() != configTaskContent.getType()) {
+                                    // build发送体
+                                    SendTextMsgRequest request = buildSendTextMsgRequest(configTaskContent.getContent(), staff, room);
+                                    // 发送消息
+                                    CommonResponse<SendTextMsgResponse> response = weComThirdPartyService.sendTextMsg(staff, room, request);
+                                    // 存储消息
+                                    saveTextWeComMsg(staff.getId(), configTaskContent.getContent(), request, response);
+                                } else if (ConfigTaskContentTypeEnum.MINI_PROGRAM.getVal() == configTaskContent.getType()) {
+                                    List<CgiReplyBucketData> cgiReplyBucketDataList = getCgiReplyBucketData(room.getThirdRoomId(), staff, roomConfig, configTaskContent);
+                                    for (CgiReplyBucketData cgiReplyBucketData : cgiReplyBucketDataList) {
+                                        // build发送体
+                                        SendAppMsgRequest request = buildSendAppMsgRequest(cgiReplyBucketData, staff, room);
+                                        // 发送消息
+                                        CommonResponse<SendAppMsgResponse> response = weComThirdPartyService.sendAppMsg(staff, room, request);
+                                        // 存储消息
+                                        saveAppWeComMsg(staff.getId(), cgiReplyBucketData.getMiniVideoId(), request, response);
+                                    }
+                                }
+                            }
                         }
                     }
                 });
@@ -114,14 +148,29 @@ public class WeComSendMsgJob {
         return ReturnT.SUCCESS;
     }
 
-    private List<String> getRoomSendTime(ThirdPartWeComRoom room) {
-        String timeStr = redisUtils.get("wecom:room:send:time:" + room.getThirdRoomId());
+    private List<String> getRoomSendTime(ThirdPartWeComRoom room,
+                                         ThirdPartWeComRoomConfig roomConfig,
+                                         ThirdPartWeComRoomConfigTask configTask) {
+        String key = "wecom:room:send:time:" + room.getThirdRoomId() + ":" + roomConfig.getId() + ":" + configTask.getId();
+        String timeStr = redisUtils.get(key);
         if (StringUtils.isBlank(timeStr)) {
             return JSONObject.parseArray(room.getSendTime()).toJavaList(String.class);
         }
         return JSONObject.parseArray(timeStr).toJavaList(String.class);
     }
 
+    private SendTextMsgRequest buildSendTextMsgRequest(String content,
+                                                       ThirdPartWeComStaff staff,
+                                                       ThirdPartWeComRoom room) {
+        String thirdRoomId = room.getThirdRoomId();
+        SendTextMsgRequest request = new SendTextMsgRequest();
+        request.setUuid(staff.getThirdUuid());
+        request.setSend_userid(Long.valueOf(thirdRoomId));
+        request.setIsRoom(true);
+        request.setContent(content);
+        return request;
+    }
+
     private SendAppMsgRequest buildSendAppMsgRequest(CgiReplyBucketData cgiReplyBucketData,
                                                      ThirdPartWeComStaff staff,
                                                      ThirdPartWeComRoom room) {
@@ -136,11 +185,8 @@ public class WeComSendMsgJob {
         request.setTitle(cgiReplyBucketData.getTitle());
         request.setWeappIconUrl("http://rescdn.yishihui.com/temp/1755515422185_%E7%A5%A8%E5%9C%88Vlog_logo.jpg");
         // 填充视频信息
-        String coverUrl = cgiReplyBucketData.getCoverUrl();
-        // 实验 封面添加播放按钮水印
-        if (!testRoomList.contains(thirdRoomId)) {
-            coverUrl = addPlayWatermark(cgiReplyBucketData.getCoverUrl());
-        }
+        // 封面添加播放按钮水印
+        String coverUrl = addPlayWatermark(cgiReplyBucketData.getCoverUrl());
         request.setDesc(cgiReplyBucketData.getTitle());
         request.setPagepath(cgiReplyBucketData.getMiniPagePath());
         CdnUploadImgLinkRequest cdnUploadImgLinkRequest = new CdnUploadImgLinkRequest();
@@ -165,7 +211,10 @@ public class WeComSendMsgJob {
         return coverUrl + waterMark;
     }
 
-    private List<CgiReplyBucketData> getCgiReplyBucketData(String roomId, ThirdPartWeComStaff thirdPartWeComStaff) {
+    private List<CgiReplyBucketData> getCgiReplyBucketData(String roomId,
+                                                           ThirdPartWeComStaff thirdPartWeComStaff,
+                                                           ThirdPartWeComRoomConfig roomConfig,
+                                                           ThirdPartWeComRoomConfigTaskContent configTaskContent) {
         String dt = planMapperExt.getVideoMaxDt();
         String datastatDt = planMapperExt.getVideoDatastatMaxDt();
         // 排除最近发送过的视频
@@ -174,34 +223,32 @@ public class WeComSendMsgJob {
         String sort = "datastat.fission_rate desc, video.score desc";
         String type = "企微-社群";
         String channel = "sum";
-        List<ContentPlatformVideo> videoList = getVideoByStrategy(thirdPartWeComStaff.getThirdStaffId(), roomId, dt, datastatDt, type, channel, videoMinScore,
-                sentVideoIds, 1, 100, sort);
+        List<ContentPlatformVideo> videoList = getVideoByStrategy(thirdPartWeComStaff.getThirdStaffId(), roomId,
+                dt, datastatDt, type, channel, videoMinScore, sentVideoIds, configTaskContent, 1, 100, sort);
         if (CollectionUtils.isEmpty(videoList)) {
             LarkRobotUtil.sendWeComThirdPartMessage(
                     "【账号发送群消息,视频数量不足通知】\n" +
                             "账号名称:" + thirdPartWeComStaff.getName() + "\n" +
                             "账号VID:" + thirdPartWeComStaff.getThirdStaffId() + "\n" +
                             "群ID:" + roomId + "\n" +
-                            "账号配置:" + videoSourceStaffConfig.get(thirdPartWeComStaff.getId()));
+                            "账号配置:" + JSONObject.toJSONString(configTaskContent));
             return Collections.emptyList();
         }
         List<CgiReplyBucketData> result = new ArrayList<>();
-        for (int i = 0; i < videoNum; i++) {
-            ContentPlatformVideo video = videoList.get(i);
-            Staff staff = new Staff();
-            staff.setCarrierId(String.valueOf(thirdPartWeComStaff.getThirdStaffId()));
-            staff.setRemark(thirdPartWeComStaff.getName());
-            String putScene = staffPutSceneConfig.getOrDefault(thirdPartWeComStaff.getThirdStaffId(), "touliu");
-            String pageChannel = staffChannelConfig.getOrDefault(thirdPartWeComStaff.getThirdStaffId(), "tencentqw");
-            String page = messageAttachmentService.getPageNoCache(putScene, pageChannel, staff, video.getVideoId(), "企微", "社群");
+        ContentPlatformVideo video = videoList.get(0);
+        Staff staff = new Staff();
+        staff.setCarrierId(String.valueOf(thirdPartWeComStaff.getThirdStaffId()));
+        staff.setRemark(thirdPartWeComStaff.getName());
+        String putScene = StringUtils.isNotBlank(roomConfig.getPutScene()) ? roomConfig.getPutScene() : "touliu";
+        String pageChannel = StringUtils.isNotBlank(roomConfig.getChannel()) ? roomConfig.getChannel() : "tencentqw";
+        String page = messageAttachmentService.getPageNoCache(putScene, pageChannel, staff, video.getVideoId(), "企微", "社群");
 
-            CgiReplyBucketData cgiReplyBucketData = new CgiReplyBucketData();
-            cgiReplyBucketData.setMiniVideoId(video.getVideoId());
-            cgiReplyBucketData.setTitle(video.getTitle());
-            cgiReplyBucketData.setCoverUrl(video.getCover());
-            cgiReplyBucketData.setMiniPagePath(page);
-            result.add(cgiReplyBucketData);
-        }
+        CgiReplyBucketData cgiReplyBucketData = new CgiReplyBucketData();
+        cgiReplyBucketData.setMiniVideoId(video.getVideoId());
+        cgiReplyBucketData.setTitle(video.getTitle());
+        cgiReplyBucketData.setCoverUrl(video.getCover());
+        cgiReplyBucketData.setMiniPagePath(page);
+        result.add(cgiReplyBucketData);
         return result;
     }
 
@@ -213,19 +260,16 @@ public class WeComSendMsgJob {
                                                           String channel,
                                                           Double videoMinScore,
                                                           List<Long> sentVideoIds,
+                                                          ThirdPartWeComRoomConfigTaskContent configTaskContent,
                                                           int pageNum,
                                                           int pageSize,
                                                           String sort) {
         List<ContentPlatformVideo> result = new ArrayList<>();
-        JSONObject staffConfig = videoSourceStaffConfig.get(staffId);
-        if (staffConfig == null) {
-            staffConfig = new JSONObject();
-        }
         List<ContentPlatformVideo> videoList;
-        String source = (String) staffConfig.getOrDefault("source", "");
-        switch (source) {
-            case "user":
-                Long uid = staffConfig.getLong("uid");
+        // 0-热榜 1-标签 2-账号
+        switch (configTaskContent.getSource()) {
+            case 2:
+                Long uid = Long.valueOf(configTaskContent.getSourceContent());
                 List<WxVideoV2VO> list = videoApiService.getUserVideoList(uid, sentVideoIds, pageNum, pageSize);
                 if (CollectionUtils.isEmpty(list)) {
                     break;
@@ -233,8 +277,8 @@ public class WeComSendMsgJob {
                 videoList = convertWxVideoV2VOToVideo(list);
                 result.addAll(videoList);
                 break;
-            case "tag":
-                String tagName = staffConfig.getString("tagName");
+            case 1:
+                String tagName = configTaskContent.getSourceContent();
                 list = videoApiService.getTagVideoList(tagName, roomId, sentVideoIds, pageNum, pageSize);
                 if (CollectionUtils.isEmpty(list)) {
                     break;
@@ -272,7 +316,7 @@ public class WeComSendMsgJob {
         return msgList.stream().map(ThirdPartWeComMsg::getVideoId).collect(Collectors.toList());
     }
 
-    private void saveWeComMsg(Long staffId, Long videoId, SendAppMsgRequest request, CommonResponse<SendAppMsgResponse> response) {
+    private void saveAppWeComMsg(Long staffId, Long videoId, SendAppMsgRequest request, CommonResponse<SendAppMsgResponse> response) {
         ThirdPartWeComMsg msg = new ThirdPartWeComMsg();
         msg.setStaffId(staffId);
         msg.setVideoId(videoId);
@@ -299,11 +343,30 @@ public class WeComSendMsgJob {
         msgMapper.insertSelective(msg);
     }
 
+    private void saveTextWeComMsg(Long staffId, String content, SendTextMsgRequest request, CommonResponse<SendTextMsgResponse> response) {
+        ThirdPartWeComMsg msg = new ThirdPartWeComMsg();
+        msg.setStaffId(staffId);
+        msg.setUuid(request.getUuid());
+        msg.setSendUserid(request.getSend_userid());
+        msg.setIsroom(request.getIsRoom());
+        if (response.getErrcode() == 0) {
+            msg.setStatus(MsgSendStatusEnum.NORMAL.getVal());
+        } else {
+            msg.setStatus(MsgSendStatusEnum.FAIL.getVal());
+        }
+        // todo save text msg
+        //msgMapper.insertSelective(msg);
+    }
+
     @XxlJob("autoOpenSendStatusJob")
     public ReturnT<String> autoOpenSendStatusJob(String param) {
         List<ThirdPartWeComStaff> activeStaffList = weComThirdPartyService.getActiveStaffList();
+        List<Long> staffIdList = activeStaffList.stream().map(ThirdPartWeComStaff::getId).collect(Collectors.toList());
+        List<ThirdPartWeComStaffConfig> staffConfigList = weComThirdPartyAccountService.getStaffConfigListByStaffIds(staffIdList);
+        Map<Long, ThirdPartWeComStaffConfig> staffConfigMap = staffConfigList.stream().collect(Collectors.toMap(ThirdPartWeComStaffConfig::getStaffId, a -> a));
         for (ThirdPartWeComStaff staff : activeStaffList) {
-            if (!autoOpenStaffList.contains(staff.getThirdStaffId())) {
+            ThirdPartWeComStaffConfig staffConfig = staffConfigMap.get(staff.getId());
+            if (Objects.isNull(staffConfig) || staffConfig.getSwitchFlag() != 1 || Objects.isNull(staffConfig.getOpenRoomSendSwitchNum())) {
                 continue;
             }
             List<ThirdPartWeComRoom> roomList = weComThirdPartyService.getStaffRoomList(staff.getId());
@@ -311,7 +374,7 @@ public class WeComSendMsgJob {
                 if (room.getSendStatus() == 1) {
                     continue;
                 }
-                if (room.getMemberCount() > 20) {
+                if (room.getMemberCount() > staffConfig.getOpenRoomSendSwitchNum()) {
                     room.setSendStatus(1);
                     roomMapper.updateByPrimaryKeySelective(room);
                 }
@@ -326,47 +389,67 @@ public class WeComSendMsgJob {
         String now = DateUtil.getCurrentDateStr("HH:mm");
         for (ThirdPartWeComStaff staff : activeStaffList) {
             List<ThirdPartWeComRoom> roomList = weComThirdPartyService.getStaffRoomList(staff.getId());
+            List<ThirdPartWeComRoomConfig> roomConfigList = weComThirdPartyRoomService.getRoomConfigListByRoomIds(roomList.stream().map(ThirdPartWeComRoom::getId).collect(Collectors.toList()));
+            Map<Long, ThirdPartWeComRoomConfig> roomConfigMap = roomConfigList.stream().collect(Collectors.toMap(ThirdPartWeComRoomConfig::getRoomId, Function.identity()));
+            List<String> configIds = roomConfigList.stream().map(ThirdPartWeComRoomConfig::getId).map(String::valueOf).collect(Collectors.toList());
+            List<ThirdPartWeComRoomConfigTask> roomConfigTaskList = weComThirdPartyRoomService.getRoomConfigTasks(configIds);
+            Map<String, List<ThirdPartWeComRoomConfigTask>> roomConfigTaskMap = roomConfigTaskList.stream().collect(Collectors.groupingBy(ThirdPartWeComRoomConfigTask::getConfigId));
             for (ThirdPartWeComRoom room : roomList) {
-                if (room.getSendStatus() != 1) {
+                ThirdPartWeComRoomConfig roomConfig = roomConfigMap.get(room.getId());
+                if (roomConfig == null) {
                     continue;
                 }
-                String key = "wecom:room:send:time:" + room.getThirdRoomId();
-                if (redisUtils.containsKey(key)) {
+                List<ThirdPartWeComRoomConfigTask> taskList = roomConfigTaskMap.getOrDefault(roomConfig.getId(), new ArrayList<>());
+                if (taskList.isEmpty()) {
                     continue;
                 }
-                List<String> timeList = JSONObject.parseArray(room.getSendTime()).toJavaList(String.class);
-                // 判断timeList中在now之后的时间,随机增加或减少20以内的分钟数
-                List<String> newTimeList = new ArrayList<>();
-                for (String time : timeList) {
-                    // time与now比较,判断是否在now之后
-                    int hour = Integer.parseInt(time.substring(0, 2));
-                    int minute = Integer.parseInt(time.substring(3, 5));
-                    int nowHour = Integer.parseInt(now.substring(0, 2));
-                    int nowMinute = Integer.parseInt(now.substring(3, 5));
-                    if (hour < nowHour || (hour == nowHour && minute <= nowMinute)) {
-                        newTimeList.add(time);
-                        continue;
-                    }
-                    // 增加或减少20以内的分钟数 -20~20
-                    int randomMinute = new Random().nextInt(randomTimeRange * 2) - randomTimeRange;
-                    minute += randomMinute;
-                    if (minute < 0) {
-                        hour--;
-                        minute += 60;
-                    } else if (minute >= 60) {
-                        hour++;
-                        minute -= 60;
-                    }
-                    // 确保时间在now之后
-                    if (hour < nowHour || (hour == nowHour && minute <= nowMinute)) {
-                        newTimeList.add(time);
-                        continue;
-                    }
-                    newTimeList.add(String.format("%02d:%02d", hour, minute));
-                }
-                redisUtils.set(key, JSONObject.toJSONString(newTimeList), 18 * 60 * 60);
+                randomRoomSendTime(room, roomConfig, taskList, now);
             }
         }
         return ReturnT.SUCCESS;
     }
+
+    public void randomRoomSendTime(ThirdPartWeComRoom room,
+                                   ThirdPartWeComRoomConfig roomConfig,
+                                   List<ThirdPartWeComRoomConfigTask> taskList,
+                                   String now) {
+        for (ThirdPartWeComRoomConfigTask configTask : taskList) {
+            String key = "wecom:room:send:time:" + room.getThirdRoomId() + ":" + roomConfig.getId() + ":" + configTask.getId();
+            if (redisUtils.containsKey(key)) {
+                continue;
+            }
+            List<String> timeList = JSONObject.parseArray(room.getSendTime()).toJavaList(String.class);
+            // 判断timeList中在now之后的时间,随机增加或减少20以内的分钟数
+            List<String> newTimeList = new ArrayList<>();
+            for (String time : timeList) {
+                // time与now比较,判断是否在now之后
+                int hour = Integer.parseInt(time.substring(0, 2));
+                int minute = Integer.parseInt(time.substring(3, 5));
+                int nowHour = Integer.parseInt(now.substring(0, 2));
+                int nowMinute = Integer.parseInt(now.substring(3, 5));
+                if (hour < nowHour || (hour == nowHour && minute <= nowMinute)) {
+                    newTimeList.add(time);
+                    continue;
+                }
+                // 增加或减少20以内的分钟数 -20~20
+                int randomTimeRange = Objects.isNull(configTask.getRandomMin()) ? 0 : configTask.getRandomMin();
+                int randomMinute = new Random().nextInt(randomTimeRange * 2) - randomTimeRange;
+                minute += randomMinute;
+                if (minute < 0) {
+                    hour--;
+                    minute += 60;
+                } else if (minute >= 60) {
+                    hour++;
+                    minute -= 60;
+                }
+                // 确保时间在now之后
+                if (hour < nowHour || (hour == nowHour && minute <= nowMinute)) {
+                    newTimeList.add(time);
+                    continue;
+                }
+                newTimeList.add(String.format("%02d:%02d", hour, minute));
+            }
+            redisUtils.set(key, JSONObject.toJSONString(newTimeList), 18 * 60 * 60);
+        }
+    }
 }

+ 21 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/param/wecom/thirdpart/SendTextMsgResponse.java

@@ -0,0 +1,21 @@
+package com.tzld.piaoquan.api.model.param.wecom.thirdpart;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SendTextMsgResponse {
+    private Long receiver;
+    private Long sender;
+    private List<Long> atList;
+    private String senderName;
+    private String app_info;
+    private Integer isRoom;
+    private Long sendtime;
+    private Long msgId;
+    private Long serverId;
+    private Integer msgtype;
+    private String content;
+
+}

+ 3 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/wecom/thirdparty/WeComThirdPartyAccountService.java

@@ -1,6 +1,7 @@
 package com.tzld.piaoquan.api.service.wecom.thirdparty;
 
 import com.tzld.piaoquan.api.model.param.wecom.thirdpart.*;
+import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComStaffConfig;
 import com.tzld.piaoquan.api.model.vo.IdNameVO;
 import com.tzld.piaoquan.api.model.vo.contentplatform.AccountQrCodeVO;
 import com.tzld.piaoquan.api.model.vo.wecom.thirdpart.ThirdPartyAccountConfigVO;
@@ -26,4 +27,6 @@ public interface WeComThirdPartyAccountService {
     void saveAccountConfig(ThirdPartyAccountConfigParam param);
 
     void logout(ThirdPartyAccountLogOutParam param);
+
+    List<ThirdPartWeComStaffConfig> getStaffConfigListByStaffIds(List<Long> staffIdList);
 }

+ 9 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/wecom/thirdparty/WeComThirdPartyRoomService.java

@@ -5,6 +5,9 @@ import com.tzld.piaoquan.api.model.param.wecom.thirdpart.ThirdPartyConfigGetPara
 import com.tzld.piaoquan.api.model.param.wecom.thirdpart.ThirdPartyRoomConfigParam;
 import com.tzld.piaoquan.api.model.param.wecom.thirdpart.ThirdPartyRoomListParam;
 import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComRoom;
+import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComRoomConfig;
+import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComRoomConfigTask;
+import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComRoomConfigTaskContent;
 import com.tzld.piaoquan.api.model.vo.IdNameVO;
 import com.tzld.piaoquan.api.model.vo.wecom.thirdpart.ThirdPartyRoomConfigVO;
 import com.tzld.piaoquan.api.model.vo.wecom.thirdpart.ThirdPartyRoomVO;
@@ -20,7 +23,13 @@ public interface WeComThirdPartyRoomService {
 
     ThirdPartyRoomConfigVO getRoomConfig(ThirdPartyConfigGetParam param);
 
+    List<ThirdPartWeComRoomConfigTask> getRoomConfigTasks(List<String> configIds);
+
+    List<ThirdPartWeComRoomConfigTaskContent> getRoomConfigTaskContents(List<String> taskIds);
+
     void saveRoomConfig(ThirdPartyRoomConfigParam param, String accountConfigId);
 
     void saveRoomConfig(ThirdPartWeComRoom room, String accountConfigId, ThirdPartyAccountConfigParam param);
+
+    List<ThirdPartWeComRoomConfig> getRoomConfigListByRoomIds(List<Long> roomIds);
 }

+ 2 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/wecom/thirdparty/WeComThirdPartyService.java

@@ -35,6 +35,8 @@ public interface WeComThirdPartyService {
 
     CommonResponse<SendAppMsgResponse> sendAppMsg(ThirdPartWeComStaff staff, ThirdPartWeComRoom room, SendAppMsgRequest request);
 
+    CommonResponse<SendTextMsgResponse> sendTextMsg(ThirdPartWeComStaff staff, ThirdPartWeComRoom room, SendTextMsgRequest request);
+
     List<ThirdPartWeComStaff> getActiveStaffList();
 
     List<ThirdPartWeComRoom> getAllStaffRoomList(Long staffId);

+ 7 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/wecom/thirdparty/impl/WeComThirdPartyAccountServiceImpl.java

@@ -388,4 +388,11 @@ public class WeComThirdPartyAccountServiceImpl implements WeComThirdPartyAccount
         staffMapper.updateByPrimaryKey(staff);
     }
 
+    @Override
+    public List<ThirdPartWeComStaffConfig> getStaffConfigListByStaffIds(List<Long> staffIdList) {
+        ThirdPartWeComStaffConfigExample example = new ThirdPartWeComStaffConfigExample();
+        example.createCriteria().andStaffIdIn(staffIdList).andStatusEqualTo(1);
+        return staffConfigMapper.selectByExample(example);
+    }
+
 }

+ 25 - 1
api-module/src/main/java/com/tzld/piaoquan/api/service/wecom/thirdparty/impl/WeComThirdPartyRoomServiceImpl.java

@@ -9,6 +9,7 @@ import com.tzld.piaoquan.api.dao.mapper.wecom.thirdpart.ThirdPartWeComRoomConfig
 import com.tzld.piaoquan.api.dao.mapper.wecom.thirdpart.ThirdPartWeComRoomConfigTaskMapper;
 import com.tzld.piaoquan.api.dao.mapper.wecom.thirdpart.ext.ThirdPartWeComRoomMapperExt;
 import com.tzld.piaoquan.api.dao.mapper.wecom.thirdpart.ext.ThirdPartWeComStaffMapperExt;
+import com.tzld.piaoquan.api.job.wecom.thirdpart.WeComSendMsgJob;
 import com.tzld.piaoquan.api.model.param.wecom.thirdpart.*;
 import com.tzld.piaoquan.api.model.po.wecom.thirdpart.*;
 import com.tzld.piaoquan.api.model.vo.IdNameVO;
@@ -18,6 +19,7 @@ import com.tzld.piaoquan.api.model.vo.wecom.thirdpart.ThirdPartyRoomConfigVO;
 import com.tzld.piaoquan.api.model.vo.wecom.thirdpart.ThirdPartyRoomVO;
 import com.tzld.piaoquan.api.service.wecom.thirdparty.WeComThirdPartyRoomService;
 import com.tzld.piaoquan.api.service.wecom.thirdparty.WeComThirdPartyService;
+import com.tzld.piaoquan.growth.common.utils.DateUtil;
 import com.tzld.piaoquan.growth.common.utils.DistributedIdGenerator;
 import com.tzld.piaoquan.growth.common.utils.page.Page;
 import lombok.extern.slf4j.Slf4j;
@@ -36,6 +38,8 @@ public class WeComThirdPartyRoomServiceImpl implements WeComThirdPartyRoomServic
     @Autowired
     private WeComThirdPartyService weComThirdPartyService;
     @Autowired
+    private WeComSendMsgJob weComSendMsgJob;
+    @Autowired
     private ThirdPartWeComRoomConfigMapper roomConfigMapper;
     @Autowired
     private ThirdPartWeComRoomConfigTaskMapper roomConfigTaskMapper;
@@ -197,7 +201,15 @@ public class WeComThirdPartyRoomServiceImpl implements WeComThirdPartyRoomServic
         return roomConfigTaskMapper.selectByExample(example);
     }
 
-    private List<ThirdPartWeComRoomConfigTaskContent> getRoomConfigTaskContents(List<String> taskIds) {
+    @Override
+    public List<ThirdPartWeComRoomConfigTask> getRoomConfigTasks(List<String> configIds) {
+        ThirdPartWeComRoomConfigTaskExample example = new ThirdPartWeComRoomConfigTaskExample();
+        example.createCriteria().andConfigIdIn(configIds);
+        return roomConfigTaskMapper.selectByExample(example);
+    }
+
+    @Override
+    public List<ThirdPartWeComRoomConfigTaskContent> getRoomConfigTaskContents(List<String> taskIds) {
         ThirdPartWeComRoomConfigTaskContentExample example = new ThirdPartWeComRoomConfigTaskContentExample();
         example.createCriteria().andTaskIdIn(taskIds);
         return roomConfigTaskContentMapper.selectByExample(example);
@@ -213,6 +225,7 @@ public class WeComThirdPartyRoomServiceImpl implements WeComThirdPartyRoomServic
             config.setUpdateTime(new Date());
             roomConfigMapper.updateByPrimaryKey(config);
         }
+        ThirdPartWeComRoom room = weComThirdPartyService.getRoomById(param.getRoomId());
         ThirdPartWeComRoomConfig newConfig = new ThirdPartWeComRoomConfig();
         newConfig.setId(DistributedIdGenerator.generate());
         newConfig.setAccountConfigId(accountConfigId);
@@ -225,6 +238,7 @@ public class WeComThirdPartyRoomServiceImpl implements WeComThirdPartyRoomServic
         newConfig.setCreateTime(new Date());
         newConfig.setUpdateTime(new Date());
         roomConfigMapper.insert(newConfig);
+        List<ThirdPartWeComRoomConfigTask> taskList = new ArrayList<>();
         for (ThirdPartyRoomConfigTaskParam taskParam : param.getTaskList()) {
             ThirdPartWeComRoomConfigTask newTask = new ThirdPartWeComRoomConfigTask();
             newTask.setId(DistributedIdGenerator.generate());
@@ -236,6 +250,7 @@ public class WeComThirdPartyRoomServiceImpl implements WeComThirdPartyRoomServic
             newTask.setCreateTime(new Date());
             newTask.setUpdateTime(new Date());
             roomConfigTaskMapper.insert(newTask);
+            taskList.add(newTask);
             for (ThirdPartyRoomConfigTaskContentParam taskContentParam : taskParam.getContentList()) {
                 ThirdPartWeComRoomConfigTaskContent newContent = new ThirdPartWeComRoomConfigTaskContent();
                 newContent.setId(DistributedIdGenerator.generate());
@@ -250,6 +265,8 @@ public class WeComThirdPartyRoomServiceImpl implements WeComThirdPartyRoomServic
                 roomConfigTaskContentMapper.insert(newContent);
             }
         }
+        String now = DateUtil.getCurrentDateStr("HH:mm");
+        weComSendMsgJob.randomRoomSendTime(room, newConfig, taskList, now);
     }
 
     private void checkRoomConfigParam(ThirdPartyRoomConfigParam param) {
@@ -332,4 +349,11 @@ public class WeComThirdPartyRoomServiceImpl implements WeComThirdPartyRoomServic
         roomConfigParam.setTaskList(taskList);
         return roomConfigParam;
     }
+
+    @Override
+    public List<ThirdPartWeComRoomConfig> getRoomConfigListByRoomIds(List<Long> roomIds) {
+        ThirdPartWeComRoomConfigExample example = new ThirdPartWeComRoomConfigExample();
+        example.createCriteria().andRoomIdIn(roomIds).andStatusEqualTo(1);
+        return roomConfigMapper.selectByExample(example);
+    }
 }

+ 17 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/wecom/thirdparty/impl/WeComThirdPartyServiceImpl.java

@@ -348,6 +348,23 @@ public class WeComThirdPartyServiceImpl implements WeComThirdPartyService {
         return commonResponse;
     }
 
+    @Override
+    public CommonResponse<SendTextMsgResponse> sendTextMsg(ThirdPartWeComStaff staff, ThirdPartWeComRoom room, SendTextMsgRequest request) {
+        String response = apiClient.sendTextMsg(request);
+        CommonResponse<SendTextMsgResponse> commonResponse =
+                JSONObject.parseObject(response, new TypeReference<CommonResponse<SendTextMsgResponse>>() {});
+        if (commonResponse.getErrcode() != 0) {
+            LarkRobotUtil.sendWeComThirdPartMessage(
+                    "【发送应用消息失败通知】\n" +
+                            "账号名称:" + staff.getName() + "\n" +
+                            "群名:" + room.getName() + "\n" +
+                            "错误码:" + commonResponse.getErrcode() + "\n" +
+                            "错误信息:" + commonResponse.getErrmsg());
+            log.error("WeComThirdPartyService send text msg failed, request: {}, response: {}", request, response);
+        }
+        return commonResponse;
+    }
+
     @Override
     public List<ThirdPartWeComStaff> getActiveStaffList() {
         ThirdPartWeComStaffExample example = new ThirdPartWeComStaffExample();