|
@@ -5,7 +5,9 @@ import cn.hutool.core.util.ObjUtil;
|
|
|
import cn.hutool.extra.spring.SpringUtil;
|
|
|
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
|
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
|
|
+import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
|
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
|
|
+import cn.iocoder.yudao.module.infra.api.ai.AiApi;
|
|
|
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
|
|
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
|
|
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
|
@@ -20,19 +22,22 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuMessageMapper;
|
|
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
|
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
|
|
import jakarta.annotation.Resource;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
+import reactor.core.publisher.Flux;
|
|
|
|
|
|
import java.util.Collections;
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
|
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
|
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
|
|
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
|
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.KEFU_CONVERSATION_NOT_EXISTS;
|
|
|
-import static cn.iocoder.yudao.module.promotion.enums.WebSocketMessageTypeConstants.KEFU_MESSAGE_ADMIN_READ;
|
|
|
-import static cn.iocoder.yudao.module.promotion.enums.WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE;
|
|
|
+import static cn.iocoder.yudao.module.promotion.enums.WebSocketMessageTypeConstants.*;
|
|
|
|
|
|
/**
|
|
|
* 客服消息 Service 实现类
|
|
@@ -41,6 +46,7 @@ import static cn.iocoder.yudao.module.promotion.enums.WebSocketMessageTypeConsta
|
|
|
*/
|
|
|
@Service
|
|
|
@Validated
|
|
|
+@Slf4j
|
|
|
public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|
|
|
|
|
@Resource
|
|
@@ -53,7 +59,8 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|
|
private MemberUserApi memberUserApi;
|
|
|
@Resource
|
|
|
private WebSocketSenderApi webSocketSenderApi;
|
|
|
-
|
|
|
+ @Resource
|
|
|
+ private AiApi aiApi;
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public Long sendKefuMessage(KeFuMessageSendReqVO sendReqVO) {
|
|
@@ -100,6 +107,7 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
+ //@Async
|
|
|
public Long sendMessage(AppKeFuMessageSendReqVO sendReqVO) {
|
|
|
// 1.1 设置会话编号
|
|
|
KeFuMessageDO kefuMessage = BeanUtils.toBean(sendReqVO, KeFuMessageDO.class);
|
|
@@ -118,7 +126,21 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|
|
MemberUserRespDTO user = memberUserApi.getUser(kefuMessage.getSenderId());
|
|
|
KeFuMessageRespVO message =
|
|
|
BeanUtils.toBean(kefuMessage, KeFuMessageRespVO.class).setSenderAvatar(user.getAvatar());
|
|
|
- getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_TYPE, message);
|
|
|
+ getSelf().sendAsyncMessageToMember(sendReqVO.getRelUserId(), KEFU_MESSAGE_IM, message);
|
|
|
+ String apiKey = DictFrameworkUtils.parseDictDataValue("ai_key", "多轮对话");
|
|
|
+ Map<String, Object> inputs = new HashMap<>();
|
|
|
+ inputs.put("type", "活林木");
|
|
|
+ aiApi.getDifyMessageStreaming(inputs,
|
|
|
+ SecurityFrameworkUtils.getLoginUserId().toString(),
|
|
|
+ apiKey, sendReqVO.getContent(), "123")
|
|
|
+ .flatMap(response -> {
|
|
|
+ log.info("流式结果:" + response.toString());
|
|
|
+ message.setContent(response);
|
|
|
+ getSelf().sendAsyncMessageToMember(sendReqVO.getRelUserId(), KEFU_MESSAGE_IM, message);
|
|
|
+ return Flux.empty();
|
|
|
+ }
|
|
|
+
|
|
|
+ );
|
|
|
return kefuMessage.getId();
|
|
|
}
|
|
|
|
|
@@ -128,11 +150,14 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|
|
// 1.1 校验会话是否存在
|
|
|
KeFuConversationDO conversation = conversationService.validateKefuConversationExists(conversationId);
|
|
|
// 1.2 如果是会员端处理已读,需要传递 userId;万一用户模拟一个 conversationId
|
|
|
- if (UserTypeEnum.MEMBER.getValue().equals(userType) && ObjUtil.notEqual(conversation.getUserId(), userId)) {
|
|
|
+ if (ObjUtil.notEqual(conversation.getUserId(), userId) && ObjUtil.notEqual(conversation.getRelUserId(),
|
|
|
+ userId)) {
|
|
|
throw exception(KEFU_CONVERSATION_NOT_EXISTS);
|
|
|
}
|
|
|
// 1.3 查询会话所有的未读消息 (tips: 多个客服,一个人点了,就都点了)
|
|
|
- List<KeFuMessageDO> messageList = keFuMessageMapper.selectListByConversationIdAndUserTypeAndReadStatus(conversationId, userType, Boolean.FALSE);
|
|
|
+ List<KeFuMessageDO> messageList =
|
|
|
+ keFuMessageMapper.selectListByConversationIdAndUserTypeAndReadStatus(conversationId, userId,
|
|
|
+ Boolean.FALSE);
|
|
|
if (CollUtil.isEmpty(messageList)) {
|
|
|
return;
|
|
|
}
|
|
@@ -143,19 +168,24 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|
|
// 2.2 将管理员未读消息计数更新为零
|
|
|
if (SecurityFrameworkUtils.getLoginUserId().equals(conversation.getUserId())) {
|
|
|
conversationService.updateAdminUnreadMessageCountToZero(conversationId);
|
|
|
+ getSelf().sendAsyncMessageToMember(conversation.getUserId(), KEFU_MESSAGE_ADMIN_READ,
|
|
|
+ new KeFuMessageRespVO().setConversationId(conversation.getId()));
|
|
|
}
|
|
|
if (SecurityFrameworkUtils.getLoginUserId().equals(conversation.getRelUserId())) {
|
|
|
conversationService.updateRelUnreadMessageCountToZero(conversationId);
|
|
|
+ getSelf().sendAsyncMessageToMember(conversation.getRelUserId(), KEFU_MESSAGE_ADMIN_READ,
|
|
|
+ new KeFuMessageRespVO().setConversationId(conversation.getId()));
|
|
|
}
|
|
|
|
|
|
// 2.3 发送消息通知会员,管理员已读 -> 会员更新发送的消息状态
|
|
|
- KeFuMessageDO keFuMessage = getFirst(filterList(messageList, message -> UserTypeEnum.MEMBER.getValue().equals(message.getSenderType())));
|
|
|
- assert keFuMessage != null; // 断言避免警告
|
|
|
- getSelf().sendAsyncMessageToMember(keFuMessage.getSenderId(), KEFU_MESSAGE_ADMIN_READ,
|
|
|
- new KeFuMessageRespVO().setConversationId(keFuMessage.getConversationId()));
|
|
|
+ /* KeFuMessageDO keFuMessage = getFirst(filterList(messageList, message -> UserTypeEnum.MEMBER.getValue()
|
|
|
+ .equals(message.getSenderType())));
|
|
|
+ assert keFuMessage != null; // 断言避免警告*/
|
|
|
+
|
|
|
+
|
|
|
// 2.4 通知所有管理员消息已读
|
|
|
- getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_ADMIN_READ,
|
|
|
- new KeFuMessageRespVO().setConversationId(keFuMessage.getConversationId()));
|
|
|
+ /* getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_ADMIN_READ,
|
|
|
+ new KeFuMessageRespVO().setConversationId(keFuMessage.getConversationId()));*/
|
|
|
}
|
|
|
|
|
|
private void validateReceiverExist(Long receiverId, Integer receiverType) {
|