2 Commits f56a5e6c6a ... 6f5da4c485

Auteur SHA1 Message Date
  xw 6f5da4c485 Merge remote-tracking branch 'origin/master' il y a 3 jours
  xw ca1f74e1cf 企微群公告和一键群发群公告 il y a 3 jours

+ 70 - 1
fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java

@@ -201,6 +201,18 @@ public class IpadSendServer {
         }
     }
 
+    /**
+     * 发送群公告
+     */
+    public void sendNotice(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
+        WxWorkResponseDTO<WxwSendNoticeMsgRespDTO> resp = ipadSendUtils.sendNotice(vo, content.getValue());
+        if (resp.getErrcode() != 0) {
+            log.debug("ID:{}-ipad接口请求返回异常:{}", vo.getId(), resp.getErrmsg());
+            content.setSendStatus(2);
+            content.setSendRemarks("发送失败:" + resp.getErrmsg());
+        }
+    }
+
     public void sendImg(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
         FileVo imgVo = FileVo.builder().url(content.getImgUrl()).build();
         imgVo.setBase(vo);
@@ -577,10 +589,63 @@ public class IpadSendServer {
         return true;
     }
 
+    /**
+     * 群公告判定消息
+     * @param qwSopLogs
+     * @param setting
+     * @param qwUser
+     * @return
+     */
+    public boolean isSendLogsGroupNotice(QwSopLogs qwSopLogs, QwSopCourseFinishTempSetting setting, QwUser qwUser){
+        // 群公告只能发给群聊
+        if(qwSopLogs.getSendType() != 6 && qwSopLogs.getSendType() != 21){
+            log.warn("群公告SOP_LOG_ID:{}, 不是群聊消息,不发送", qwSopLogs.getId());
+            qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "群公告只能发给群聊,不发送");
+            return false;
+        }
+
+        if(qwSopLogs.getSendStatus() != 3){
+            log.info("群公告状态异常不发送:{}, LOGID: {}", qwUser.getQwUserName(), qwSopLogs.getId());
+            return false;
+        }
+        if(redisCache.getCacheObject("qw:user:id:" + qwUser.getId()) != null){
+            log.info("群公告频率异常不发送:{}", qwUser.getQwUserName());
+            return false;
+        }
+
+        boolean noSop = qwSopLogs.getSendType() != 3 && qwSopLogs.getSendType() != 7 && qwSopLogs.getSendType() != 21;
+
+        if (qwSopLogs.getExpiryTime() == null && noSop) {
+            // 作废消息
+            log.warn("群公告SOP_LOG_ID:{}, SOP任务被删除", qwSopLogs.getId());
+            qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "SOP任务被删除");
+            return false;
+        }
+
+        LocalDateTime sendTime = DateUtil.stringToLocalDateTime(qwSopLogs.getSendTime());
+        LocalDateTime expiryDateTime;
+
+        // 判断是否过期
+        if(qwSopLogs.getSendType() == 3 || qwSopLogs.getSendType() == 7 || qwSopLogs.getSendType() == 21){
+            expiryDateTime = sendTime.plusHours(12);
+        }else{
+            expiryDateTime = sendTime.plusHours(qwSopLogs.getExpiryTime());
+        }
+
+        if (LocalDateTime.now().isAfter(expiryDateTime)) {
+            // 作废消息
+            log.warn("群公告SOP_LOG_ID:{}, 已过期,不发送", qwSopLogs.getId());
+            qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "已过期,不发送");
+            return false;
+        }
+
+        return true;
+    }
+
     public void send(QwSopCourseFinishTempSetting.Setting content, QwUser qwUser, QwSopLogs qwSopLogs, Map<String, FsCoursePlaySourceConfig> miniMap, BaseVo parentVo) {
         BaseVo vo = new BaseVo();
         vo.setId(Long.parseLong(qwSopLogs.getId()));
-        vo.setRoom(qwSopLogs.getSendType() == 6);
+        vo.setRoom(qwSopLogs.getSendType() == 6 || qwSopLogs.getSendType() == 21);
         vo.setUuid(qwUser.getUid());
         vo.setExId(qwSopLogs.getExternalUserId());
         vo.setServerId(qwUser.getServerId());
@@ -589,6 +654,10 @@ public class IpadSendServer {
         vo.setQwUserId(qwUser.getId());
         try {
             content.setSendStatus(1);
+            if(qwSopLogs.getSendType() == 21 && "11".equals(content.getContentType())){
+                sendNotice(vo, content);
+                return;
+            }
             switch (content.getContentType()) {
                 case "1":
                     // 文本

+ 7 - 0
fs-ipad-task/src/main/java/com/fs/app/task/SendMsg.java

@@ -194,12 +194,19 @@ public class SendMsg {
             QwSopCourseFinishTempSetting setting = JSON.parseObject(qwSopLogs.getContentJson(), QwSopCourseFinishTempSetting.class);
             //直播的sendType:20单独走判断 其他的走以前的逻辑
             boolean isSendLive = Integer.valueOf(20).equals(qwSopLogs.getSendType());
+            boolean isSendGroupNotice = Integer.valueOf(21).equals(qwSopLogs.getSendType());
             if(isSendLive){
                 if (!sendServer.isSendLogsLive(qwSopLogs, setting, user)) {
                     log.info("销售:{}, 直播消息发送条件未满足:{}", user.getQwUserName(), qwSopLogs.getId());
                     continue;
                 }
             }
+            else if(isSendGroupNotice){
+                if (!sendServer.isSendLogsGroupNotice(qwSopLogs, setting, user)) {
+                    log.info("销售:{}, 群公告发送条件未满足:{}", user.getQwUserName(), qwSopLogs.getId());
+                    continue;
+                }
+            }
             else{
                 // 判断消息状态是否满足发送条件
                 if (!sendServer.isSendLogs(qwSopLogs, setting, user)) {

+ 31 - 1
fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java

@@ -772,7 +772,14 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             QwGroupChat groupChat = groupChatMap.get(logVo.getChatId());
             if (groupChat.getChatUserList() != null && !groupChat.getChatUserList().isEmpty()) {
                 QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, groupChat.getChatId(), groupChat.getName(), null, isOfficial, null, null);
-                ruleTimeVO.setSendType(6);
+                boolean hasGroupNotice = content.getSetting() != null && content.getSetting().stream()
+                        .anyMatch(st -> "11".equals(st.getContentType()));
+                if(hasGroupNotice){
+                    ruleTimeVO.setSendType(21);
+                    log.info("检测到群公告类型,设置sendType=21, sopId:{}, chatId:{}", logVo.getSopId(), groupChat.getChatId());
+                } else {
+                    ruleTimeVO.setSendType(6);
+                }
                 ruleTimeVO.setType(2);
                 handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
                         type, qwUserId, companyUserId, companyId, groupChat.getChatId(), welcomeText, qwUserName,
@@ -945,12 +952,35 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             //直播间发送类型
             case 20:
                 handleLiveMessage(sopLogs, content, companyUserId, companyId, isGroupChat, qwUserId, groupChat, externalId, logVo, liveId);
+                break;
+            case 21:
+                handleGroupNoticeMessage(sopLogs, content, isGroupChat);
+                break;
             default:
                 log.error("未知的消息类型 {},跳过处理。", type);
                 break;
         }
     }
 
+    /**
+     * 处理群公告消息
+     * @param sopLogs 日志对象
+     * @param content 内容对象
+     * @param isGroupChat 是否为群聊
+     */
+    private void handleGroupNoticeMessage(QwSopLogs sopLogs, QwSopTempSetting.Content content, boolean isGroupChat) {
+        // 群公告只能发给群聊
+        if (!isGroupChat) {
+            log.warn("群公告只能发给群聊,跳过处理");
+            return;
+        }
+
+        // 设置发送类型为21(群公告)
+        sopLogs.setSendType(21);
+        sopLogs.setContentJson(JSON.toJSONString(content));
+        enqueueQwSopLogs(sopLogs);
+    }
+
     private void handleVoiceMessage(QwSopLogs sopLogs, QwSopTempSetting.Content content, String companyUserId) {
         sopLogs.setContentJson(JSON.toJSONString(content));
         enqueueQwSopLogs(sopLogs);

+ 11 - 0
fs-service/src/main/java/com/fs/ipad/IpadSendUtils.java

@@ -212,6 +212,17 @@ public class IpadSendUtils {
         return wxWorkService.SendAppMsg(dto, vo.getServerId());
     }
 
+    /**
+     * 发送群公告
+     */
+    public WxWorkResponseDTO<WxwSendNoticeMsgRespDTO> sendNotice(BaseVo vo, String content){
+        WxwSendNoticeMsgDTO dto = new WxwSendNoticeMsgDTO();
+        dto.setUuid(vo.getUuid());
+        dto.setRoomid(chatIds(vo));
+        dto.setMsg(content);
+        return wxWorkService.SendNotice(dto, vo.getServerId());
+    }
+
 
 
 

+ 19 - 0
fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java

@@ -803,6 +803,10 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
                                 createVoiceUrl(st, companyUserId, qwSop);
                                 sopLogs.setAppSendStatus(0);
                                 break;
+                            //群公告
+                            case "11":
+                                sopLogs.setSendType(21); // 设置为群公告类型
+                                break;
                             default:
                                 break;
                         }
@@ -851,6 +855,13 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
 
                     List<QwSopCourseFinishTempSetting.Setting> list = JSONArray.parseArray(param.getSetting(), QwSopCourseFinishTempSetting.Setting.class);
 
+                    // 检查是否有群公告类型,如果有则设置sendType=21
+                    boolean hasGroupNotice = list.stream().anyMatch(st -> "11".equals(st.getContentType()));
+                    if(hasGroupNotice){
+                        sopLogs.setSendType(21);
+                        log.info("检测到群公告类型,设置sendType=21, sopId:{}, chatId:{}", param.getSopId(), groupChat.getChatId());
+                    }
+
                     for (QwSopCourseFinishTempSetting.Setting st : list) {
 
                         //过滤违禁词
@@ -1057,6 +1068,10 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
                                 }
                                 sopLogs.setAppSendStatus(0);
                                 break;
+                            //群公告
+                            case "11":
+                                sopLogs.setSendType(21); // 设置为群公告类型
+                                break;
                         }
                     }
                     setting.setSetting(list);
@@ -1440,6 +1455,10 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
                             }
                             sopLogs.setAppSendStatus(0);
                             break;
+                        //群公告(仅用于一键群发,个人不应该有群公告)
+                        case "11":
+                            log.warn("群公告不能发给个人,跳过处理,sopId:{}, externalId:{}", param.getSopId(), item.getExternalId());
+                            break;
                         default:
                             break;
 

+ 22 - 0
fs-service/src/main/java/com/fs/wxwork/dto/WxwSendNoticeMsgDTO.java

@@ -0,0 +1,22 @@
+package com.fs.wxwork.dto;
+
+import lombok.Data;
+
+/**
+ * 发送群公告请求DTO
+ */
+@Data
+public class WxwSendNoticeMsgDTO {
+    /**
+     * 消息的唯一标识符 (UUID)
+     */
+    private String uuid;
+    /**
+     * 群聊room_id
+     */
+    private Long roomid;
+    /**
+     * 群公告内容
+     */
+    private String msg;
+}

+ 22 - 0
fs-service/src/main/java/com/fs/wxwork/dto/WxwSendNoticeMsgRespDTO.java

@@ -0,0 +1,22 @@
+package com.fs.wxwork.dto;
+
+import lombok.Data;
+
+/**
+ * 发送群公告响应DTO
+ */
+@Data
+public class WxwSendNoticeMsgRespDTO {
+    /**
+     * 数据(通常为null)
+     */
+    private Object data;
+    /**
+     * 错误码
+     */
+    private Integer errcode;
+    /**
+     * 错误信息
+     */
+    private String errmsg;
+}

+ 6 - 2
fs-service/src/main/java/com/fs/wxwork/service/WxWorkServiceNew.java

@@ -45,6 +45,10 @@ public class WxWorkServiceNew {
         redisCache.setCacheObject("serverId:" + serverId,qwIpadServer.getUrl(),2, TimeUnit.HOURS);
         return qwIpadServer.getUrl();
     }
+    public WxWorkResponseDTO<WxwSendNoticeMsgRespDTO> SendNotice(WxwSendNoticeMsgDTO param,Long serverId) {
+        String url = getUrl(serverId) + "/SendNotice";
+        return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxwSendNoticeMsgRespDTO>>() {}, serverId);
+    }
 
     public WxWorkResponseDTO<WxWorkInitRespDTO> init(WxWorkInitDTO param,Long serverId) {
         String url = getUrl(serverId) + "/init";
@@ -233,8 +237,8 @@ public class WxWorkServiceNew {
         String url = getUrl(serverId) + "/RoomIdToChatId";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxWorkChatIdToRoomIdResp>>() {}, serverId);
     }
-    
-    
+
+
     public WxWorkResponseDTO<WxSendTextAtMsgVo> sendTextAtMsgTwo(WxSendTextAtMsgTwoDTO param, Long serverId) {
         String url = getUrl(serverId) + "/SendTextAtMsgTwo";
         return WxWorkHttpUtil.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxSendTextAtMsgVo>>() {});