|
@@ -2,24 +2,31 @@ package com.fs.app.taskService.impl;
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
-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;
|
|
|
import com.fs.common.utils.BatchUtils;
|
|
|
import com.fs.common.utils.PubFun;
|
|
|
import com.fs.common.utils.StringUtils;
|
|
|
+import com.fs.common.utils.date.DateUtil;
|
|
|
import com.fs.company.domain.CompanyUser;
|
|
|
import com.fs.company.service.ICompanyUserService;
|
|
|
import com.fs.course.config.CourseConfig;
|
|
|
import com.fs.course.domain.*;
|
|
|
import com.fs.course.mapper.*;
|
|
|
+import com.fs.course.param.FsCourseLinkCreateParam;
|
|
|
+import com.fs.course.service.IFsCourseLinkService;
|
|
|
import com.fs.fastgptApi.util.AudioUtils;
|
|
|
import com.fs.fastgptApi.vo.AudioVO;
|
|
|
import com.fs.qw.domain.QwExternalContact;
|
|
|
+import com.fs.qw.domain.QwGroupChat;
|
|
|
+import com.fs.qw.domain.QwGroupChatUser;
|
|
|
import com.fs.qw.domain.QwUser;
|
|
|
import com.fs.qw.mapper.QwExternalContactMapper;
|
|
|
import com.fs.qw.mapper.QwUserMapper;
|
|
|
import com.fs.qw.service.IQwExternalContactService;
|
|
|
+import com.fs.qw.service.IQwGroupChatService;
|
|
|
+import com.fs.qw.service.IQwGroupChatUserService;
|
|
|
import com.fs.qw.service.impl.QwExternalContactServiceImpl;
|
|
|
import com.fs.qw.vo.QwSopCourseFinishTempSetting;
|
|
|
import com.fs.qw.vo.QwSopRuleTimeVO;
|
|
@@ -55,6 +62,7 @@ import java.time.format.DateTimeFormatter;
|
|
|
import java.time.temporal.ChronoUnit;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.*;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
import static com.fs.course.utils.LinkUtil.generateRandomStringWithLock;
|
|
@@ -92,9 +100,15 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
private QwSopTagMapper qwSopTagMapper ;
|
|
|
@Autowired
|
|
|
private QwSopMapper sopMapper;
|
|
|
+ @Autowired
|
|
|
+ private IFsCourseLinkService courseLinkService;
|
|
|
|
|
|
@Autowired
|
|
|
private IQwExternalContactService iQwExternalContactService;
|
|
|
+ @Autowired
|
|
|
+ private IQwGroupChatService qwGroupChatService;
|
|
|
+ @Autowired
|
|
|
+ private IQwGroupChatUserService qwGroupChatUserService;
|
|
|
|
|
|
@Autowired
|
|
|
private QwExternalContactServiceImpl qwExternalContactService;
|
|
@@ -263,7 +277,15 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
log.info("没有需要处理的 SOP 用户日志。");
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+ String[] array = sopUserLogsVos.stream().map(SopUserLogsVo::getChatId).filter(StringUtils::isNotEmpty).toArray(String[]::new);
|
|
|
+ Map<String, QwGroupChat> groupChatMap = new HashMap<>();
|
|
|
+ if(array.length > 0){
|
|
|
+ List<QwGroupChat> qwGroupChatList = qwGroupChatService.selectQwGroupChatByChatIds(array);
|
|
|
+ List<QwGroupChatUser> qwGroupChatUserList = qwGroupChatUserService.selectQwGroupChatUserByChatIds(array);
|
|
|
+ Map<String, List<QwGroupChatUser>> chatUserMap = PubFun.listToMapByGroupList(qwGroupChatUserList, QwGroupChatUser::getChatId);
|
|
|
+ qwGroupChatList.stream().filter(e -> chatUserMap.containsKey(e.getChatId())).forEach(e -> e.setChatUserList(chatUserMap.get(e.getChatId())));
|
|
|
+ groupChatMap = PubFun.listToMapByGroupObject(qwGroupChatList, QwGroupChat::getChatId);
|
|
|
+ }
|
|
|
// 查询销售二级域名
|
|
|
Set<Long> ids = sopUserLogsVos.stream().map(s -> {
|
|
|
String[] userKey = s.getUserId().split("\\|");
|
|
@@ -308,7 +330,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
for (Map.Entry<String, List<SopUserLogsVo>> entry : sopLogsGroupedById.entrySet()) {
|
|
|
String sopId = entry.getKey();
|
|
|
List<SopUserLogsVo> userLogsVos = entry.getValue();
|
|
|
- processSopGroupAsync(sopId, userLogsVos, sopGroupLatch,currentTime);
|
|
|
+ processSopGroupAsync(sopId, userLogsVos, sopGroupLatch,currentTime, groupChatMap);
|
|
|
}
|
|
|
|
|
|
// 等待所有 SOP 分组处理完成
|
|
@@ -328,9 +350,9 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
maxAttempts = 3,
|
|
|
backoff = @Backoff(delay = 2000)
|
|
|
)
|
|
|
- public void processSopGroupAsync(String sopId, List<SopUserLogsVo> userLogsVos, CountDownLatch latch ,LocalDateTime currentTime) {
|
|
|
+ public void processSopGroupAsync(String sopId, List<SopUserLogsVo> userLogsVos, CountDownLatch latch , LocalDateTime currentTime, Map<String, QwGroupChat> groupChatMap) {
|
|
|
try {
|
|
|
- processSopGroup(sopId, userLogsVos,currentTime);
|
|
|
+ processSopGroup(sopId, userLogsVos,currentTime, groupChatMap);
|
|
|
} catch (Exception e) {
|
|
|
log.error("处理 SOP ID {} 时发生异常: {}", sopId, e.getMessage(), e);
|
|
|
} finally {
|
|
@@ -339,7 +361,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
}
|
|
|
|
|
|
|
|
|
- private void processSopGroup(String sopId, List<SopUserLogsVo> userLogsVos,LocalDateTime currentTime) throws Exception {
|
|
|
+ private void processSopGroup(String sopId, List<SopUserLogsVo> userLogsVos, LocalDateTime currentTime, Map<String, QwGroupChat> groupChatMap) throws Exception {
|
|
|
QwSopRuleTimeVO ruleTimeVO = sopMapper.selectQwSopByClickHouseId(sopId);
|
|
|
|
|
|
if (ruleTimeVO == null) {
|
|
@@ -373,7 +395,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
|
|
|
CountDownLatch userLogsLatch = new CountDownLatch(userLogsVos.size());
|
|
|
for (SopUserLogsVo logVo : userLogsVos) {
|
|
|
- processUserLogAsync(logVo, ruleTimeVO, rulesList, userLogsLatch, currentTime);
|
|
|
+ processUserLogAsync(logVo, ruleTimeVO, rulesList, userLogsLatch, currentTime, groupChatMap);
|
|
|
}
|
|
|
|
|
|
// 等待所有用户日志处理完成
|
|
@@ -392,9 +414,9 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
maxAttempts = 3,
|
|
|
backoff = @Backoff(delay = 2000)
|
|
|
)
|
|
|
- public void processUserLogAsync(SopUserLogsVo logVo, QwSopRuleTimeVO ruleTimeVO, List<QwSopTempRules> tempSettings, CountDownLatch latch, LocalDateTime currentTime) {
|
|
|
+ public void processUserLogAsync(SopUserLogsVo logVo, QwSopRuleTimeVO ruleTimeVO, List<QwSopTempRules> tempSettings, CountDownLatch latch, LocalDateTime currentTime, Map<String, QwGroupChat> groupChatMap) {
|
|
|
try {
|
|
|
- processUserLog(logVo, ruleTimeVO, tempSettings,currentTime);
|
|
|
+ processUserLog(logVo, ruleTimeVO, tempSettings,currentTime, groupChatMap);
|
|
|
} catch (Exception e) {
|
|
|
log.error("处理用户日志 {} 时发生异常: {}", logVo.getId(), e.getMessage(), e);
|
|
|
} finally {
|
|
@@ -403,7 +425,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
}
|
|
|
|
|
|
|
|
|
- private void processUserLog(SopUserLogsVo logVo, QwSopRuleTimeVO ruleTimeVO, List<QwSopTempRules> tempSettings, LocalDateTime currentTime) {
|
|
|
+ private void processUserLog(SopUserLogsVo logVo, QwSopRuleTimeVO ruleTimeVO, List<QwSopTempRules> tempSettings, LocalDateTime currentTime, Map<String, QwGroupChat> groupChatMap) {
|
|
|
try {
|
|
|
LocalDate startDate = LocalDate.parse(logVo.getStartTime(), DATE_FORMATTER);
|
|
|
LocalDate currentDate = currentTime.toLocalDate();
|
|
@@ -429,11 +451,11 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
day++;
|
|
|
}
|
|
|
List<QwSopTempSetting.Content> contents = getDay(tempSettings, day);
|
|
|
+
|
|
|
if (contents == null || contents.isEmpty()) {
|
|
|
log.error("SOP ID {} 的 TempSetting 内容为空,跳过处理。", logVo.getSopId());
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
String[] userKey = logVo.getUserId().split("\\|");
|
|
|
if (userKey.length < 3) {
|
|
|
log.error("用户 ID {} 格式不正确,跳过处理。", logVo.getUserId());
|
|
@@ -487,7 +509,6 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
|
|
|
for (QwSopTempSetting.Content content : contents) {
|
|
|
try {
|
|
|
-
|
|
|
LocalTime elementLocalTime = LocalTime.parse(content.getTime());
|
|
|
LocalDateTime elementDateTime = LocalDateTime.of(currentTime.toLocalDate(), elementLocalTime);
|
|
|
|
|
@@ -508,7 +529,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
|
|
|
// 如果时间差在目标范围内,更新记录
|
|
|
// 组合年月日和element的时间
|
|
|
- LocalDate targetDate = startDate.plusDays(intervalDay * tempGap);
|
|
|
+ LocalDate targetDate = startDate.plusDays((long) intervalDay * tempGap);
|
|
|
|
|
|
// 将 targetDate 和 elementTime 组合成 LocalDateTime
|
|
|
LocalDateTime dateTime = LocalDateTime.of(targetDate, elementLocalTime);
|
|
@@ -548,7 +569,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
// }
|
|
|
|
|
|
// insertSopUserLogs(sopUserLogsInfos, logVo, sendTime, ruleTimeVO, content);
|
|
|
- insertSopUserLogs(sopUserLogsInfos, logVo, sendTime, ruleTimeVO, content, qwUserId, companyUserId, companyId, qwUserByRedis.getWelcomeText(),qwUserByRedis.getQwUserName());
|
|
|
+ insertSopUserLogs(sopUserLogsInfos, logVo, sendTime, ruleTimeVO, content, qwUserId, companyUserId, companyId, qwUserByRedis.getWelcomeText(),qwUserByRedis.getQwUserName(), groupChatMap);
|
|
|
|
|
|
|
|
|
}
|
|
@@ -565,6 +586,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
|
|
|
private List<QwSopTempSetting.Content> getDay(List<QwSopTempRules> tempSettings, long days){
|
|
|
List<QwSopTempRules> collect = tempSettings.stream().filter(e -> e.getDayNum() == days).collect(Collectors.toList());
|
|
|
+ AtomicInteger i = new AtomicInteger();
|
|
|
return collect.stream().map(e -> {
|
|
|
QwSopTempSetting.Content content = new QwSopTempSetting.Content();
|
|
|
content.setId(e.getId());
|
|
@@ -583,13 +605,13 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
content.setCourseType(e.getCourseType());
|
|
|
content.setAiTouch(e.getAiTouch());
|
|
|
return content;
|
|
|
- }).collect(Collectors.toList());
|
|
|
+ }).sorted(Comparator.comparing(e -> LocalTime.parse(e.getTime() + ":00"))).peek(e -> e.setIndex(i.getAndIncrement())).collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
|
//消息处理
|
|
|
private void insertSopUserLogs(List<SopUserLogsInfo> sopUserLogsInfos, SopUserLogsVo logVo, Date sendTime,
|
|
|
- QwSopRuleTimeVO ruleTimeVO, QwSopTempSetting.Content content,
|
|
|
- String qwUserId,String companyUserId,String companyId,String welcomeText,String qwUserName) {
|
|
|
+ QwSopRuleTimeVO ruleTimeVO, QwSopTempSetting.Content content,
|
|
|
+ String qwUserId, String companyUserId, String companyId, String welcomeText, String qwUserName, Map<String, QwGroupChat> groupChatMap) {
|
|
|
|
|
|
String formattedSendTime = sendTime.toInstant()
|
|
|
.atZone(ZoneId.systemDefault())
|
|
@@ -639,20 +661,37 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
sopAddTag(logVo,content,sendTime);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- // 处理每个 externalContactId
|
|
|
- sopUserLogsInfos.forEach(contactId -> {
|
|
|
- try {
|
|
|
- String externalId = contactId.getExternalId().toString();
|
|
|
- String externalUserName = contactId.getExternalUserName();
|
|
|
- Long fsUserId = contactId.getFsUserId();
|
|
|
- QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, contactId.getExternalContactId(), externalUserName, fsUserId);
|
|
|
+ if(StringUtils.isNotEmpty(logVo.getChatId())){
|
|
|
+ QwGroupChat groupChat = groupChatMap.get(logVo.getChatId());
|
|
|
+ ruleTimeVO.setSendType(6);
|
|
|
+ ruleTimeVO.setType(2);
|
|
|
+ if(content.getIndex() == 0){
|
|
|
+ QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, groupChat.getChatId(), groupChat.getName(), null);
|
|
|
handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
|
|
|
- type, qwUserId, companyUserId, companyId, externalId, welcomeText,qwUserName,fsUserId);
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("处理 externalContactId {} 时发生异常: {}", contactId, e.getMessage(), e);
|
|
|
+ type, qwUserId, companyUserId, companyId, groupChat.getChatId(), welcomeText,qwUserName, null, true);
|
|
|
+ }else{
|
|
|
+ groupChat.getChatUserList().forEach(user -> {
|
|
|
+ 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);
|
|
|
+ });
|
|
|
}
|
|
|
- });
|
|
|
+ }else{
|
|
|
+ // 处理每个 externalContactId
|
|
|
+ sopUserLogsInfos.forEach(contactId -> {
|
|
|
+ try {
|
|
|
+ String externalId = contactId.getExternalId().toString();
|
|
|
+ String externalUserName = contactId.getExternalUserName();
|
|
|
+ Long fsUserId = contactId.getFsUserId();
|
|
|
+ QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, contactId.getExternalContactId(), externalUserName, fsUserId);
|
|
|
+ handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
|
|
|
+ type, qwUserId, companyUserId, companyId, externalId, welcomeText,qwUserName,fsUserId, false);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("处理 externalContactId {} 时发生异常: {}", contactId, e.getMessage(), e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
private void sopAddTag(SopUserLogsVo logVo, QwSopTempSetting.Content content, Date sendTime) {
|
|
@@ -700,15 +739,15 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
private void handleLogBasedOnType(QwSopLogs sopLogs, QwSopTempSetting.Content content,
|
|
|
SopUserLogsVo logVo, Date sendTime, Long courseId,
|
|
|
Long videoId, int type, String qwUserId,
|
|
|
- String companyUserId, String companyId, String externalId,String welcomeText,
|
|
|
- String qwUserName,Long fsUserId) {
|
|
|
+ String companyUserId, String companyId, String externalId, String welcomeText,
|
|
|
+ String qwUserName, Long fsUserId, boolean isGroupChat) {
|
|
|
switch (type) {
|
|
|
case 1:
|
|
|
handleNormalMessage(sopLogs, content,companyUserId);
|
|
|
break;
|
|
|
case 2:
|
|
|
handleCourseMessage(sopLogs, content, logVo, sendTime, courseId, videoId,
|
|
|
- qwUserId, companyUserId, companyId, externalId, welcomeText,qwUserName,fsUserId);
|
|
|
+ qwUserId, companyUserId, companyId, externalId, welcomeText,qwUserName,fsUserId, isGroupChat);
|
|
|
break;
|
|
|
case 3:
|
|
|
handleOrderMessage(sopLogs, content);
|
|
@@ -740,8 +779,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
private void handleCourseMessage(QwSopLogs sopLogs, QwSopTempSetting.Content content,
|
|
|
SopUserLogsVo logVo, Date sendTime, Long courseId,
|
|
|
Long videoId, String qwUserId, String companyUserId,
|
|
|
- String companyId, String externalId,String welcomeText,
|
|
|
- String qwUserName,Long fsUserId) {
|
|
|
+ String companyId, String externalId, String welcomeText,
|
|
|
+ String qwUserName, Long fsUserId, boolean isGroupChat) {
|
|
|
// 深拷贝 Content 对象,避免使用 JSON
|
|
|
QwSopTempSetting.Content clonedContent = deepCopyContent(content);
|
|
|
if (clonedContent == null) {
|
|
@@ -766,22 +805,40 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
|
|
|
case "1":
|
|
|
case "3":
|
|
|
if ("1".equals(setting.getIsBindUrl())) {
|
|
|
+ String link;
|
|
|
+ if(isGroupChat){
|
|
|
+ FsCourseLinkCreateParam createParam = new FsCourseLinkCreateParam();
|
|
|
+ createParam.setCourseId(courseId);
|
|
|
+ createParam.setVideoId(videoId);
|
|
|
+ createParam.setCorpId(logVo.getCorpId());
|
|
|
+ createParam.setCompanyUserId(Long.parseLong(companyUserId));
|
|
|
+ createParam.setCompanyId(Long.parseLong(companyId));
|
|
|
+ createParam.setChatId(logVo.getChatId());
|
|
|
+ createParam.setQwUserId(qwUserId);
|
|
|
+ createParam.setDays(setting.getExpiresDays());
|
|
|
+ R createLink = courseLinkService.createRoomLinkUrl(createParam);
|
|
|
+ if (createLink.get("code").equals(500)){
|
|
|
+ throw new BaseException("链接生成失败!");
|
|
|
+ }
|
|
|
+ link = (String) createLink.get("url");
|
|
|
+ }else{
|
|
|
+ addWatchLogIfNeeded(sopLogs, videoId, courseId, sendTime, qwUserId, companyUserId, companyId, externalId,logVo);
|
|
|
+ link = generateShortLink(setting, logVo, sendTime, courseId, videoId,
|
|
|
+ qwUserId, companyUserId, companyId, externalId,fsUserId);
|
|
|
+ }
|
|
|
|
|
|
- addWatchLogIfNeeded(sopLogs, videoId, courseId, sendTime, qwUserId, companyUserId, companyId, externalId,logVo);
|
|
|
- String sortLink = generateShortLink(setting, logVo, sendTime, courseId, videoId,
|
|
|
- qwUserId, companyUserId, companyId, externalId,fsUserId);
|
|
|
- if (StringUtils.isNotEmpty(sortLink)) {
|
|
|
+ if (StringUtils.isNotEmpty(link)) {
|
|
|
if ("3".equals(setting.getContentType())) {
|
|
|
- setting.setLinkUrl(sortLink);
|
|
|
+ setting.setLinkUrl(link);
|
|
|
} else {
|
|
|
String currentValue = setting.getValue();
|
|
|
if (currentValue == null) {
|
|
|
- setting.setValue(sortLink);
|
|
|
+ setting.setValue(link);
|
|
|
} else {
|
|
|
// setting.setValue(currentValue + "\n" + sortLink);
|
|
|
setting.setValue(currentValue
|
|
|
.replaceAll("#销售称呼#",StringUtil.strIsNullOrEmpty(welcomeText)?"":welcomeText)
|
|
|
- + "\n" + sortLink);
|
|
|
+ + "\n" + link);
|
|
|
}
|
|
|
}
|
|
|
} else {
|