소스 검색

直播代码提交 自动建群功能

yuhongqi 1 주 전
부모
커밋
eaa1404bb9
26개의 변경된 파일443개의 추가작업 그리고 4개의 파일을 삭제
  1. 9 0
      fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java
  2. 99 3
      fs-qw-task/src/main/java/com/fs/app/task/qwTask.java
  3. 161 0
      fs-service/src/main/java/com/fs/ipad/IpadSendUtils.java
  4. 3 0
      fs-service/src/main/java/com/fs/ipad/vo/BaseVo.java
  5. 3 0
      fs-service/src/main/java/com/fs/qw/domain/QwExternalContact.java
  6. 7 0
      fs-service/src/main/java/com/fs/qw/domain/QwGroupChat.java
  7. 2 0
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java
  8. 2 0
      fs-service/src/main/java/com/fs/qw/mapper/QwGroupChatMapper.java
  9. 9 0
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  10. 2 0
      fs-service/src/main/java/com/fs/qw/service/IQwExternalContactService.java
  11. 2 0
      fs-service/src/main/java/com/fs/qw/service/IQwGroupChatService.java
  12. 2 0
      fs-service/src/main/java/com/fs/qw/service/IQwUserService.java
  13. 6 1
      fs-service/src/main/java/com/fs/qw/service/impl/AsyncChatSopService.java
  14. 14 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java
  15. 5 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwGroupChatServiceImpl.java
  16. 4 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java
  17. 10 0
      fs-service/src/main/java/com/fs/sop/domain/QwSop.java
  18. 7 0
      fs-service/src/main/java/com/fs/sop/mapper/QwSopMapper.java
  19. 3 0
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopServiceImpl.java
  20. 17 0
      fs-service/src/main/java/com/fs/wxwork/dto/WxCreateRoomMsgDTO.java
  21. 11 0
      fs-service/src/main/java/com/fs/wxwork/dto/WxCreateRoomRespDTO.java
  22. 1 0
      fs-service/src/main/java/com/fs/wxwork/dto/WxWorkChatIdToRoomIdDTO.java
  23. 11 0
      fs-service/src/main/java/com/fs/wxwork/service/WxWorkServiceNew.java
  24. 4 0
      fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml
  25. 14 0
      fs-service/src/main/resources/mapper/qw/QwGroupChatMapper.xml
  26. 35 0
      fs-service/src/main/resources/mapper/sop/QwSopMapper.xml

+ 9 - 0
fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java

@@ -40,6 +40,7 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
+import com.fs.app.task.qwTask;
 
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -77,6 +78,8 @@ public class CommonController {
 
     @Autowired
     private IQwSopLogsService qwSopLogsService;
+    @Autowired
+    private qwTask qwTask1;
 
     @Autowired
     private QwSopMapper qwSopMapper;
@@ -382,4 +385,10 @@ public class CommonController {
         return R.ok();
     }
 
+    @GetMapping("/autoPullGroup")
+    public R autoPullGroup(){
+        qwTask1.autoPullGroup();
+        return R.ok();
+    }
+
 }

+ 99 - 3
fs-qw-task/src/main/java/com/fs/app/task/qwTask.java

@@ -1,10 +1,15 @@
 package com.fs.app.task;
 
 import com.fs.app.taskService.*;
-import com.fs.qw.service.IQwExternalErrRetryService;
-import com.fs.qw.service.IQwGroupMsgService;
-import com.fs.qw.service.IQwWorkUserService;
+import com.fs.common.utils.PubFun;
+import com.fs.ipad.IpadSendUtils;
+import com.fs.qw.domain.QwExternalContact;
+import com.fs.qw.domain.QwGroupChat;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.service.*;
+import com.fs.sop.domain.QwSop;
 import com.fs.sop.mapper.QwSopLogsMapper;
+import com.fs.sop.mapper.QwSopMapper;
 import com.fs.sop.service.IQwSopLogsService;
 import com.fs.sop.service.IQwSopTagService;
 import com.fs.sop.service.ISopUserLogsService;
@@ -20,7 +25,15 @@ import org.springframework.stereotype.Component;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static com.fs.qw.service.impl.AsyncChatSopService.MAX_GROUP_USER_NUM;
+import static com.fs.qw.service.impl.AsyncChatSopService.MAX_GROUP_NUM;
 
 /**
  * 企业微信SOP定时任务管理类
@@ -33,6 +46,20 @@ import java.util.List;
 @Slf4j
 public class qwTask {
 
+    @Autowired
+    private QwSopMapper qwSopMapper;
+
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
+    @Autowired
+    private IQwUserService qwUserService;
+    @Autowired
+    private IQwGroupChatService qwGroupChatService;
+
+    @Autowired
+    private IpadSendUtils ipadSendUtils;
+
     @Autowired
     private QwSopServiceImpl qwSopService;
 
@@ -385,4 +412,73 @@ public class qwTask {
         syncQwExternalContactService.syncQwExternalContactUnionid();
 
     }
+
+    /**
+     * 定时拉人进群
+     */
+    @Scheduled(cron = "0 0 16 * * ?")
+    public void autoPullGroup(){
+        //  拉群 ,①保持群号 ②每日拉群 ③创建建群记录
+        // 计算每个人最大拉人数量
+        long maxNum = (long) MAX_GROUP_NUM * MAX_GROUP_USER_NUM;
+        // 获取当前时间
+        LocalDate now = LocalDate.now();
+        // 获取需要自动拉群的SOP任务
+        List<QwSop> list = qwSopMapper.selectGroup(now);
+        if(list == null || list.isEmpty()) return;
+        list.forEach(sop -> {
+            // 获取这个SOP下面的企微ID
+            List<Long> qwUserIdList = Arrays.stream(sop.getQwUserIds().split(",")).map(Long::parseLong).distinct().collect(Collectors.toList());
+            // 获取企微ID下面的所有用户
+            List<QwExternalContact> qwExternalContactList = qwExternalContactService.selectQwUserAndLevel(qwUserIdList, Arrays.asList(sop.getAutoGroupLevel().split(",")), sop.getAutoUserReg() == 1);
+            // 根据企微ID进行分组
+            Map<Long, List<QwExternalContact>> qwUserMap = PubFun.listToMapByGroupList(qwExternalContactList, QwExternalContact::getQwUserId);
+            // 获取企微列表
+            List<QwUser> qwUserList = qwUserService.selectQwUserByIds(qwUserIdList);
+            try {
+                // 每个企微都拉人
+                qwUserList.stream().filter(qwUser -> qwUserMap.containsKey(qwUser.getId())).forEach(qwUser -> {
+                    List<QwExternalContact> userList = qwUserMap.get(qwUser.getId()).stream().limit(maxNum).collect(Collectors.toList());
+                    // 创建群 如果没人或者人数没达到满群的要求,不进行建群
+                    if(userList.isEmpty() || userList.size() < MAX_GROUP_USER_NUM) return;
+                    List<QwGroupChat> chatList = qwGroupChatService.selectSopAndQwUser(qwUser.getQwUserId(), sop.getId());
+                    int groupNum = 0;
+                    if (chatList != null && !chatList.isEmpty()) {
+                        groupNum = extractLastNumber(chatList.get(0).getName())  == null ? 0 : extractLastNumber(chatList.get(0).getName());
+                    }
+                    try {
+                        // 建群
+                        ipadSendUtils.createRoom(sop, sop.getGroupName(), qwUser, userList, MAX_GROUP_NUM, MAX_GROUP_USER_NUM,groupNum);
+                    }catch (Exception e){
+                        log.error("群聊拉人进群错误:{},企微ID:{},企微名称:{},外部联系人:{}", e.getMessage(), qwUser.getId(), qwUser.getQwUserName(), PubFun.listToNewList(userList, QwExternalContact::getId));
+                        log.error("群聊拉人进群错误", e);
+                    }
+                });
+            }catch (Exception e){
+                log.error("SOP拉人进群错误", e);
+            }
+        });
+    }
+    /**
+     * 提取字符串中最后的数字
+     * @param str 待处理的字符串
+     * @return 提取到的数字,若没有数字则返回null
+     */
+    public static Integer extractLastNumber(String str) {
+        if (str == null || str.isEmpty()) {
+            return null;
+        }
+
+        // 正则表达式:匹配字符串末尾的一个或多个数字
+        Pattern pattern = Pattern.compile("\\d+$");
+        Matcher matcher = pattern.matcher(str);
+
+        if (matcher.find()) {
+            String numberStr = matcher.group();
+            return Integer.parseInt(numberStr);
+        }
+
+        // 没有找到数字
+        return null;
+    }
 }

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

@@ -2,28 +2,45 @@ package com.fs.ipad;
 
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.core.redis.RedisCacheT;
 import com.fs.common.exception.base.BaseException;
+import com.fs.common.utils.PubFun;
 import com.fs.common.utils.StringUtils;
 import com.fs.ipad.param.WxGetSessionRoomListParam;
 import com.fs.ipad.param.WxRoomUserListParam;
 import com.fs.ipad.param.WxSendAtMsgParam;
 import com.fs.ipad.vo.*;
+import com.fs.qw.domain.QwExternalContact;
+import com.fs.qw.domain.QwGroupChat;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.mapper.QwExternalContactMapper;
+import com.fs.qw.mapper.QwGroupChatMapper;
+import com.fs.sop.domain.QwSop;
+import com.fs.sop.domain.SopUserLogs;
+import com.fs.sop.mapper.QwSopMapper;
+import com.fs.sop.mapper.SopUserLogsMapper;
 import com.fs.wxwork.dto.*;
 import com.fs.wxwork.service.WxWorkServiceNew;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 
 @Slf4j
 @Component
@@ -32,6 +49,10 @@ public class IpadSendUtils {
 
     private final WxWorkServiceNew wxWorkService;
     private final RedisCacheT<String> redisCache;
+    private final QwGroupChatMapper qwGroupChatMapper;
+    private final QwSopMapper qwSopMapper;
+    private final QwExternalContactMapper qwExternalContactMapper;
+    private final SopUserLogsMapper sopUserLogsMapper;
     private final RedisCache redisCacheUrl;
     private final String FILE_KEY = "ipad:upload:";
 
@@ -379,4 +400,144 @@ public class IpadSendUtils {
         log.info("发送返回数据:{}", result);
         if(result.getErrcode() != 0) throw new BaseException("发送消息错误:" + result.getErrmsg());
     }
+
+    /**
+     * 创建群聊
+     * @param qwSop           SOP
+     * @param groupName       群聊名称
+     * @param qwUser          创建企微账号
+     * @param list            客户列表
+     * @param maxGroupNum     最大拉群数量
+     * @param maxGroupUserNum 单个群聊最大拉取用户数量
+     */
+    public String createRoom(QwSop qwSop, String groupName, QwUser qwUser, List<QwExternalContact> list, Integer maxGroupNum, Integer maxGroupUserNum, int currentNum) {
+        // 最大支持的客户数量
+        int maxNum = maxGroupNum * maxGroupUserNum;
+        // 根据最大客户数量限制客户
+        List<QwExternalContact> joinList = list.stream().limit(maxNum).collect(Collectors.toList());
+        // 修改加群状态微 已加群
+        joinList.forEach(e -> e.setJoinGroup(1));
+        // 用外部联系人ID去换取企微对应的ID
+        List<Long> userIds = changeUserIds(qwUser, joinList);
+        // 添加的群ID
+        List<String> chatIds = new ArrayList<>();
+        // 筛选出来的客户可以创建多少个群聊
+        int groupNum = BigDecimal.valueOf((double) userIds.size() / maxGroupUserNum).setScale(0, RoundingMode.UP).intValue();
+        List<SopUserLogs> logsList = new ArrayList<>();
+        // 获取当前日期
+        Date currentDate = new Date();
+        // 创建格式化器,指定格式为"yyyy年MM月dd日"
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        // 格式化日期
+        String today = sdf.format(currentDate);
+        // 循环创建群聊添加客户
+        for (int i = 0; i < groupNum; i++) {
+            List<Long> collect = userIds.stream().skip((long) i * maxGroupUserNum).limit(maxGroupUserNum).collect(Collectors.toList());
+            // 如果人数为空 或者 人数不足最大群聊人数
+            if(collect.isEmpty() || collect.size() < maxGroupUserNum) continue;
+            // 设置新的群聊名称
+            String newGroupName = groupName + (i + 1 + currentNum);
+            // 创建群聊对象
+            WxCreateRoomMsgDTO dto = new WxCreateRoomMsgDTO();
+            // 设置UUID
+            dto.setUuid(qwUser.getUid());
+            // 设置群聊名称
+            dto.setRoomName(newGroupName);
+            // 客户ID列表,会自动拉取到群聊里面
+            dto.setVids(collect);
+            // 请求创建群聊方法
+            WxWorkResponseDTO<WxCreateRoomRespDTO> room = wxWorkService.createRoom(dto, qwUser.getServerId());
+            // 通过创建群聊接口返回的ID换取系统需要的群聊ID
+            String chatId = toChatIds(qwUser.getUid(), room.getData().getRoomid(), qwUser.getServerId());
+            // 群聊对象
+            QwGroupChat qwGroupChat = new QwGroupChat();
+            // 群聊ID
+            qwGroupChat.setChatId(chatId);
+            // 群聊名称
+            qwGroupChat.setName(newGroupName);
+            // 对应的SOPID
+            qwGroupChat.setSopId(qwSop.getId());
+            // 所属的企微ID
+            qwGroupChat.setQwUserId(qwUser.getId());
+            // 微信对应的群聊ID
+            qwGroupChat.setRoomid(room.getData().getRoomid());
+            // 创建活修改群聊
+            qwGroupChatMapper.insertOrUpdateQwGroupChat(qwGroupChat);
+            // 群聊ID添加
+            chatIds.add(chatId);
+            SopUserLogs sopUserLogs = new SopUserLogs();
+            sopUserLogs.setSopId(qwSop.getId());
+            sopUserLogs.setSopTempId(qwSop.getTempId());
+            sopUserLogs.setQwUserId(qwUser.getQwUserId());
+            sopUserLogs.setCorpId(qwSop.getCorpId());
+            sopUserLogs.setStartTime(today);
+            sopUserLogs.setStatus(1);
+            sopUserLogs.setUserId(qwUser.getId() + "|" + qwUser.getCompanyUserId() + "|" + qwUser.getCompanyId());
+            sopUserLogs.setChatId(chatId);
+            logsList.add(sopUserLogs);
+        }
+        // 更新客户信息
+        qwExternalContactMapper.updateJoinGroup(PubFun.listToNewList(joinList, QwExternalContact::getId));
+        // 组装群聊ID
+        String chatId = String.join(",", chatIds);
+        // 修改SOP对象
+        qwSopMapper.updateSopGroupIds(qwSop.getId(), chatId);
+        sopUserLogsMapper.batchInsertSopUserLogs(logsList);
+        return chatId;
+    }
+    private String toChatIds(String uuid, Long roomid, Long serverId) {
+        WxWorkChatIdToRoomIdDTO tdo = new WxWorkChatIdToRoomIdDTO();
+        tdo.setRoom_id(roomid);
+        tdo.setUuid(uuid);
+        WxWorkResponseDTO<WxWorkChatIdToRoomIdResp> result = wxWorkService.RoomIdToChatId(tdo, serverId);
+        if(result.getErrcode() != 0){
+            throw new BaseException(result.getErrmsg());
+        }
+        WxWorkChatIdToRoomIdResp data = result.getData();
+        if(data == null || data.getRoom_id() == null) {
+            log.error("未找到群聊数据,请求数据:{},返回数据:{}", JSON.toJSONString(tdo), JSON.toJSONString(result));
+            throw new BaseException("未找到群聊:" + roomid);
+        }
+        return data.getChatid();
+    }
+
+    private List<Long> changeUserIds(QwUser qwUser, List<QwExternalContact> joinList) {
+        BaseVo vo = new BaseVo();
+        vo.setId(qwUser.getId());
+        vo.setRoom(false);
+        vo.setUuid(qwUser.getUid());
+        vo.setExIdList(joinList.stream().map(QwExternalContact::getExternalUserId).collect(Collectors.toList()));
+        vo.setServerId(qwUser.getServerId());
+        return userIdList(vo);
+    }
+    private List<Long> userIdList(BaseVo vo){
+        if(vo.isRoom()){
+            return Collections.emptyList();
+        }
+        WxWorkUserId2VidDTO wxWorkUserId2VidDTO = new WxWorkUserId2VidDTO();
+        wxWorkUserId2VidDTO.setOpenid(vo.getExIdList());
+        wxWorkUserId2VidDTO.setCorpid(vo.getCorpId());
+        wxWorkUserId2VidDTO.setScorpid(vo.getCorpCode());
+        wxWorkUserId2VidDTO.setUuid(vo.getUuid());
+        WxWorkResponseDTO<List<WxWorkVid2UserIdRespDTO>> resutl = wxWorkService.UserId2Vid(wxWorkUserId2VidDTO, vo.getServerId());
+        List<?> rawData = resutl.getData(); // 先用一个泛型不确定的列表接收
+        if(rawData.isEmpty()) {
+            log.error("未找到用户数据,基础数据:{},请求数据:{},返回数据:{}", vo, JSON.toJSONString(wxWorkUserId2VidDTO), JSON.toJSONString(resutl));
+            throw new BaseException("未找到用户:" + vo.getId());
+        }
+        List<WxWorkVid2UserIdRespDTO> data = new ArrayList<>();
+        for (Object item : rawData) {
+            if (item instanceof WxWorkVid2UserIdRespDTO) {
+                data.add((WxWorkVid2UserIdRespDTO) item);
+            } else if (item instanceof JSONObject) {
+                // 如果是JSONObject,则需要将其转换为目标类型
+                WxWorkVid2UserIdRespDTO dto = ((JSONObject) item).toJavaObject(WxWorkVid2UserIdRespDTO.class);
+                data.add(dto);
+            } else {
+                log.warn("未知类型: {}", item.getClass());
+                // 根据实际情况处理,例如跳过或抛出更明确的异常
+            }
+        }
+        return data.stream().map(WxWorkVid2UserIdRespDTO::getUser_id).collect(Collectors.toList());
+    }
 }

+ 3 - 0
fs-service/src/main/java/com/fs/ipad/vo/BaseVo.java

@@ -2,12 +2,15 @@ package com.fs.ipad.vo;
 
 import lombok.Data;
 
+import java.util.List;
+
 @Data
 public class BaseVo{
 
     private Long id;
     private String uuid;
     private Long serverId;
+    private List<String> exIdList;
     private String exId;
     private String corpId;
     private String corpCode;

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

@@ -148,4 +148,7 @@ public class QwExternalContact extends BaseEntity
     //用户是否回复  0未回复  1已回复
     private Integer isReply;
 
+    // 是否被邀请进群0否1是
+    private Integer joinGroup;
+
 }

+ 7 - 0
fs-service/src/main/java/com/fs/qw/domain/QwGroupChat.java

@@ -75,4 +75,11 @@ public class QwGroupChat extends BaseEntity
     private Long allOutGroup;
     @TableField(exist = false)
     private List<QwGroupChatUser> chatUserList;
+
+
+    // 是否自动拉人0否1是
+    private Long autoAdduser;
+    private String sopId;
+    private Long qwUserId;
+    private Long roomid;
 }

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

@@ -534,4 +534,6 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
      * 根据qw_user_id+crop_id+external_user_id查询外部联系人信息
      * */
     QwExternalContact selectQwUserListVOByQwUserIdAndCorpIdAndExternalUserId(ExternalContactParam externalContactParam);
+
+    void updateJoinGroup(List<Long> longs);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwGroupChatMapper.java

@@ -128,4 +128,6 @@ public interface QwGroupChatMapper
      * @return  list
      */
     List<QwGroupChatTransferVO> selectQwGroupChatTransferList(QwGroupChatParam qwGroupChat);
+
+    List<QwGroupChat> selectSopAndQwUser(@Param("qwUserId") String qwUserId, @Param("sopId") String sopId);
 }

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

@@ -455,4 +455,13 @@ public interface QwUserMapper extends BaseMapper<QwUser>
 
     @Select("  select company_id from qw_user where qw_user_id = #{owner} and corp_id = #{corpId}  limit 1")
     Long getCompanyIdByCorpIdAndOwner(@Param("corpId")String corpId, @Param("owner")String owner);
+
+    @Select("<script>" +
+            "select * from qw_user where qw_user_id in " +
+            "<foreach collection='qwUserIdList' item='item' open='(' separator=',' close=')'> " +
+            "#{item} " +
+            "</foreach> " +
+            "</script>")
+    List<QwUser> selectQwUserByIds(@Param("qwUserIdList") List<Long> qwUserIdList);
+
 }

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

@@ -257,4 +257,6 @@ public interface IQwExternalContactService extends IService<QwExternalContact> {
      * 根据qw_user_id+crop_id+external_user_id查询外部联系人信息
      * */
     QwExternalContact selectQwUserListVOByQwUserIdAndCorpIdAndExternalUserId(ExternalContactParam externalContactParam);
+
+    List<QwExternalContact> selectQwUserAndLevel(List<Long> qwUserIdList, List<String> levelList, boolean isReg);
 }

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

@@ -86,4 +86,6 @@ public interface IQwGroupChatService
      * @return message
      */
     ResultMessage processTransfer(TransferChatParam param, CompanyUser user, boolean isResigned);
+
+    List<QwGroupChat> selectSopAndQwUser(String qwUserId, String id);
 }

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

@@ -200,4 +200,6 @@ public interface IQwUserService
     List<QwOptionsVO> selectQwCompanyListOptionsVOBySys();
 
     List<Long> selectDeptByParentId(Long deptId,String cropId);
+
+    List<QwUser> selectQwUserByIds(List<Long> qwUserIdList);
 }

+ 6 - 1
fs-service/src/main/java/com/fs/qw/service/impl/AsyncChatSopService.java

@@ -29,6 +29,11 @@ import java.util.stream.Collectors;
 @AllArgsConstructor
 public class AsyncChatSopService {
 
+    // 每个人一次性最大创建群聊次数
+    public final static Integer MAX_GROUP_NUM = 3;
+    // 一个群一天最大拉群人数量
+    public final static Integer MAX_GROUP_USER_NUM = 40;
+
     private final QwSopMapper qwSopMapper;
     private final QwSopTempMapper qwSopTempMapper;
     private final SopUserLogsMapper sopUserLogsMapper;
@@ -49,7 +54,7 @@ public class AsyncChatSopService {
             Map<String, QwUserVO> qwUserMap = PubFun.listToMapByGroupObject(qwUserVOList, QwUserVO::getQwUserId);
             List<QwGroupChat> qwGroupChatList = qwGroupChatService.selectQwGroupChatByChatIds(ruleTimeVOList.stream().flatMap(e -> Arrays.stream(e.getChatId().split(","))).toArray(String[]::new));
             Map<String, QwGroupChat> groupChatMap = PubFun.listToMapByGroupObject(qwGroupChatList, QwGroupChat::getChatId);
-            ruleTimeVOList.forEach(ruleTimeVO -> {
+            ruleTimeVOList.stream().filter(e -> StringUtils.isNotEmpty(e.getChatId())).forEach(ruleTimeVO -> {
                 QwSopTemp qwSopTemp = tempMap.get(ruleTimeVO.getTempId());
                 if (!qwSopTemp.getStatus().equals("0")) {
                     processInternal(ruleTimeVO, qwSopTemp, qwUserMap, groupChatMap);

+ 14 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -5918,6 +5918,20 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
         qwExternalContactMapper.updateQwExternalContactStatusById(qwExternalContact);
     }
 
+    @Override
+    public List<QwExternalContact> selectQwUserAndLevel(List<Long> qwUserIdList, List<String> levelList, boolean isReg) {
+        QueryWrapper<QwExternalContact> queryCondition = new QueryWrapper<QwExternalContact>().isNotNull(isReg, "fs_user_id").eq("status", 0).eq("join_group", 0)
+                        .in("qw_user_id", qwUserIdList).and(qw->{
+                        qw.in("level", levelList);
+                        if(levelList.contains("-1")) {
+                                qw.or().isNull("level");
+                            }
+                        return qw;
+                    });
+
+        return list(queryCondition);
+    }
+
     @Override
     public R getRepeat(RepeatParam param) {
         List<QwExternalContact> list = qwExternalContactMapper.selectList(new QueryWrapper<QwExternalContact>().eq("external_user_id", param.getExternalUserId()));

+ 5 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwGroupChatServiceImpl.java

@@ -564,4 +564,9 @@ public class QwGroupChatServiceImpl implements IQwGroupChatService
         return transferLog;
     }
 
+    @Override
+    public List<QwGroupChat> selectSopAndQwUser(String qwUserId, String sopId) {
+        return qwGroupChatMapper.selectSopAndQwUser(qwUserId, sopId);
+    }
+
 }

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

@@ -1546,6 +1546,10 @@ public class QwUserServiceImpl implements IQwUserService
         qwUserMapper.updateById(qwUser);
     }
 
+    @Override
+    public List<QwUser> selectQwUserByIds(List<Long> qwUserIdList) {
+        return qwUserMapper.selectQwUserByIds(qwUserIdList);
+    }
     /**
      * 根据销售公司和企微ID查询企微用户
      */

+ 10 - 0
fs-service/src/main/java/com/fs/sop/domain/QwSop.java

@@ -138,10 +138,20 @@ public class QwSop implements Serializable
     private List<Long> qwUserIdList;
 
     @Excel(name = "开启评论或者弹幕,1-开启评论;2-开启弹幕;3-都关闭")
+    @TableField(exist = false)
     private Integer openCommentStatus;
 
     /**
      * 是否按照营期 发送官方群发 1是 2否(否的时候按单链发)
      */
     private Integer isSampSend;
+    private Integer isLiveMgs;
+    private Long liveTempId;
+    private String liveTempSendTime;
+    private Integer autoGroup;
+    private String autoGroupLevel;
+    private String groupName;
+    private Integer autoUserReg;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private String pullTime;
 }

+ 7 - 0
fs-service/src/main/java/com/fs/sop/mapper/QwSopMapper.java

@@ -22,6 +22,7 @@ import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.springframework.stereotype.Repository;
 
+import java.time.LocalDate;
 import java.util.List;
 import java.util.Set;
 
@@ -427,4 +428,10 @@ public interface QwSopMapper extends BaseMapper<QwSop> {
 
     @DataSource(DataSourceType.SOP)
     List<QwSop> selectAllQwSopInfo(QwSop qwSop);
+
+    @DataSource(DataSourceType.SOP)
+    List<QwSop> selectGroup(@Param("now")LocalDate now);
+
+    @DataSource(DataSourceType.SOP)
+    void updateSopGroupIds(@Param("id") String id, @Param("chatId") String chatId);
 }

+ 3 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopServiceImpl.java

@@ -198,6 +198,9 @@ public class QwSopServiceImpl implements IQwSopService
         qwSop.setCreateTime(sdf.format(new Date()));
         QwSopTemp qwSopTemp = qwSopTempMapper.selectById(qwSop.getTempId());
         qwSop.setProject(qwSopTemp.getProject());
+        if(qwSop.getAutoGroup() == 1){
+            qwSop.setPullTime(qwSop.getStartTime());
+        }
         return qwSopMapper.insert(qwSop);
     }
 

+ 17 - 0
fs-service/src/main/java/com/fs/wxwork/dto/WxCreateRoomMsgDTO.java

@@ -0,0 +1,17 @@
+package com.fs.wxwork.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class WxCreateRoomMsgDTO {
+    /**
+     * 消息的唯一标识符 (UUID)
+     */
+    private String uuid;
+    private String roomName;
+    private Long roomid;
+    private List<Long> vids;
+
+}

+ 11 - 0
fs-service/src/main/java/com/fs/wxwork/dto/WxCreateRoomRespDTO.java

@@ -0,0 +1,11 @@
+package com.fs.wxwork.dto;
+
+import lombok.Data;
+
+@Data
+public class WxCreateRoomRespDTO {
+    private String roomname;
+    private Long createTime;
+    private Long createid;
+    private Long roomid;
+}

+ 1 - 0
fs-service/src/main/java/com/fs/wxwork/dto/WxWorkChatIdToRoomIdDTO.java

@@ -7,4 +7,5 @@ public class WxWorkChatIdToRoomIdDTO {
     private String uuid;
     private String corpid;
     private String chatid;
+    private Long room_id;
 }

+ 11 - 0
fs-service/src/main/java/com/fs/wxwork/service/WxWorkServiceNew.java

@@ -221,4 +221,15 @@ public class WxWorkServiceNew {
         String url = getUrl(serverId) + "/SendTextAtMsg";
         return WxWorkHttpUtil.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxSendAtMsgVo>>() {});
     }
+
+    public WxWorkResponseDTO<WxCreateRoomRespDTO> createRoom(WxCreateRoomMsgDTO param, Long serverId) {
+        String url = getUrl(serverId) + "/CreateRoomWx";
+        return WxWorkHttpUtil.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxCreateRoomRespDTO>>() {});
+    }
+
+
+    public WxWorkResponseDTO<WxWorkChatIdToRoomIdResp> RoomIdToChatId(WxWorkChatIdToRoomIdDTO param, Long serverId) {
+        String url = getUrl(serverId) + "/RoomIdToChatId";
+        return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxWorkChatIdToRoomIdResp>>() {}, serverId);
+    }
 }

+ 4 - 0
fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml

@@ -786,4 +786,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectQwExternalContactVo"/>
         where user_id = #{userId} and corp_id = #{corpId} and external_user_id = #{externalUserId}
     </select>
+
+    <update id="updateJoinGroup">
+        update qw_external_contact set join_group = 1 where id in <foreach collection="ids" open="(" separator="," close=")" item="item">#{item}</foreach>
+    </update>
 </mapper>

+ 14 - 0
fs-service/src/main/resources/mapper/qw/QwGroupChatMapper.xml

@@ -102,6 +102,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="todayJoin != null">today_join,</if>
             <if test="todayOut != null">today_out,</if>
             <if test="allOutGroup != null">all_out_group,</if>
+            <if test="sopId != null">sop_id,</if>
+            <if test="qwUserId != null">qw_user_id,</if>
+            <if test="roomid != null">roomid,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="chatId != null">#{chatId},</if>
@@ -119,6 +122,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="todayJoin != null">#{todayJoin},</if>
             <if test="todayOut != null">#{todayOut},</if>
             <if test="allOutGroup != null">#{allOutGroup},</if>
+            <if test="sopId != null">#{sopId},</if>
+            <if test="qwUserId != null">#{qwUserId},</if>
+            <if test="roomid != null">#{roomid},</if>
         </trim>
         on duplicate key update
         <trim suffixOverrides=",">
@@ -136,6 +142,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="todayJoin != null">today_join = #{todayJoin},</if>
             <if test="todayOut != null">today_out = #{todayOut},</if>
             <if test="allOutGroup != null">all_out_group = #{allOutGroup},</if>
+            <if test="sopId != null">sop_id = #{sopId},</if>
+            <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
+            <if test="roomid != null">roomid = #{roomid},</if>
         </trim>
     </insert>
 
@@ -208,4 +217,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{chatId}
         </foreach>
     </delete>
+
+    <select id="selectSopAndQwUser" resultType="com.fs.qw.domain.QwGroupChat">
+       select * from qw_group_chat where owner = #{qwUserId} and sop_id = #{sopId}
+            order by create_time desc limit 1
+    </select>
 </mapper>

+ 35 - 0
fs-service/src/main/resources/mapper/sop/QwSopMapper.xml

@@ -35,6 +35,12 @@
         <result property="chatId"    column="chat_id"    />
         <result property="openCommentStatus"    column="open_comment_status"    />
         <result property="isSampSend"    column="is_samp_send"    />
+        <result property="isLiveMgs"    column="is_live_mgs"    />
+        <result property="liveTempId"    column="live_temp_id"    />
+        <result property="liveTempSendTime"    column="live_temp_send_time"    />
+        <result property="autoGroup"    column="auto_group"    />
+        <result property="autoGroupLevel"    column="auto_group_level"    />
+        <result property="groupName"    column="group_name"    />
     </resultMap>
 
     <sql id="selectQwSopVo">
@@ -282,6 +288,12 @@
             <if test="data.isRating != null">is_rating,</if>
             <if test="data.courseDay != null">course_day,</if>
             <if test="data.openCommentStatus != null">open_comment_status,</if>
+            <if test="data.isLiveMgs != null">is_live_mgs,</if>
+            <if test="data.liveTempId != null">live_temp_id,</if>
+            <if test="data.liveTempSendTime != null">live_temp_send_time,</if>
+            <if test="data.autoGroup != null">auto_group,</if>
+            <if test="data.autoGroupLevel != null">auto_group_level,</if>
+            <if test="data.groupName != null">group_name,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="data.name != null">#{data.name},</if>
@@ -308,6 +320,12 @@
             <if test="data.isRating != null">#{data.isRating},</if>
             <if test="data.courseDay != null">#{data.courseDay},</if>
             <if test="data.openCommentStatus != null">#{data.openCommentStatus},</if>
+            <if test="data.isLiveMgs != null">#{data.isLiveMgs},</if>
+            <if test="data.liveTempId != null">#{data.liveTempId},</if>
+            <if test="data.liveTempSendTime != null">#{data.liveTempSendTime},</if>
+            <if test="data.autoGroup != null">#{data.autoGroup},</if>
+            <if test="data.autoGroupLevel != null">#{data.autoGroupLevel},</if>
+            <if test="data.groupName != null">#{data.groupName},</if>
         </trim>
     </insert>
 
@@ -388,6 +406,10 @@
             <if test="minSend != null "> and min_send = #{minSend}</if>
             <if test="maxSend != null "> and max_send = #{maxSend}</if>
             <if test="stopTime != null "> and stop_time = #{stopTime}</if>
+            <if test="isLiveMgs != null "> and is_live_mgs = #{isLiveMgs}</if>
+            <if test="liveTempId != null "> and live_temp_id = #{liveTempId}</if>
+            <if test="liveTempSendTime != null "> and live_temp_send_time = #{liveTempSendTime}</if>
+            <if test="groupName != null "> and group_name = #{groupName}</if>
             <!-- 加入固定条件 -->
             and status != 6
         </where>
@@ -477,6 +499,12 @@
             <if test="data.openCommentStatus != null">open_comment_status = #{data.openCommentStatus},</if>
             <if test="data.chatId != null">chat_id = #{data.chatId},</if>
             <if test="data.isSampSend != null">is_samp_send = #{data.isSampSend},</if>
+            <if test="data.isLiveMgs != null">is_live_mgs = #{data.isLiveMgs},</if>
+            <if test="data.liveTempId != null">live_temp_id = #{data.liveTempId},</if>
+            <if test="data.liveTempSendTime != null">live_temp_send_time = #{data.liveTempSendTime},</if>
+            <if test="data.autoGroup != null">auto_group = #{data.autoGroup},</if>
+            <if test="data.autoGroupLevel != null">auto_group_level = #{data.autoGroupLevel},</if>
+            <if test="data.groupName != null">group_name = #{data.groupName},</if>
         </trim>
         where id = #{data.id}
     </update>
@@ -568,5 +596,12 @@
         </where>
         order by create_time desc
     </select>
+    <select id="selectGroup" resultMap="QwSopResult">
+        select * from qw_sop where auto_group = 1
+    </select>
+
+    <update id="updateSopGroupIds">
+        update qw_sop set chat_id = #{chatId},pull_time = now() where id = #{id}
+    </update>
 
 </mapper>