Parcourir la source

群聊发送完课

吴树波 il y a 6 jours
Parent
commit
188fa7722f
31 fichiers modifiés avec 361 ajouts et 229 suppressions
  1. 98 54
      fs-company/src/main/java/com/fs/qw/SopUserLogsInfoController.java
  2. 40 25
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  3. 24 26
      fs-qwhook-sop/src/main/resources/application-dev.yml
  4. 2 2
      fs-qwhook-sop/src/main/resources/application.yml
  5. 4 3
      fs-service-system/src/main/java/com/fs/course/domain/FsCourseFinishTemp.java
  6. 1 0
      fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseFinishTempServiceImpl.java
  7. 1 0
      fs-service-system/src/main/java/com/fs/course/vo/FsCourseFinishTempVO.java
  8. 5 0
      fs-service-system/src/main/java/com/fs/qw/domain/QwGroupChatUser.java
  9. 2 0
      fs-service-system/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java
  10. 3 0
      fs-service-system/src/main/java/com/fs/qw/mapper/QwGroupChatUserMapper.java
  11. 1 0
      fs-service-system/src/main/java/com/fs/qw/param/QwExternalContactVOTime.java
  12. 1 0
      fs-service-system/src/main/java/com/fs/qw/param/SopUserLogsVO.java
  13. 1 0
      fs-service-system/src/main/java/com/fs/qw/service/IQwExternalContactService.java
  14. 3 0
      fs-service-system/src/main/java/com/fs/qw/service/IQwGroupChatUserService.java
  15. 5 0
      fs-service-system/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java
  16. 6 0
      fs-service-system/src/main/java/com/fs/qw/service/impl/QwGroupChatUserServiceImpl.java
  17. 1 0
      fs-service-system/src/main/java/com/fs/qw/vo/QwSopRuleTimeVO.java
  18. 6 1
      fs-service-system/src/main/java/com/fs/sop/domain/QwSop.java
  19. 1 0
      fs-service-system/src/main/java/com/fs/sop/domain/QwSopTemp.java
  20. 5 0
      fs-service-system/src/main/java/com/fs/sop/domain/SopUserLogsInfo.java
  21. 101 97
      fs-service-system/src/main/java/com/fs/sop/service/impl/QwSopLogsServiceImpl.java
  22. 7 7
      fs-service-system/src/main/java/com/fs/sop/service/impl/QwSopServiceImpl.java
  23. 14 1
      fs-service-system/src/main/java/com/fs/sop/service/impl/SopUserLogsServiceImpl.java
  24. 1 0
      fs-service-system/src/main/java/com/fs/sop/vo/SopUserLogsVo.java
  25. 6 6
      fs-service-system/src/main/resources/mapper/course/FsCourseFinishTempMapper.xml
  26. 9 0
      fs-service-system/src/main/resources/mapper/qw/QwExternalContactMapper.xml
  27. 3 0
      fs-service-system/src/main/resources/mapper/qw/QwGroupChatUserMapper.xml
  28. 4 4
      fs-service-system/src/main/resources/mapper/sop/QwSopLogsMapper.xml
  29. 1 0
      fs-service-system/src/main/resources/mapper/sop/QwSopMapper.xml
  30. 1 0
      fs-service-system/src/main/resources/mapper/sop/QwSopTempMapper.xml
  31. 4 3
      fs-service-system/src/main/resources/mapper/sop/SopUserLogsMapper.xml

+ 98 - 54
fs-company/src/main/java/com/fs/qw/SopUserLogsInfoController.java

@@ -8,9 +8,12 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.StringUtils;
+import com.fs.qw.domain.QwGroupChatUser;
 import com.fs.qw.param.QwExternalContactVOTime;
 import com.fs.qw.param.SopExternalContactInfo;
 import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.service.IQwGroupChatUserService;
 import com.fs.sop.domain.SopUserLogsInfo;
 import com.fs.sop.params.BatchSopUserLogsInfoParam;
 import com.fs.sop.params.SendUserLogsInfoMsgParam;
@@ -33,62 +36,108 @@ import java.util.stream.Collectors;
  */
 @RestController
 @RequestMapping("/qwSop/sopUserLogsInfo")
-public class SopUserLogsInfoController extends BaseController
-{
+public class SopUserLogsInfoController extends BaseController {
     @Autowired
     private ISopUserLogsInfoService sopUserLogsInfoService;
 
     @Autowired
     private IQwExternalContactService iQwExternalContactService;
 
+    @Autowired
+    private IQwGroupChatUserService qwGroupChatUserService;
+
     /**
      * 查询sopUserLogsInfo列表
      */
     @PreAuthorize("@ss.hasPermi('qw:sop:list')")
     @GetMapping("/list")
-    public TableDataInfo list(SopUserLogsInfo sopUserLogsInfo)
-    {
+    public TableDataInfo list(SopUserLogsInfo sopUserLogsInfo) {
         startPage();
-        List<SopUserLogsInfo> list = sopUserLogsInfoService.selectSopUserLogsInfoList(sopUserLogsInfo);
-
-        if (!list.isEmpty()){
-
-            List<Long> externalIdList = list.stream()
-                    .map(SopUserLogsInfo::getExternalId) // 提取 externalId
-                    .filter(Objects::nonNull) // 过滤掉 null 值,防止 NullPointerException
-                    .collect(Collectors.toList()); // 收集到 List
-
-            List<QwExternalContactVOTime> qwExternalContactVOTimes = iQwExternalContactService.selectQwExternalContactListVOByIds(externalIdList);
-
-
-            // 先将 qwExternalContactVOTimes 转换为 Map,key 为 id,value 为 ExternalContactInfo(包含 createTime 和 tagIds)
-            Map<Long, SopExternalContactInfo> externalContactInfoMap = qwExternalContactVOTimes.stream()
-                    .collect(Collectors.toMap(
-                            QwExternalContactVOTime::getId,
-                            item -> new SopExternalContactInfo(item.getCreateTime(), item.getTagIds(),item.getRemark())
-                    ));
-
-            // 遍历 list,赋值 inComTime 和 tagIds
-            list.forEach(item -> {
-                SopExternalContactInfo info = externalContactInfoMap.getOrDefault(item.getExternalId(), new SopExternalContactInfo("无进线时间", "无标签","无备注"));
-                item.setInComTime(info.getCreateTime());
-                item.setTagIds(info.getTagIds());
-                item.setRemark(info.getRemark());
-            });
-
-        }
-
-        if ((sopUserLogsInfo.getTagIds() != null && !sopUserLogsInfo.getTagIds().isEmpty())
-                || !StringUtil.strIsNullOrEmpty(sopUserLogsInfo.getRemark())) {
-            list = list.stream()
-                    .filter(item ->
-                            (sopUserLogsInfo.getTagIds() == null || sopUserLogsInfo.getTagIds().isEmpty() || item.getTagIds().contains(sopUserLogsInfo.getTagIds()))
-                                    && (StringUtil.strIsNullOrEmpty(sopUserLogsInfo.getRemark()) || item.getRemark().contains(sopUserLogsInfo.getRemark()))
-                    )
-                    .collect(Collectors.toList());
+        if (sopUserLogsInfo.getFilterMode() == 1) {
+            List<SopUserLogsInfo> list = sopUserLogsInfoService.selectSopUserLogsInfoList(sopUserLogsInfo);
+
+            if (!list.isEmpty()) {
+
+                List<Long> externalIdList = list.stream()
+                        .map(SopUserLogsInfo::getExternalId) // 提取 externalId
+                        .filter(Objects::nonNull) // 过滤掉 null 值,防止 NullPointerException
+                        .collect(Collectors.toList()); // 收集到 List
+
+                List<QwExternalContactVOTime> qwExternalContactVOTimes = iQwExternalContactService.selectQwExternalContactListVOByIds(externalIdList);
+
+
+                // 先将 qwExternalContactVOTimes 转换为 Map,key 为 id,value 为 ExternalContactInfo(包含 createTime 和 tagIds)
+                Map<Long, SopExternalContactInfo> externalContactInfoMap = qwExternalContactVOTimes.stream()
+                        .collect(Collectors.toMap(
+                                QwExternalContactVOTime::getId,
+                                item -> new SopExternalContactInfo(item.getCreateTime(), item.getTagIds(), item.getRemark())
+                        ));
+
+                // 遍历 list,赋值 inComTime 和 tagIds
+                list.forEach(item -> {
+                    SopExternalContactInfo info = externalContactInfoMap.getOrDefault(item.getExternalId(), new SopExternalContactInfo("无进线时间", "无标签", "无备注"));
+                    item.setInComTime(info.getCreateTime());
+                    item.setTagIds(info.getTagIds());
+                    item.setRemark(info.getRemark());
+                });
+
+            }
+
+            if ((sopUserLogsInfo.getTagIds() != null && !sopUserLogsInfo.getTagIds().isEmpty())
+                    || !StringUtil.strIsNullOrEmpty(sopUserLogsInfo.getRemark())) {
+                list = list.stream()
+                        .filter(item ->
+                                (sopUserLogsInfo.getTagIds() == null || sopUserLogsInfo.getTagIds().isEmpty() || item.getTagIds().contains(sopUserLogsInfo.getTagIds()))
+                                        && (StringUtil.strIsNullOrEmpty(sopUserLogsInfo.getRemark()) || item.getRemark().contains(sopUserLogsInfo.getRemark()))
+                        )
+                        .collect(Collectors.toList());
+            }
+
+            return getDataTable(list);
+        } else {
+            List<QwGroupChatUser> list = qwGroupChatUserService.selectByChatId(sopUserLogsInfo);
+
+
+            if (!list.isEmpty()) {
+
+                List<String> externalIdList = list.stream()
+                        .map(QwGroupChatUser::getUserId) // 提取 externalId
+                        .filter(StringUtils::isNotEmpty) // 过滤掉 null 值,防止 NullPointerException
+                        .distinct()
+                        .collect(Collectors.toList()); // 收集到 List
+
+                List<QwExternalContactVOTime> qwExternalContactVOTimes = iQwExternalContactService.selectQwExternalContactListVOByUserIds(externalIdList);
+
+
+                // 先将 qwExternalContactVOTimes 转换为 Map,key 为 id,value 为 ExternalContactInfo(包含 createTime 和 tagIds)
+                Map<String, SopExternalContactInfo> externalContactInfoMap = qwExternalContactVOTimes.stream()
+                        .collect(Collectors.toMap(
+                                QwExternalContactVOTime::getExternalUserId,
+                                item -> new SopExternalContactInfo(item.getCreateTime(), item.getTagIds(), item.getRemark())
+                        ));
+
+                // 遍历 list,赋值 inComTime 和 tagIds
+                list.forEach(item -> {
+                    SopExternalContactInfo info = externalContactInfoMap.getOrDefault(item.getUserId(), new SopExternalContactInfo("无进线时间", "无标签", "无备注"));
+                    item.setInComTime(info.getCreateTime());
+                    item.setTagIds(info.getTagIds());
+                    item.setRemark(info.getRemark());
+                });
+
+            }
+
+            if ((sopUserLogsInfo.getTagIds() != null && !sopUserLogsInfo.getTagIds().isEmpty())
+                    || !StringUtil.strIsNullOrEmpty(sopUserLogsInfo.getRemark())) {
+                list = list.stream()
+                        .filter(item ->
+                                (sopUserLogsInfo.getTagIds() == null || sopUserLogsInfo.getTagIds().isEmpty() || item.getTagIds().contains(sopUserLogsInfo.getTagIds()))
+                                        && (StringUtil.strIsNullOrEmpty(sopUserLogsInfo.getRemark()) || item.getRemark().contains(sopUserLogsInfo.getRemark()))
+                        )
+                        .collect(Collectors.toList());
+            }
+            return getDataTable(list);
         }
 
-
 //        if (sopUserLogsInfo.getTagIds() != null && !sopUserLogsInfo.getTagIds().isEmpty()) {
 //            list = list.stream()
 //                    .filter(item -> item.getTagIds().contains(sopUserLogsInfo.getTagIds()))
@@ -99,8 +148,6 @@ public class SopUserLogsInfoController extends BaseController
 //                    .filter(item -> item.getRemark().contains(sopUserLogsInfo.getRemark()))
 //                    .collect(Collectors.toList());
 //        }
-
-        return getDataTable(list);
     }
 
 //    /**
@@ -116,13 +163,13 @@ public class SopUserLogsInfoController extends BaseController
 //        return util.exportExcel(list, "sopUserLogsInfo数据");
 //    }
 //
+
     /**
      * 获取sopUserLogsInfo详细信息
      */
     @PreAuthorize("@ss.hasPermi('qw:sop:list')")
     @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") String id)
-    {
+    public AjaxResult getInfo(@PathVariable("id") String id) {
         return AjaxResult.success(sopUserLogsInfoService.selectSopUserLogsInfoById(id));
     }
 
@@ -132,8 +179,7 @@ public class SopUserLogsInfoController extends BaseController
     @PreAuthorize("@ss.hasPermi('qw:sopUserLogsInfo:edit')")
     @Log(title = "updateSopUserLogsInfo", businessType = BusinessType.UPDATE)
     @PostMapping("/batchUpdateSopUserLogsInfoToTime")
-    public R edit(@RequestBody BatchSopUserLogsInfoParam param)
-    {
+    public R edit(@RequestBody BatchSopUserLogsInfoParam param) {
         return sopUserLogsInfoService.batchUpdateSopUserLogsInfoToTime(param);
     }
 
@@ -141,11 +187,10 @@ public class SopUserLogsInfoController extends BaseController
      * 一键群发sopUserLogsInfo
      */
     @PreAuthorize("@ss.hasPermi('qw:sopUserLogsInfo:msg')")
-    @Log(title = "sendMsgSopUserLogsInfo", businessType = BusinessType.INSERT,isSaveRequestData=false)
+    @Log(title = "sendMsgSopUserLogsInfo", businessType = BusinessType.INSERT, isSaveRequestData = false)
     @PostMapping("/sendUserLogsInfoMsg")
     @RepeatSubmit
-    public R sendUserLogsInfoMsg(@RequestBody SendUserLogsInfoMsgParam param)
-    {
+    public R sendUserLogsInfoMsg(@RequestBody SendUserLogsInfoMsgParam param) {
         return sopUserLogsInfoService.sendUserLogsInfoMsg(param);
     }
 
@@ -154,9 +199,8 @@ public class SopUserLogsInfoController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('qw:sopUserLogsInfo:remove')")
     @Log(title = "deleteSopUserLogsInfo", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable String[] ids)
-    {
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable String[] ids) {
         return toAjax(sopUserLogsInfoService.deleteSopUserLogsInfoByIds(ids));
     }
 }

+ 40 - 25
fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java

@@ -3,6 +3,8 @@ package com.fs.app.taskService.impl;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.app.taskService.SopLogsTaskService;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.base.BaseException;
@@ -549,25 +551,27 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 
                         List<SopUserLogsInfo> sopUserLogsInfos = sopUserLogsInfoMapper.selectSopUserLogsInfoListByIsRegister(logsInfoParam);
 
-//                        if(logVo.getIsRegister() == 1){
-//                            List<Long> externalContactIdList = PubFun.listToNewList(sopUserLogsInfos, SopUserLogsInfo::getExternalId);
-//                            List<QwExternalContact> list = qwExternalContactService.list(new QueryWrapper<QwExternalContact>().isNotNull("fs_user_id").in("id", externalContactIdList));
-//                            Map<Long, QwExternalContact> map = PubFun.listToMapByGroupObject(list, QwExternalContact::getId);
-//                            sopUserLogsInfos = sopUserLogsInfos.stream().filter(e -> map.containsKey(e.getExternalId())).collect(Collectors.toList());
-//                        }
+                        if(logVo.getIsRegister() == 1){
+                            List<Long> externalContactIdList = PubFun.listToNewList(sopUserLogsInfos, SopUserLogsInfo::getExternalId);
+                            if(!externalContactIdList.isEmpty()){
+                                List<QwExternalContact> list = qwExternalContactService.list(new QueryWrapper<QwExternalContact>().isNotNull("fs_user_id").in("id", externalContactIdList));
+                                Map<Long, QwExternalContact> map = PubFun.listToMapByGroupObject(list, QwExternalContact::getId);
+                                sopUserLogsInfos = sopUserLogsInfos.stream().filter(e -> map.containsKey(e.getExternalId())).collect(Collectors.toList());
+                            }
+                        }
 
 
                         // 获取fsUserId
-//                        Set<Long> externalIds = sopUserLogsInfos.stream().map(SopUserLogsInfo::getExternalId).collect(Collectors.toSet());
-//                        if (!externalIds.isEmpty()) {
-//                            List<QwExternalContact> externalContactList = qwExternalContactService.list(Wrappers.<QwExternalContact>lambdaQuery().in(QwExternalContact::getId, externalIds));
-//                            sopUserLogsInfos.forEach(s -> {
-//                                QwExternalContact qwExternalContact = externalContactList.stream().filter(e -> Objects.equals(s.getExternalId(), e.getId())).findFirst().orElse(null);
-//                                if (Objects.nonNull(qwExternalContact)) {
-//                                    s.setFsUserId(qwExternalContact.getFsUserId());
-//                                }
-//                            });
-//                        }
+                        Set<Long> externalIds = sopUserLogsInfos.stream().map(SopUserLogsInfo::getExternalId).collect(Collectors.toSet());
+                        if (!externalIds.isEmpty()) {
+                            List<QwExternalContact> externalContactList = qwExternalContactService.list(Wrappers.<QwExternalContact>lambdaQuery().in(QwExternalContact::getId, externalIds));
+                            sopUserLogsInfos.forEach(s -> {
+                                QwExternalContact qwExternalContact = externalContactList.stream().filter(e -> Objects.equals(s.getExternalId(), e.getId())).findFirst().orElse(null);
+                                if (Objects.nonNull(qwExternalContact)) {
+                                    s.setFsUserId(qwExternalContact.getFsUserId());
+                                }
+                            });
+                        }
 
 //                        insertSopUserLogs(sopUserLogsInfos, logVo, sendTime, ruleTimeVO, content);
                         insertSopUserLogs(sopUserLogsInfos, logVo, sendTime, ruleTimeVO, content, qwUserId, companyUserId, companyId, qwUserByRedis.getWelcomeText(),qwUserByRedis.getQwUserName(), groupChatMap);
@@ -672,6 +676,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                         type, qwUserId, companyUserId, companyId, groupChat.getChatId(), welcomeText,qwUserName, null, true);
             }else{
                 groupChat.getChatUserList().forEach(user -> {
+                    ruleTimeVO.setSendType(2);
+                    ruleTimeVO.setRemark("客户群催课");
                     QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, user.getUserId(), user.getName(), null);
                     handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
                             type, qwUserId, companyUserId, companyId, user.getUserId(), welcomeText,qwUserName, null, false);
@@ -725,6 +731,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         sopLogs.setSendType(ruleTimeVO.getSendType());
         sopLogs.setSendStatus(3L);
         sopLogs.setReceivingStatus(0L);
+        sopLogs.setRemark(ruleTimeVO.getRemark());
 
         String[] userKey = logVo.getUserId().split("\\|");
         sopLogs.setCompanyId(Long.valueOf(userKey[2].trim()));
@@ -1623,10 +1630,14 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                     continue;
                 }
 
+
+                // 查询完课模板信息
+                FsCourseFinishTemp finishTemp = fsCourseFinishTempMapper.selectFsCourseFinishTempByCompanyUserId(finishLog.getCompanyUserId(), finishLog.getVideoId());
+
+
                 List<QwGroupChatUser> qwGroupChatUserList = qwGroupChatUserService.selectUserIsChat(externalContact.getExternalUserId());
                 if(!qwGroupChatUserList.isEmpty()){
-                    FsCourseFinishTemp finishSopTemp = fsCourseFinishTempMapper.selectFsCourseFinishTempChatSopByCompanyUserId(finishLog.getCompanyUserId(), finishLog.getVideoId());
-                    if(finishSopTemp != null){
+                    if(finishTemp != null){
                         List<SopUserLogs> sopLogsList = sopUserLogsMapper.selectSopUserLogByChatIds(PubFun.listToNewList(qwGroupChatUserList, QwGroupChatUser::getChatId));
                         List<QwGroupChat> qwGroupChatList = qwGroupChatService.selectQwGroupChatByChatIds(PubFun.listToNewList(sopLogsList, SopUserLogs::getChatId).toArray(new String[0]));
                         Map<String, QwGroupChat> groupChatMap = PubFun.listToMapByGroupObject(qwGroupChatList, QwGroupChat::getChatId);
@@ -1636,13 +1647,10 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                                 e.setChatName(groupChat.getName());
                             }
                         });
-                        List<QwSopLogs> qwSopLogs = buildSopLogsChat(finishLog, finishSopTemp, externalContact, sopLogsList);
+                        List<QwSopLogs> qwSopLogs = buildSopLogsChat(finishLog, finishTemp, externalContact, sopLogsList);
                         sopLogsToInsert.addAll(qwSopLogs);
                     }
                 }
-
-                // 查询完课模板信息
-                FsCourseFinishTemp finishTemp = fsCourseFinishTempMapper.selectFsCourseFinishTempByCompanyUserId(finishLog.getCompanyUserId(), finishLog.getVideoId());
                 if (finishTemp == null) {
 //                    log.warn("完课模板不存在: " + finishLog.getCompanyUserId() + ", " + finishLog.getVideoId());
                     continue;
@@ -1716,9 +1724,16 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             sopLogs.setSopId(e.getSopId());
             sopLogs.setExternalUserId(e.getChatId());
             sopLogs.setExternalUserName(e.getChatName());
-            JSONObject obj = JSON.parseObject(finishTemp.getSetting());
-            obj.put("value", obj.getString("obj").replace("${name}", externalContact.getName()));
-            setting.setSetting(obj.toJSONString());
+            if(finishTemp.getChatSetting() == null || finishTemp.getChatSetting().isEmpty()){
+                throw new BaseException("消息为空");
+            }
+            JSONArray list = new JSONArray();
+            JSON.parseArray(finishTemp.getChatSetting()).forEach(item -> {
+                JSONObject obj = JSON.parseObject(item.toString());
+                obj.put("value", obj.getString("obj").replace("${name}", externalContact.getName()));
+                list.add(obj);
+            });
+            setting.setSetting(list.toJSONString());
             sopLogs.setContentJson(JSON.toJSONString(setting));
             return sopLogs;
         }).collect(Collectors.toList());

+ 24 - 26
fs-qwhook-sop/src/main/resources/application-dev.yml

@@ -3,15 +3,13 @@ spring:
     # redis 配置
     redis:
         # 地址
-        host: 127.0.0.1
+        host: localhost
         # 端口,默认为6379
         port: 6379
-        # 数据库索引
-        database: 0
         # 密码
         password:
         # 连接超时时间
-        timeout: 20s
+        timeout: 10s
         lettuce:
             pool:
                 # 连接池中的最小空闲连接
@@ -23,32 +21,21 @@ spring:
                 # #连接池最大阻塞等待时间(使用负值表示没有限制)
                 max-wait: -1ms
     datasource:
-#        clickhouse:
-#            type: com.alibaba.druid.pool.DruidDataSource
-#            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
-#            url: jdbc:clickhouse://1.14.104.71:8123/sop_test?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
-#            username: default
-#            password: rt2024
-#            initialSize: 10
-#            maxActive: 100
-#            minIdle: 10
-#            maxWait: 6000
         mysql:
             type: com.alibaba.druid.pool.DruidDataSource
             driverClassName: com.mysql.cj.jdbc.Driver
             druid:
                 # 主库数据源
                 master:
-                    url: jdbc:mysql://42.194.245.189:3306/rt_fs_his_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: YJF_2024
+                    url: jdbc:mysql://139.186.77.83:3306/ylrz_scrm?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: Rtroot
+                    password: Rtroot
                 # 从库数据源
                 slave:
                     # 从数据源开关/默认关闭
-                    enabled: false
-                    url:
-                    username:
-                    password:
+                    url: jdbc:mysql://139.186.77.83:3306/ylrz_scrm?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: Rtroot
+                    password: Rtroot
                 # 初始连接数
                 initialSize: 5
                 # 最小连接池数量
@@ -76,8 +63,8 @@ spring:
                     allow:
                     url-pattern: /druid/*
                     # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
+                    login-username:
+                    login-password:
                 filter:
                     stat:
                         enabled: true
@@ -94,9 +81,9 @@ spring:
             druid:
                 # 主库数据源
                 master:
-                    url: jdbc:mysql://42.194.245.189:3306/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: YJF_2024
+                    url: jdbc:mysql://139.186.77.83:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: Rtroot
+                    password: Rtroot
                 # 初始连接数
                 initialSize: 5
                 # 最小连接池数量
@@ -136,3 +123,14 @@ spring:
                     wall:
                         config:
                             multi-statement-allow: true
+
+rocketmq:
+    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+    consumer:
+        group: test-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey

+ 2 - 2
fs-qwhook-sop/src/main/resources/application.yml

@@ -42,8 +42,8 @@ spring:
     # 国际化资源文件路径
     basename: i18n/messages
   profiles:
-    active: druid
-#    active: dev
+#    active: druid
+    active: dev
     include: config
   mvc:
     async:

+ 4 - 3
fs-service-system/src/main/java/com/fs/course/domain/FsCourseFinishTemp.java

@@ -18,9 +18,6 @@ public class FsCourseFinishTemp extends BaseEntity
     /** $column.columnComment */
     private Long id;
 
-    /** 模板类型 1个人模板2群聊模板 */
-    @Excel(name = "模板名称")
-    private Integer type;
     /** 模板名称 */
     @Excel(name = "模板名称")
     private String name;
@@ -33,6 +30,10 @@ public class FsCourseFinishTemp extends BaseEntity
     @Excel(name = "规则")
     private String setting;
 
+    /** 规则 */
+    @Excel(name = "规则")
+    private String chatSetting;
+
     /** 公司id */
     @Excel(name = "公司id")
     private Long companyId;

+ 1 - 0
fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseFinishTempServiceImpl.java

@@ -101,6 +101,7 @@ public class FsCourseFinishTempServiceImpl implements IFsCourseFinishTempService
 
         //清理一下违禁词
         fsCourseFinishTemp.setSetting(JSON.toJSONString(processAndReplaceCrouseContent(fsCourseFinishTemp.getSetting())));
+        fsCourseFinishTemp.setChatSetting(JSON.toJSONString(processAndReplaceCrouseContent(fsCourseFinishTemp.getChatSetting())));
 
         return fsCourseFinishTempMapper.insertFsCourseFinishTemp(fsCourseFinishTemp);
     }

+ 1 - 0
fs-service-system/src/main/java/com/fs/course/vo/FsCourseFinishTempVO.java

@@ -51,6 +51,7 @@ public class FsCourseFinishTempVO extends BaseEntity {
     private Integer isAllCompanyUser;
 
     private Integer type;
+    private String chatSetting;
 
     public List<QwUserVO> userSelectList;
 }

+ 5 - 0
fs-service-system/src/main/java/com/fs/qw/domain/QwGroupChatUser.java

@@ -1,5 +1,6 @@
 package com.fs.qw.domain;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
@@ -84,5 +85,9 @@ public class QwGroupChatUser extends BaseEntity
      *  退群方式
      */
     private Integer quitScene;
+    @TableField(exist = false)
+    private String inComTime;
+    @TableField(exist = false)
+    private String tagIds;
 
 }

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

@@ -372,4 +372,6 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
     int updateContactByIds(@Param("ids") List<String> ids,@Param("status") Integer status);
 
     int batchUpdateContactByIds(@Param("list") List<Map<Long, Integer>> list);
+
+    List<QwExternalContactVOTime> selectQwExternalContactListVOByUserIds(@Param("ids") List<String> ids);
 }

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

@@ -3,6 +3,7 @@ package com.fs.qw.mapper;
 import com.fs.qw.domain.QwGroupChatUser;
 import com.fs.qw.param.QwGroupChatUserDataType;
 import com.fs.qw.vo.QwGroupChatUserVO;
+import com.fs.sop.domain.SopUserLogsInfo;
 import org.apache.ibatis.annotations.Delete;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -142,4 +143,6 @@ public interface QwGroupChatUserMapper
     List<QwGroupChatUser> selectQwGroupChatUserByChatIds(@Param("ids") String[] ids);
 
     List<QwGroupChatUser> selectUserIsChat(@Param("externalUserId") String externalUserId);
+
+    List<QwGroupChatUser> selectByChatId(SopUserLogsInfo sopUserLogsInfo);
 }

+ 1 - 0
fs-service-system/src/main/java/com/fs/qw/param/QwExternalContactVOTime.java

@@ -15,6 +15,7 @@ public class QwExternalContactVOTime {
     private String avatar;
 
     private String fsUserId;
+    private String externalUserId;
 
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private String createTime;

+ 1 - 0
fs-service-system/src/main/java/com/fs/qw/param/SopUserLogsVO.java

@@ -37,5 +37,6 @@ public class SopUserLogsVO {
     private String sopId;
 
     private String chatId;
+    private String chatName;
 
 }

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

@@ -197,4 +197,5 @@ public interface IQwExternalContactService extends IService<QwExternalContact> {
      */
     Boolean disabledUser(String[] ids, boolean status);
 
+    List<QwExternalContactVOTime> selectQwExternalContactListVOByUserIds(List<String> externalIdList);
 }

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

@@ -4,6 +4,7 @@ import com.fs.common.core.domain.R;
 import com.fs.qw.domain.QwGroupChatUser;
 import com.fs.qw.param.QwGroupChatUserDataType;
 import com.fs.qw.vo.QwGroupChatUserVO;
+import com.fs.sop.domain.SopUserLogsInfo;
 
 import java.util.List;
 
@@ -50,4 +51,6 @@ public interface IQwGroupChatUserService
     List<QwGroupChatUser> selectQwGroupChatUserByChatIds(String[] array);
 
     List<QwGroupChatUser> selectUserIsChat(String externalUserId);
+
+    List<QwGroupChatUser> selectByChatId(SopUserLogsInfo sopUserLogsInfo);
 }

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

@@ -4494,6 +4494,11 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
         return result > 0;
     }
 
+    @Override
+    public List<QwExternalContactVOTime> selectQwExternalContactListVOByUserIds(List<String> ids) {
+        return qwExternalContactMapper.selectQwExternalContactListVOByUserIds(ids);
+    }
+
     //发送好友欢迎语
     void SyncAddSendWelcome(QwExternalContact qwExternalContact, QwUser qwUser, String corpId) {
         QwFriendWelcomeVO qwFriendWelcomeVO = qwFriendWelcomeMapper.selectQwFriendWelcomeByUserIdVO(qwUser.getId(), corpId);

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

@@ -12,6 +12,7 @@ import com.fs.qw.service.IQwGroupChatUserService;
 import com.fs.qw.vo.QwGroupChatUserVO;
 import com.fs.qwApi.Result.QwGroupChatDetailsResult;
 import com.fs.qwApi.service.QwApiService;
+import com.fs.sop.domain.SopUserLogsInfo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -225,4 +226,9 @@ public class QwGroupChatUserServiceImpl implements IQwGroupChatUserService
         return qwGroupChatUserMapper.selectUserIsChat(externalUserId);
     }
 
+    @Override
+    public List<QwGroupChatUser> selectByChatId(SopUserLogsInfo sopUserLogsInfo) {
+        return qwGroupChatUserMapper.selectByChatId(sopUserLogsInfo);
+    }
+
 }

+ 1 - 0
fs-service-system/src/main/java/com/fs/qw/vo/QwSopRuleTimeVO.java

@@ -73,6 +73,7 @@ public class QwSopRuleTimeVO extends BaseEntity {
      * 过滤类别 1 包含全部 2 包含任意
      */
     private Integer filterType;
+    private Integer filterMode;
 
     /**
     * 模板内容

+ 6 - 1
fs-service-system/src/main/java/com/fs/sop/domain/QwSop.java

@@ -72,6 +72,11 @@ public class QwSop implements Serializable {
      */
     private Integer filterType;
 
+    /**
+     * 过滤类别 1 包含全部 2 包含任意
+     */
+    private Integer filterMode;
+
     private String corpId;
 
     private Integer expiryTime;
@@ -118,7 +123,7 @@ public class QwSop implements Serializable {
     private Integer courseDateNum;
     // 新课对话模板
     private String newTemplateId;
-    private Integer project;
+    private String project;
     // 群聊ID
     private String chatId;
 

+ 1 - 0
fs-service-system/src/main/java/com/fs/sop/domain/QwSopTemp.java

@@ -61,6 +61,7 @@ public class QwSopTemp implements Serializable
     private String updateTime;
 
     private String createBy;
+    private String project;
 
     @TableField(exist = false)
     private List<Map<String, Object>> rules;

+ 5 - 0
fs-service-system/src/main/java/com/fs/sop/domain/SopUserLogsInfo.java

@@ -40,4 +40,9 @@ public class SopUserLogsInfo implements Serializable {
     @TableField(exist = false)
     private Integer project;
 
+    @TableField(exist = false)
+    private Integer filterMode;
+    @TableField(exist = false)
+    private String chatId;
+
 }

+ 101 - 97
fs-service-system/src/main/java/com/fs/sop/service/impl/QwSopLogsServiceImpl.java

@@ -600,110 +600,114 @@ public class QwSopLogsServiceImpl implements IQwSopLogsService
             for (QwSopLogsDoSendListTVO log : logsByJsApi) {
 
                 try {
-
-                    if (log.getSendType()==3){
-                        try {
-                            // 使用现代的日期时间 API
-                            LocalDateTime sendTime = log.getSendTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
-                            LocalDateTime expiryDateTime = sendTime.plusHours(12);
-                            LocalDateTime now = LocalDateTime.now();
-
-                            // 判断是否过期
-                            if (now.isAfter(expiryDateTime)) {
-                                // 作废消息
-                                qwSopLogsService.updateQwSopLogsByWatchLogType(log.getId(), "已过期,不发送");
-                            } else {
-                                sendJsApiList.add(log);
+                    switch (log.getSendType()){
+                        case 3:
+                            try {
+                                // 使用现代的日期时间 API
+                                LocalDateTime sendTime = log.getSendTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+                                LocalDateTime expiryDateTime = sendTime.plusHours(12);
+                                LocalDateTime now = LocalDateTime.now();
+
+                                // 判断是否过期
+                                if (now.isAfter(expiryDateTime)) {
+                                    // 作废消息
+                                    qwSopLogsService.updateQwSopLogsByWatchLogType(log.getId(), "已过期,不发送");
+                                } else {
+                                    sendJsApiList.add(log);
+                                }
+                            } catch (Exception e) {
+                                // 记录错误日志
+                                logger.error("Error processing log in logsByJsApiOver: {}", log.getId()+":"+e);
                             }
-                        } catch (Exception e) {
-                            // 记录错误日志
-                            logger.error("Error processing log in logsByJsApiOver: {}", log.getId()+":"+e);
-                        }
-                    }else {
-
-                        QwSopTempSetting.Content content = JSON.parseObject(log.getContentJson(), QwSopTempSetting.Content.class);
-                        List<QwSopTempSetting.Content.Setting> setting = content.getSetting().stream().filter(e -> "9".equals(e.getContentType())).collect(Collectors.toList());
-
-                        //有app的异步推送消息
-                        if (!setting.isEmpty()) {
-                            asyncSopTestService.asyncSendMsgBySopAppLinkNormal(setting, param.getExternalId());
-                        }
-
-                        if (log.getExpiryTime() == null) {
-                            // 作废消息
-                            qwSopLogsService.updateQwSopLogsByWatchLogType(log.getId(), "SOP任务被删除");
-                        } else {
-                            Integer expiryTime = log.getExpiryTime();
-                            LocalDateTime sendTime = log.getSendTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
-                            LocalDateTime expiryDateTime = sendTime.plusHours(expiryTime);
-                            LocalDateTime now = LocalDateTime.now();
-
-                            // 判断是否过期
-                            if (now.isAfter(expiryDateTime)) {
-                                // 作废消息
-                                qwSopLogsService.updateQwSopLogsByWatchLogType(log.getId(), "已过期,不发送");
+                            break;
+                        case 6:
+                            sendJsApiList.add(log);
+                            break;
+                        default:
+                            QwSopTempSetting.Content content = JSON.parseObject(log.getContentJson(), QwSopTempSetting.Content.class);
+                            List<QwSopTempSetting.Content.Setting> setting = content.getSetting().stream().filter(e -> "9".equals(e.getContentType())).collect(Collectors.toList());
+
+                            //有app的异步推送消息
+                            if (!setting.isEmpty()) {
+                                asyncSopTestService.asyncSendMsgBySopAppLinkNormal(setting, param.getExternalId());
                             }
-                            else {
-                                switch (content.getType()) {
-                                    case 1:
-                                        // 普通消息,不做判断,加入发送列表
-                                        sendJsApiList.add(log);
-                                        break;
-                                    case 2:
-                                        // 课程消息,进行复杂的条件判断
-                                        FsCourseWatchLog watchLog = watchLogService.getWatchCourseLogVideoBySop(
-                                                Long.valueOf(content.getVideoId()),
-                                                String.valueOf(qwId),
-                                                qwExternalContactId
-                                        );
-
-                                        Integer courseType = content.getCourseType();
-                                        String logId = log.getId();
-
-                                        if (content.getCourseType()==null){
-                                            qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "模板未选消息类型,不发送");
-                                        }
-                                        if (watchLog != null) {
 
-                                            //新逻辑
-                                            if (isCourseTypeValid(courseType, watchLog.getLogType())) {
-                                                // 加入到发送列表中
-                                                sendJsApiList.add(log);
-                                            } else {
-                                                // 作废消息
-                                                qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "看课状态未满足,不发送");
+                            if (log.getExpiryTime() == null) {
+                                // 作废消息
+                                qwSopLogsService.updateQwSopLogsByWatchLogType(log.getId(), "SOP任务被删除");
+                            } else {
+                                Integer expiryTime = log.getExpiryTime();
+                                LocalDateTime sendTime = log.getSendTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+                                LocalDateTime expiryDateTime = sendTime.plusHours(expiryTime);
+                                LocalDateTime now = LocalDateTime.now();
+
+                                // 判断是否过期
+                                if (now.isAfter(expiryDateTime)) {
+                                    // 作废消息
+                                    qwSopLogsService.updateQwSopLogsByWatchLogType(log.getId(), "已过期,不发送");
+                                }
+                                else {
+                                    switch (content.getType()) {
+                                        case 1:
+                                            // 普通消息,不做判断,加入发送列表
+                                            sendJsApiList.add(log);
+                                            break;
+                                        case 2:
+                                            // 课程消息,进行复杂的条件判断
+                                            FsCourseWatchLog watchLog = watchLogService.getWatchCourseLogVideoBySop(
+                                                    Long.valueOf(content.getVideoId()),
+                                                    String.valueOf(qwId),
+                                                    qwExternalContactId
+                                            );
+
+                                            Integer courseType = content.getCourseType();
+                                            String logId = log.getId();
+
+                                            if (content.getCourseType()==null){
+                                                qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "模板未选消息类型,不发送");
                                             }
+                                            if (watchLog != null) {
+
+                                                //新逻辑
+                                                if (isCourseTypeValid(courseType, watchLog.getLogType())) {
+                                                    // 加入到发送列表中
+                                                    sendJsApiList.add(log);
+                                                } else {
+                                                    // 作废消息
+                                                    qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "看课状态未满足,不发送");
+                                                }
 
 
-                                        } else {
-                                            // 没有观看记录,只发普通消息
-                                            if (courseType == 0) {
-                                                sendJsApiList.add(log);
                                             } else {
-                                                qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "无观看记录,不发送");
+                                                // 没有观看记录,只发普通消息
+                                                if (courseType == 0) {
+                                                    sendJsApiList.add(log);
+                                                } else {
+                                                    qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "无观看记录,不发送");
+                                                }
                                             }
-                                        }
-                                        break;
-                                    case 3:
-                                        // 订单消息,不做判断,加入发送列表
-                                        sendJsApiList.add(log);
-                                        break;
-                                    case 4:
-                                        // Ai消息,不加入序列单独处理
-                                        try {
-                                            logger.info("Ai触达消息 : {}", log.getId());
-                                            //  fastGptChatSessionService.sendAiTouch(log,param.getCorpId().trim());
-                                        }catch (Exception e){
-                                            logger.error("Ai消息 : {}", content.getType());
-                                        }
-                                        break;
-                                    default:
-                                        // 未知类型,记录警告
-                                        logger.error("Unknown content type logsByJsApi: {}", content.getType());
-                                        break;
+                                            break;
+                                        case 3:
+                                            // 订单消息,不做判断,加入发送列表
+                                            sendJsApiList.add(log);
+                                            break;
+                                        case 4:
+                                            // Ai消息,不加入序列单独处理
+                                            try {
+                                                logger.info("Ai触达消息 : {}", log.getId());
+                                                //  fastGptChatSessionService.sendAiTouch(log,param.getCorpId().trim());
+                                            }catch (Exception e){
+                                                logger.error("Ai消息 : {}", content.getType());
+                                            }
+                                            break;
+                                        default:
+                                            // 未知类型,记录警告
+                                            logger.error("Unknown content type logsByJsApi: {}", content.getType());
+                                            break;
+                                    }
                                 }
                             }
-                        }
+                            break;
                     }
 
                 } catch (Exception e) {
@@ -714,11 +718,11 @@ public class QwSopLogsServiceImpl implements IQwSopLogsService
             //获取外部联系人
             QwSopLogs qwSopLogsByJsApiNext = qwSopLogsMapper.getQwSopLogsByJsApiNext(param);
 
-            if (qwSopLogsByJsApiNext!=null && !StringUtil.strIsNullOrEmpty(qwSopLogsByJsApiNext.getExternalUserId()) ){
+            if (qwSopLogsByJsApiNext != null && !StringUtil.strIsNullOrEmpty(qwSopLogsByJsApiNext.getExternalUserId())){
                 //过滤非外部联系人
                 try{
                     List<String> exIds=redisCache.getCacheObject("qwUserExtIds:"+param.getCorpId()+":"+param.getQwUserId());
-                    if(StringUtils.isNotEmpty(exIds)&&exIds.size()>0){
+                    if(StringUtils.isNotEmpty(exIds)&& !exIds.isEmpty()){
                         //查询外部联系人是否存在,如果不存在,返回下一个外部联系人
                         if(!exIds.contains(qwSopLogsByJsApiNext.getExternalUserId())){
                             //更新此外部联系人所有待发记录为作废
@@ -736,7 +740,6 @@ public class QwSopLogsServiceImpl implements IQwSopLogsService
                                     else{
                                         break;
                                     }
-
                                 }
                                 else {
                                     break;
@@ -754,6 +757,7 @@ public class QwSopLogsServiceImpl implements IQwSopLogsService
             sopParamDetailsC.setSendList(new ArrayList<>(sendJsApiList));
 
         }catch (Exception e){
+            e.printStackTrace();
             logger.error("主动获取发送信息失败:-"+e);
         }
 

+ 7 - 7
fs-service-system/src/main/java/com/fs/sop/service/impl/QwSopServiceImpl.java

@@ -24,10 +24,7 @@ import com.fs.qw.vo.QwSopRuleTimeVO;
 import com.fs.qwApi.Result.QwUploadImgResult;
 import com.fs.qwApi.service.QwApiService;
 import com.fs.sop.domain.*;
-import com.fs.sop.mapper.QwSopLogsMapper;
-import com.fs.sop.mapper.QwSopMapper;
-import com.fs.sop.mapper.SopUserLogsInfoMapper;
-import com.fs.sop.mapper.SopUserLogsMapper;
+import com.fs.sop.mapper.*;
 import com.fs.sop.params.*;
 import com.fs.sop.service.*;
 import com.fs.sop.vo.SopVoiceListVo;
@@ -116,6 +113,8 @@ public class QwSopServiceImpl implements IQwSopService
 
     @Autowired
     private RocketMQTemplate rocketMQTemplate;
+    @Autowired
+    private QwSopTempMapper qwSopTempMapper;
 
     /**
      * 查询企微sop
@@ -160,7 +159,8 @@ public class QwSopServiceImpl implements IQwSopService
     {
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         qwSop.setCreateTime(sdf.format(new Date()));
-
+        QwSopTemp qwSopTemp = qwSopTempMapper.selectById(qwSop.getTempId());
+        qwSop.setProject(qwSopTemp.getProject());
         return qwSopMapper.insert(qwSop);
     }
 
@@ -753,9 +753,9 @@ public class QwSopServiceImpl implements IQwSopService
 
 
         List<QwSop> qwSops = qwSopMapper.selectStatusQwSopById(ids);
-        List<QwSop> qwSopList = qwSops.stream().filter(e -> e.getType() == 2).collect(Collectors.toList());
+        List<QwSop> qwSopList = qwSops.stream().filter(e -> e.getType() == 2 && e.getFilterMode() == 1).collect(Collectors.toList());
         List<QwSop> wxSopList = qwSops.stream().filter(e -> e.getType() == 1).collect(Collectors.toList());
-        List<QwSop> chatSopList = qwSops.stream().filter(e -> e.getType() == 3).collect(Collectors.toList());
+        List<QwSop> chatSopList = qwSops.stream().filter(e -> e.getType() == 2 && e.getFilterMode() == 2).collect(Collectors.toList());
 
         if(!wxSopList.isEmpty()){
             // 筛选出 status == 1 的 IDs

+ 14 - 1
fs-service-system/src/main/java/com/fs/sop/service/impl/SopUserLogsServiceImpl.java

@@ -13,10 +13,12 @@ import com.fs.course.service.IFsCourseLinkService;
 import com.fs.crm.domain.CrmMsg;
 import com.fs.crm.mapper.CrmMsgMapper;
 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.QwUserMapper;
 import com.fs.qw.param.SopUserLogsVO;
+import com.fs.qw.service.IQwGroupChatService;
 import com.fs.qw.vo.QwSopRuleTimeVO;
 import com.fs.qw.vo.QwSopTempSetting;
 import com.fs.qwApi.service.QwApiService;
@@ -77,6 +79,8 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
     private QwSopMapper sopMapper;
     @Autowired
     private QwApiService qwApiService;
+    @Autowired
+    private IQwGroupChatService qwGroupChatService;
 
     @Autowired
     private RedisCache redisCache;
@@ -612,7 +616,16 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
 
     @Override
     public List<SopUserLogsVO> selectSopUserLogsList(SopUserLogsParam param) {
-        return sopUserLogsMapper.selectSopUserLogsListByParam(param);
+        List<SopUserLogsVO> list = sopUserLogsMapper.selectSopUserLogsListByParam(param);
+        List<String> chatIdList = PubFun.listToNewList(list, SopUserLogsVO::getChatId);
+        if(!chatIdList.isEmpty()){
+            List<QwGroupChat> qwGroupChatList = qwGroupChatService.selectQwGroupChatByChatIds(chatIdList.toArray(new String[0]));
+            Map<String, QwGroupChat> groupChatMap = PubFun.listToMapByGroupObject(qwGroupChatList, QwGroupChat::getChatId);
+            list.stream().filter(e -> groupChatMap.containsKey(e.getChatId())).forEach(e -> {
+                e.setChatName(groupChatMap.get(e.getChatId()).getName());
+            });
+        }
+        return list;
     }
 
     @Override

+ 1 - 0
fs-service-system/src/main/java/com/fs/sop/vo/SopUserLogsVo.java

@@ -8,6 +8,7 @@ import java.time.LocalDate;
 @Data
 public class SopUserLogsVo  {
     private String id;
+    private String filterMode;
     private String sopId;
     private String sopTempId;
 

+ 6 - 6
fs-service-system/src/main/resources/mapper/course/FsCourseFinishTempMapper.xml

@@ -17,7 +17,7 @@
         <result property="companyUserIds"    column="company_user_ids"    />
         <result property="updateTime"    column="update_time"    />
         <result property="isDel"    column="is_del"    />
-        <result property="type"    column="type"    />
+        <result property="chatSetting"    column="chat_setting"    />
         <result property="isAllCompanyUser"    column="is_all_company_user"    />
     </resultMap>
 
@@ -25,7 +25,7 @@
         select * from fs_course_finish_temp
     </sql>
 
-    <select id="selectFsCourseFinishTempList" parameterType="FsCourseFinishTemp" resultMap="FsCourseFinishTempResult">
+    <select id="selectFsCourseFinishTempList" parameterType="FsCourseFinishTemp" resultType="FsCourseFinishTemp">
         <include refid="selectFsCourseFinishTempVo"/>
         <where>
             <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
@@ -36,12 +36,11 @@
             <if test="videoId != null "> and video_id = #{videoId}</if>
             <if test="companyUserIds != null  and companyUserIds != ''"> and company_user_ids = #{companyUserIds}</if>
             <if test="isDel != null "> and is_del = #{isDel}</if>
-            <if test="type != null "> and type = #{type}</if>
             <if test="isAllCompanyUser != null "> and is_all_company_user = #{isAllCompanyUser}</if>
         </where>
     </select>
 
-    <select id="selectFsCourseFinishTempById" parameterType="Long" resultMap="FsCourseFinishTempResult">
+    <select id="selectFsCourseFinishTempById" parameterType="Long" resultType="FsCourseFinishTemp">
         <include refid="selectFsCourseFinishTempVo"/>
         where id = #{id}
     </select>
@@ -60,8 +59,8 @@
             <if test="companyUserIds != null">company_user_ids,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="isDel != null">is_del,</if>
-            <if test="type != null">type,</if>
             <if test="isAllCompanyUser != null">is_all_company_user,</if>
+            <if test="chatSetting != null">chat_setting,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="name != null">#{name},</if>
@@ -76,6 +75,7 @@
             <if test="updateTime != null">#{updateTime},</if>
             <if test="isDel != null">#{isDel},</if>
             <if test="isAllCompanyUser != null">#{isAllCompanyUser},</if>
+            <if test="chatSetting != null">#{chatSetting},</if>
         </trim>
     </insert>
 
@@ -93,8 +93,8 @@
             <if test="companyUserIds != null">company_user_ids = #{companyUserIds},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="isDel != null">is_del = #{isDel},</if>
-            <if test="type != null">type = #{type},</if>
             <if test="isAllCompanyUser != null">is_all_company_user = #{isAllCompanyUser},</if>
+            <if test="chatSetting != null">chat_setting = #{chatSetting},</if>
         </trim>
         where id = #{id}
     </update>

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

@@ -90,6 +90,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 </foreach>
     </select>
 
+    <select id="selectQwExternalContactListVOByUserIds" resultType="com.fs.qw.param.QwExternalContactVOTime">
+            select id,tag_ids,remark,create_time,external_user_id from qw_external_contact
+          where external_user_id in
+                <foreach collection="ids" item="id" open="(" separator="," close=")">
+                #{id}
+                </foreach>
+            group by external_user_id
+    </select>
+
     <select id="selectAllFormAd" resultType="com.fs.qw.result.QwExternalContactLogVo">
         select a.*
         ,user.nick_name

+ 3 - 0
fs-service-system/src/main/resources/mapper/qw/QwGroupChatUserMapper.xml

@@ -62,6 +62,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectUserIsChat" resultType="com.fs.qw.domain.QwGroupChatUser">
         select * from qw_group_chat_user a where a.user_id = #{externalUserId}
     </select>
+    <select id="selectByChatId" resultType="com.fs.qw.domain.QwGroupChatUser">
+        select * from qw_group_chat_user a where a.chat_id = #{chatId} and type = 2
+    </select>
 
     <insert id="insertOrUpdateQwGroupChatUser" parameterType="QwGroupChatUser" useGeneratedKeys="true" keyProperty="id">
         insert into qw_group_chat_user

+ 4 - 4
fs-service-system/src/main/resources/mapper/sop/QwSopLogsMapper.xml

@@ -300,7 +300,7 @@
           and ql.corp_id=#{data.corpId}
           and ql.external_user_id =#{data.externalUserId}
           and ql.log_type = 2
-          and ql.send_type in (2,3,5,7)
+          and ql.send_type in (2,3,5,6,7)
           and ql.send_status = 3
           and ql.receiving_status = 0
           and ql.send_time <= now()
@@ -376,16 +376,16 @@
         ]]>
     </select>
 
-    <select id="getQwSopLogsByJsApiNext" parameterType="com.fs.sop.params.GetQwSopLogsByJsApiParam" resultType="java.lang.String">
+    <select id="getQwSopLogsByJsApiNext" parameterType="com.fs.sop.params.GetQwSopLogsByJsApiParam" resultType="QwSopLogs">
         <![CDATA[
-        SELECT  external_user_id
+        SELECT  external_user_id,send_type
         FROM qw_sop_logs
         WHERE qw_userid = #{data.qwUserId}
           AND corp_id = #{data.corpId}
           AND external_user_id != #{data.externalUserId}
            AND log_type = 2
            AND send_status = 3
-           AND send_type in (2,3,5)
+           AND send_type in (2,3,5,6)
            AND receiving_status = 0
            AND send_time <= now()
         ORDER BY sort DESC,send_time ASC, rand()

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

@@ -30,6 +30,7 @@
         <result property="stopTime"    column="stop_time"    />
         <result property="isRating"    column="is_rating"    />
         <result property="courseDay"    column="course_day"    />
+        <result property="filterMode"    column="filter_mode"    />
     </resultMap>
 
     <sql id="selectQwSopVo">

+ 1 - 0
fs-service-system/src/main/resources/mapper/sop/QwSopTempMapper.xml

@@ -103,6 +103,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="data.gap != null">gap = #{data.gap},</if>
             <if test="data.sendType != null">send_type = #{data.sendType},</if>
             <if test="data.updateTime != null">update_time = #{data.updateTime},</if>
+            <if test="data.project != null">project = #{data.project},</if>
         </trim>
         where id = #{data.id}
     </update>

+ 4 - 3
fs-service-system/src/main/resources/mapper/sop/SopUserLogsMapper.xml

@@ -178,7 +178,7 @@
 
 
     <select id="selectSopUserLogsListByTime" resultType="com.fs.sop.vo.SopUserLogsVo">
-        select a.*,b.min_conversion_day,b.max_conversion_day,b.min_send,b.max_send,b.is_fixed,b.is_register,b.chat_id from sop_user_logs a
+        select a.*,b.min_conversion_day,b.max_conversion_day,b.min_send,b.max_send,b.is_fixed,b.is_register,b.chat_id,b.filter_mode from sop_user_logs a
         inner join qw_sop b on a.sop_id = b.id
         where a.start_time &lt;= Now() and a.status = 1 and b.send_type != 4 and b.status in (2,3)
     </select>
@@ -209,6 +209,7 @@
           AND corp_id = #{data.corpId}
           AND start_time = STR_TO_DATE(#{data.startTime}, '%Y-%m-%d')
           AND status = #{data.status}
+            AND chat_id is null
             limit 1
     </select>
 
@@ -222,7 +223,7 @@
           AND corp_id = #{data.corpId}
           AND start_time = STR_TO_DATE(#{data.startTime}, '%Y-%m-%d')
           AND status = #{data.status}
-            limit 1
+          AND chat_id is null limit 1
     </select>
 
     <select id="selectSopUserLogsInfoListByTime" resultType="com.fs.sop.vo.SopUserLogsInfoVo">
@@ -279,7 +280,7 @@
         order by send_time desc
     </select>
     <select id="selectSopUserLogsByDateAndIds" resultType="com.fs.sop.domain.SopUserLogs" >
-        select * from sop_user_logs where sop_id=#{sopId} and sop_temp_id=#{sopTempId}  and qw_user_id=#{qwUserId}  and corp_id=#{corpId}  and start_time=#{startTime}
+        select * from sop_user_logs where sop_id=#{sopId} and sop_temp_id=#{sopTempId}  and qw_user_id=#{qwUserId}  and corp_id=#{corpId}  and start_time=#{startTime} and chat_id is null
     </select>
     <select id="selectSopUserLogByChatIds" resultType="com.fs.sop.domain.SopUserLogs">
         select * from sop_user_logs where chat_id in <foreach collection="ids" open="(" separator="," close=")" item="item">#{item}</foreach>