|
|
@@ -0,0 +1,517 @@
|
|
|
+package com.fs.company.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.fs.common.core.domain.R;
|
|
|
+import com.fs.common.utils.spring.SpringUtils;
|
|
|
+import com.fs.company.domain.AiAddwxSopTemplate;
|
|
|
+import com.fs.company.domain.AiAddwxSopTemplateNode;
|
|
|
+import com.fs.company.domain.AiAddwxSopTemplateNodeRule;
|
|
|
+import com.fs.company.domain.AiAddwxSopUserNode;
|
|
|
+import com.fs.company.domain.AiAddwxSopUserNodeRule;
|
|
|
+import com.fs.company.domain.AiAddwxSopUserWorkflow;
|
|
|
+import com.fs.company.enums.AiAddWechatSopNodeEnum;
|
|
|
+import com.fs.company.mapper.AiAddwxSopTagTemplateBindMapper;
|
|
|
+import com.fs.company.mapper.AiAddwxSopTemplateMapper;
|
|
|
+import com.fs.company.mapper.AiAddwxSopTemplateNodeMapper;
|
|
|
+import com.fs.company.mapper.AiAddwxSopTemplateNodeRuleMapper;
|
|
|
+import com.fs.company.mapper.AiAddwxSopUserNodeMapper;
|
|
|
+import com.fs.company.mapper.AiAddwxSopUserNodeRuleMapper;
|
|
|
+import com.fs.company.mapper.AiAddwxSopUserWorkflowMapper;
|
|
|
+import com.fs.company.service.IAiAddwxSopTemplateService;
|
|
|
+import com.fs.config.ai.AiHostProper;
|
|
|
+import com.fs.crm.utils.CrmCustomerAiTagUtil;
|
|
|
+import com.fs.fastGpt.domain.FastGptChatMsg;
|
|
|
+import com.fs.fastGpt.domain.FastGptChatSession;
|
|
|
+import com.fs.fastGpt.mapper.FastGptChatMsgMapper;
|
|
|
+import com.fs.fastGpt.mapper.FastGptChatSessionMapper;
|
|
|
+import com.fs.fastGpt.service.IFastGptChatMsgService;
|
|
|
+import com.fs.fastgptApi.param.ChatParam;
|
|
|
+import com.fs.fastgptApi.service.ChatService;
|
|
|
+import com.fs.ipad.vo.BaseVo;
|
|
|
+import com.fs.qw.domain.QwExternalContact;
|
|
|
+import com.fs.qw.domain.QwUser;
|
|
|
+import com.fs.qw.mapper.QwTagMapper;
|
|
|
+import com.fs.qw.mapper.QwUserMapper;
|
|
|
+import com.fs.qw.vo.QwSopCourseFinishTempSetting;
|
|
|
+import com.fs.sop.domain.QwSopLogs;
|
|
|
+import com.vdurmont.emoji.EmojiParser;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.ThreadLocalRandom;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+import java.util.stream.Stream;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * AI添加微信SOP模板Service业务层处理
|
|
|
+ *
|
|
|
+ * @author fs
|
|
|
+ * @date 2026-06-24
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class AiAddwxSopTemplateServiceImpl implements IAiAddwxSopTemplateService {
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(AiAddwxSopTemplateServiceImpl.class);
|
|
|
+ @Autowired
|
|
|
+ private AiAddwxSopTemplateMapper templateMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AiAddwxSopTemplateNodeMapper templateNodeMapper;
|
|
|
+ @Autowired
|
|
|
+ private AiAddwxSopTemplateNodeRuleMapper templateNodeRuleMapper;
|
|
|
+ @Autowired
|
|
|
+ private AiAddwxSopUserWorkflowMapper userWorkflowMapper;
|
|
|
+ @Autowired
|
|
|
+ private AiAddwxSopUserNodeMapper userNodeMapper;
|
|
|
+ @Autowired
|
|
|
+ private AiAddwxSopUserNodeRuleMapper userNodeRuleMapper;
|
|
|
+ @Autowired
|
|
|
+ private AiAddwxSopTagTemplateBindMapper aiAddwxSopTagTemplateBindMapper;
|
|
|
+ @Qualifier("qwUserMapper")
|
|
|
+ @Autowired
|
|
|
+ private QwUserMapper qwUserMapper;
|
|
|
+ @Autowired
|
|
|
+ private QwTagMapper qwTagMapper;
|
|
|
+ @Autowired
|
|
|
+ private FastGptChatSessionMapper fastGptChatSessionMapper;
|
|
|
+ @Autowired
|
|
|
+ private IFastGptChatMsgService fastGptChatMsgService;
|
|
|
+ @Qualifier("fastGptChatMsgMapper")
|
|
|
+ @Autowired
|
|
|
+ private FastGptChatMsgMapper fastGptChatMsgMapper;
|
|
|
+
|
|
|
+ @Value("${cid.addwx.sop.appKey:fastgpt-hPSZNV9pPlX5GlHyjzsGqEPbB2D8tb9mYQcnD1y5lEUIEMgGaO0PFm7BHHjF}")
|
|
|
+ private String CID_ADDWX_SOP_APPKEY;
|
|
|
+ @Autowired
|
|
|
+ private AiAddwxSopUserNodeRuleMapper aiAddwxSopUserNodeRuleMapper;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AiAddwxSopTemplate selectAiAddwxSopTemplateById(Long templateId) {
|
|
|
+ return templateMapper.selectAiAddwxSopTemplateById(templateId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<AiAddwxSopTemplate> selectAiAddwxSopTemplateList(AiAddwxSopTemplate template) {
|
|
|
+ return templateMapper.selectAiAddwxSopTemplateList(template);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Long insertAiAddwxSopTemplate(AiAddwxSopTemplate template) {
|
|
|
+ templateMapper.insertAiAddwxSopTemplate(template);
|
|
|
+ return template.getTemplateId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int updateAiAddwxSopTemplate(AiAddwxSopTemplate template) {
|
|
|
+ return templateMapper.updateAiAddwxSopTemplate(template);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int deleteAiAddwxSopTemplateByIds(Long[] templateIds) {
|
|
|
+ return templateMapper.deleteAiAddwxSopTemplateByIds(templateIds);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AiAddwxSopTemplate selectTemplateDetailById(Long templateId) {
|
|
|
+ AiAddwxSopTemplate template = templateMapper.selectAiAddwxSopTemplateById(templateId);
|
|
|
+ if (template != null) {
|
|
|
+ List<AiAddwxSopTemplateNode> nodes = templateNodeMapper.selectAiAddwxSopTemplateNodeByTemplateId(templateId);
|
|
|
+ // 可通过VO扩展返回节点列表,此处简化处理
|
|
|
+ }
|
|
|
+ return template;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Long saveTemplateWithNodes(AiAddwxSopTemplate template, List<AiAddwxSopTemplateNode> nodes) {
|
|
|
+ if (template.getTemplateId() == null) {
|
|
|
+ templateMapper.insertAiAddwxSopTemplate(template);
|
|
|
+ } else {
|
|
|
+ templateMapper.updateAiAddwxSopTemplate(template);
|
|
|
+ // 删除旧节点
|
|
|
+ templateNodeMapper.deleteAiAddwxSopTemplateNodeByTemplateId(template.getTemplateId());
|
|
|
+ }
|
|
|
+ if (nodes != null && !nodes.isEmpty()) {
|
|
|
+ for (AiAddwxSopTemplateNode node : nodes) {
|
|
|
+ node.setTemplateId(template.getTemplateId());
|
|
|
+ node.setCreateTime(new Date());
|
|
|
+ node.setUpdateTime(new Date());
|
|
|
+ }
|
|
|
+ templateNodeMapper.batchInsertAiAddwxSopTemplateNode(nodes);
|
|
|
+ }
|
|
|
+ return template.getTemplateId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+// @Async
|
|
|
+ public void initAddWxSop(List<QwExternalContact> externalUsers, List<String> tagIds) {
|
|
|
+ //qw_tag_id获取优先级最高的那条template_id
|
|
|
+ if (tagIds == null || tagIds.isEmpty()) return;
|
|
|
+ if (externalUsers == null || externalUsers.isEmpty()) return;
|
|
|
+ List<Long> tagIdlist = qwTagMapper.selectIdsByTagIds(tagIds);
|
|
|
+ Long aiAddwxTemplateId = aiAddwxSopTagTemplateBindMapper.selectOneAiAddwxSopTagTemplateBindByTagIds(tagIdlist);
|
|
|
+ if (aiAddwxTemplateId == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<Long> collect = externalUsers.stream().map(QwExternalContact::getQwUserId).collect(Collectors.toList());
|
|
|
+ List<QwUser> qwUsers = qwUserMapper.selectQwUserByIdsPrimary(collect);
|
|
|
+ Map<Long, QwUser> qwUserMap = qwUsers.stream().collect(Collectors.toMap(
|
|
|
+ QwUser::getId,
|
|
|
+ user -> user,
|
|
|
+ (k1, k2) -> k1
|
|
|
+ ));
|
|
|
+
|
|
|
+ // 查询模板
|
|
|
+ AiAddwxSopTemplate template = templateMapper.selectAiAddwxSopTemplateById(aiAddwxTemplateId);
|
|
|
+ if (template == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 查询模板节点
|
|
|
+ List<AiAddwxSopTemplateNode> templateNodes = templateNodeMapper.selectAiAddwxSopTemplateNodeByTemplateId(aiAddwxTemplateId);
|
|
|
+ if (templateNodes == null || templateNodes.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Date now = new Date();
|
|
|
+ List<AiAddwxSopUserNode> allUserNodes = new ArrayList<>();
|
|
|
+ List<AiAddwxSopUserNodeRule> allUserNodeRules = new ArrayList<>();
|
|
|
+
|
|
|
+
|
|
|
+ for (QwExternalContact externalUser : externalUsers) {
|
|
|
+ QwUser qwUser = qwUserMap.get(externalUser.getQwUserId());
|
|
|
+ Long qwUserId = qwUser != null ? qwUser.getId() : null;
|
|
|
+
|
|
|
+ // 创建个人工作流
|
|
|
+ AiAddwxSopUserWorkflow userWorkflow = new AiAddwxSopUserWorkflow();
|
|
|
+ userWorkflow.setTemplateId(aiAddwxTemplateId);
|
|
|
+ userWorkflow.setCompanyUserId(externalUser.getCompanyUserId());
|
|
|
+ userWorkflow.setCompanyId(externalUser.getCompanyId());
|
|
|
+ userWorkflow.setQwExternalId(externalUser.getId());
|
|
|
+ userWorkflow.setQwUserId(qwUserId);
|
|
|
+ userWorkflow.setStatus(0);
|
|
|
+ userWorkflow.setDelFlag(0);
|
|
|
+ userWorkflow.setCreateTime(now);
|
|
|
+ userWorkflow.setUpdateTime(now);
|
|
|
+
|
|
|
+ userWorkflowMapper.insertAiAddwxSopUserWorkflow(userWorkflow);
|
|
|
+
|
|
|
+ // 为每个模板节点创建个人节点
|
|
|
+ for (AiAddwxSopTemplateNode templateNode : templateNodes) {
|
|
|
+ AiAddwxSopUserNode userNode = new AiAddwxSopUserNode();
|
|
|
+ userNode.setUserWorkflowId(userWorkflow.getUserWorkflowId());
|
|
|
+ userNode.setQwExternalId(externalUser.getId());
|
|
|
+ userNode.setQwUserId(qwUserId);
|
|
|
+ userNode.setTemplateNodeId(templateNode.getNodeId());
|
|
|
+ userNode.setNodeKey(templateNode.getNodeKey());
|
|
|
+ userNode.setNodeName(templateNode.getNodeName());
|
|
|
+ userNode.setNodeType(templateNode.getNodeType());
|
|
|
+ userNode.setPrevNodeId(templateNode.getPrevNodeId());
|
|
|
+ userNode.setNodeConfig(templateNode.getNodeConfig());
|
|
|
+ userNode.setIsValidReply(templateNode.getIsValidReply() != null && templateNode.getIsValidReply() ? 1 : 0);
|
|
|
+ userNode.setStatus(0);
|
|
|
+ userNode.setSortOrder(templateNode.getSortOrder());
|
|
|
+ userNode.setCreateTime(now);
|
|
|
+ userNode.setUpdateTime(now);
|
|
|
+ userNodeMapper.insertAiAddwxSopUserNode(userNode);
|
|
|
+ //加微节点更新用户工作流
|
|
|
+ if (userNode.getNodeType().equals(AiAddWechatSopNodeEnum.ADD_WECHAT.getCode())){
|
|
|
+ AiAddwxSopUserWorkflow aiAddwxSopUserWorkflow = new AiAddwxSopUserWorkflow();
|
|
|
+ aiAddwxSopUserWorkflow.setUserWorkflowId(userWorkflow.getUserWorkflowId()).
|
|
|
+ setCurrentNodeId(userNode.getUserNodeId())
|
|
|
+ .setCurrentNodeType(userNode.getNodeType())
|
|
|
+ .setCurrentNodeKey(userNode.getNodeKey());
|
|
|
+ userWorkflowMapper.updateById(aiAddwxSopUserWorkflow);
|
|
|
+ userWorkflow
|
|
|
+ .setCurrentNodeId(userNode.getUserNodeId())
|
|
|
+ .setCurrentNodeType(userNode.getNodeType())
|
|
|
+ .setCurrentNodeKey(userNode.getNodeKey());
|
|
|
+ }
|
|
|
+ allUserNodes.add(userNode);
|
|
|
+ // 加微节点直接发第一条rule的消息 todo
|
|
|
+ // 查询模板节点规则,生成个人节点规则(不配置send_time和send_day)
|
|
|
+ List<AiAddwxSopTemplateNodeRule> templateRules = templateNodeRuleMapper.selectAiAddwxSopTemplateNodeRuleByNodeId(templateNode.getNodeId());
|
|
|
+ if (templateRules != null && !templateRules.isEmpty()) {
|
|
|
+ for (AiAddwxSopTemplateNodeRule templateRule : templateRules) {
|
|
|
+
|
|
|
+ AiAddwxSopUserNodeRule userNodeRule = new AiAddwxSopUserNodeRule();
|
|
|
+ userNodeRule.setUserNodeId(userNode.getUserNodeId());
|
|
|
+ userNodeRule.setQwExternalId(externalUser.getId());
|
|
|
+ userNodeRule.setQwUserId(qwUserId);
|
|
|
+ userNodeRule.setRuleName(templateRule.getRuleName());
|
|
|
+ userNodeRule.setMsgType(templateRule.getMsgType());
|
|
|
+ userNodeRule.setContentType(templateRule.getContentType());
|
|
|
+ userNodeRule.setContentJson(templateRule.getContentJson());
|
|
|
+ userNodeRule.setSortOrder(templateRule.getSortOrder());
|
|
|
+ userNodeRule.setCreateTime(now);
|
|
|
+ userNodeRule.setUpdateTime(now);
|
|
|
+ userNodeRule.setSendDay(templateRule.getSendDay());
|
|
|
+ userNodeRule.setSendTime(templateRule.getSendTime());
|
|
|
+ if (templateNode.getNodeType().equals(AiAddWechatSopNodeEnum.ADD_WECHAT.getCode())){
|
|
|
+ if (templateRule.getSortOrder()==1){
|
|
|
+ // 计算 realSendTime: now + sendDay 天 + sendTime,限制在 9:00-18:00
|
|
|
+ // 获取当前时间
|
|
|
+ LocalDateTime nowL = LocalDateTime.now();
|
|
|
+
|
|
|
+ // 解析发送时间
|
|
|
+ String[] timeParts = userNodeRule.getSendTime().split(":");
|
|
|
+ int hour = Integer.parseInt(timeParts[0]);
|
|
|
+ int minute = Integer.parseInt(timeParts[1]);
|
|
|
+
|
|
|
+ // 构建目标时间:当前日期 + sendDay 天 + sendTime 时间
|
|
|
+ LocalDateTime targetTime = nowL.plusDays(userNodeRule.getSendDay())
|
|
|
+ .plusHours(hour)
|
|
|
+ .plusMinutes(minute).plusMinutes(1)
|
|
|
+ .withSecond(0)
|
|
|
+ .withNano(0);
|
|
|
+
|
|
|
+ // 业务规则:调整到 9:00 - 18:00 之间
|
|
|
+ int targetHour = targetTime.getHour();
|
|
|
+ if (targetHour < 9) {
|
|
|
+ targetTime = targetTime.withHour(9).withMinute(0);
|
|
|
+ } else if (targetHour >= 18) {
|
|
|
+ targetTime = targetTime.plusDays(1).withHour(9).withMinute(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转为 Date 类型(如果 userNodeRule.setRealSendTime 需要 Date)
|
|
|
+ userNodeRule.setRealSendTime(Date.from(targetTime.atZone(ZoneId.systemDefault()).toInstant()));
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ allUserNodeRules.add(userNodeRule);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 批量插入个人节点规则
|
|
|
+ if (!allUserNodeRules.isEmpty()) {
|
|
|
+ userNodeRuleMapper.batchInsertAiAddwxSopUserNodeRule(allUserNodeRules);
|
|
|
+ }
|
|
|
+ Map<String, Object> requestParam = new HashMap<>();
|
|
|
+
|
|
|
+ initAiChatParam(requestParam, userWorkflow,null,AiAddWechatSopNodeEnum.ADD_WECHAT.getDesc(),externalUser);
|
|
|
+
|
|
|
+ R r = callAiService(requestParam, ThreadLocalRandom.current().nextLong(100_000_000_000L, 999_999_999_999L + 1)
|
|
|
+ , CID_ADDWX_SOP_APPKEY);
|
|
|
+
|
|
|
+// System.out.println(r);
|
|
|
+ JSONObject content = extractContentJson(r);
|
|
|
+// System.out.println(content);
|
|
|
+ if (content != null) {
|
|
|
+ if (content.containsKey("aiContent")){
|
|
|
+ String sendWords = (String) content.get("aiContent");
|
|
|
+ // 新增fastgptchatsession新生成必须发第一条
|
|
|
+ qwHookNotifyAddMsgNew(qwUser,externalUser,sendWords);
|
|
|
+ AiAddwxSopUserNodeRule aiAddwxSopUserNodeRule = userNodeRuleMapper.selectOne(new LambdaQueryWrapper<AiAddwxSopUserNodeRule>()
|
|
|
+ .eq(AiAddwxSopUserNodeRule::getUserNodeId, userWorkflow.getCurrentNodeId())
|
|
|
+ .orderByAsc(AiAddwxSopUserNodeRule::getSortOrder).last("limit 1"));
|
|
|
+ AiAddwxSopUserNodeRule firstRUle = new AiAddwxSopUserNodeRule();
|
|
|
+ if (aiAddwxSopUserNodeRule != null)
|
|
|
+ firstRUle.setUserNodeRuleId(aiAddwxSopUserNodeRule.getUserNodeRuleId());
|
|
|
+ firstRUle.setContentJson(sendWords);
|
|
|
+ userNodeRuleMapper.updateById(firstRUle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ private static JSONObject extractContentJson(R result) {
|
|
|
+ try {
|
|
|
+ Object data = result.get("data");
|
|
|
+ if (data == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ String dataJson = JSON.toJSONString(data);
|
|
|
+ JSONObject dataObj = JSON.parseObject(dataJson);
|
|
|
+
|
|
|
+ JSONArray choices = dataObj.getJSONArray("choices");
|
|
|
+ if (choices == null || choices.isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONObject firstChoice = choices.getJSONObject(0);
|
|
|
+ JSONObject message = firstChoice.getJSONObject("message");
|
|
|
+ if (message == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ String content = message.getString("content");
|
|
|
+ if (content == null || content.trim().isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return JSON.parseObject(content);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.err.println("提取 content JSON 失败: " + e.getMessage());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final ObjectMapper mapper = new ObjectMapper();
|
|
|
+ public static R callAiService(Map<String, Object> requestParam, Long logId,String appKey) {
|
|
|
+ try {
|
|
|
+ String requestJson = mapper.writeValueAsString(requestParam);
|
|
|
+
|
|
|
+ ChatParam param = new ChatParam();
|
|
|
+ param.setChatId(logId.toString());
|
|
|
+ param.setStream(false);
|
|
|
+ param.setDetail(true);
|
|
|
+ ChatParam.Message message = new ChatParam.Message();
|
|
|
+ List<ChatParam.Message> messageList = new ArrayList<ChatParam.Message>();
|
|
|
+ message.setContent(requestJson);
|
|
|
+ message.setRole("user");
|
|
|
+ messageList.add(message);
|
|
|
+ param.setMessages(messageList);
|
|
|
+ ChatService chatService = SpringUtils.getBean(ChatService.class);
|
|
|
+ AiHostProper aiHost = SpringUtils.getBean(AiHostProper.class);
|
|
|
+
|
|
|
+ return chatService.initiatingTakeChat(param, aiHost.getAiApiV3(), appKey);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("AI服务调用失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private void initAiChatParam(Map<String, Object> requestParam, AiAddwxSopUserWorkflow workflow, FastGptChatSession session, String nodeTypeE, QwExternalContact externalUser) {
|
|
|
+ // 1. 构建 userInfo
|
|
|
+ Map<String, Object> userInfo = new HashMap<>();
|
|
|
+ userInfo.put("姓名", externalUser.getName()!=null?externalUser.getName():"");
|
|
|
+ userInfo.put("微信昵称", externalUser.getRemark() != null ? externalUser.getRemark() : "");
|
|
|
+ userInfo.put("联系方式", "");
|
|
|
+ userInfo.put("性别", externalUser.getGender()==1?"男":externalUser.getGender()==2?"女":"未知");
|
|
|
+ userInfo.put("收货地址", "");
|
|
|
+ userInfo.put("状态", "");
|
|
|
+ userInfo.put("当前阶段", nodeTypeE);
|
|
|
+
|
|
|
+ // 查询下一阶段(下一节点的类型)
|
|
|
+ StringBuilder nextStages = new StringBuilder();
|
|
|
+ List<AiAddwxSopUserNode> allNodes = userNodeMapper.selectAiAddwxSopUserNodeByWorkflowId(workflow.getUserWorkflowId());
|
|
|
+ AiAddwxSopUserNode currentNode = allNodes.stream().filter(node -> node.getUserNodeId().equals(workflow.getCurrentNodeId())).findFirst().orElse(null);
|
|
|
+ if (allNodes != null && workflow.getCurrentNodeId() != null && currentNode != null) {
|
|
|
+ for (AiAddwxSopUserNode node : allNodes) {
|
|
|
+ if (currentNode.getTemplateNodeId().equals(node.getPrevNodeId())) {
|
|
|
+ if (nextStages.length() > 0) {
|
|
|
+ nextStages.append("|");
|
|
|
+ }
|
|
|
+ AiAddWechatSopNodeEnum nextType = AiAddWechatSopNodeEnum.fromCode(node.getNodeType());
|
|
|
+ nextStages.append(nextType != null ? nextType.getDesc() : node.getNodeType());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ userInfo.put("下一阶段", nextStages.toString());
|
|
|
+ requestParam.put("userInfo", userInfo);
|
|
|
+ // 2. 构建 history
|
|
|
+ List<Map<String, String>> history = new ArrayList<>();
|
|
|
+ String userContent = "";
|
|
|
+ if (session != null) {
|
|
|
+ List<FastGptChatMsg> msgs = fastGptChatMsgMapper.selectFastGptChatMsgByMsgSessionIdAndExtId(session.getSessionId(), String.valueOf(workflow.getQwExternalId()));
|
|
|
+ if (msgs != null) {
|
|
|
+ for (FastGptChatMsg msg : msgs) {
|
|
|
+ Map<String, String> item = new HashMap<>();
|
|
|
+ item.put("role", msg.getSendType() != null && msg.getSendType() == 1 ? "user" : "ai");
|
|
|
+ item.put("content", msg.getContent());
|
|
|
+ history.add(item);
|
|
|
+ }
|
|
|
+ // 取最后一条用户消息作为 userContent
|
|
|
+ for (FastGptChatMsg msg : msgs) {
|
|
|
+ if (msg.getSendType() != null && msg.getSendType() == 1) {
|
|
|
+ userContent = msg.getContent();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ requestParam.put("history", history);
|
|
|
+ requestParam.put("userContent", userContent);
|
|
|
+
|
|
|
+ // 3. knowledgeBase
|
|
|
+ ArrayList<Object> knowledgeBase = new ArrayList<>();
|
|
|
+// AiAddwxSopUserNodeRule currentRule = aiAddwxSopUserNodeRuleMapper.selectOne(new LambdaQueryWrapper<AiAddwxSopUserNodeRule>()
|
|
|
+// .eq(AiAddwxSopUserNodeRule::getUserNodeId, workflow.getCurrentNodeId()).eq(AiAddwxSopUserNodeRule::getIsSent, 0).orderByAsc(AiAddwxSopUserNodeRule::getSortOrder).last("limit 1"));
|
|
|
+// if (currentRule != null){
|
|
|
+// JSONObject rule = JSON.parseObject(currentRule.getContentJson());
|
|
|
+// if (rule.get("prompt")!=null){
|
|
|
+// knowledgeBase.add(rule.get("prompt"));
|
|
|
+// }
|
|
|
+// }
|
|
|
+ requestParam.put("knowledgeBase", knowledgeBase);
|
|
|
+ }
|
|
|
+ private void qwHookNotifyAddMsgNew(QwUser sendUser,QwExternalContact qwExternalContacts,String count) {
|
|
|
+ if (sendUser!=null){
|
|
|
+ if (qwExternalContacts==null){
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ FastGptChatSession fastGptChatSession = fastGptChatSessionMapper.selectFastGptChatSessionByQwExternalContactsAndUserId(qwExternalContacts.getId(), sendUser.getId());
|
|
|
+ if (fastGptChatSession==null){
|
|
|
+ if(qwExternalContacts.getType()!=null&&qwExternalContacts.getType()==1){
|
|
|
+ if(sendUser.getFastGptRoleId()!=null){
|
|
|
+ fastGptChatSession = new FastGptChatSession();
|
|
|
+ String chatId = UUID.randomUUID().toString();
|
|
|
+ fastGptChatSession.setChatId(chatId);
|
|
|
+ fastGptChatSession.setKfId(sendUser.getFastGptRoleId().toString());
|
|
|
+ fastGptChatSession.setStatus(1);
|
|
|
+ fastGptChatSession.setRemindCount(0);
|
|
|
+ fastGptChatSession.setRemindStatus(0);
|
|
|
+ fastGptChatSession.setCreateTime(new Date());
|
|
|
+ fastGptChatSession.setQwExtId(qwExternalContacts.getId());
|
|
|
+ fastGptChatSession.setQwUserId(sendUser.getId());
|
|
|
+ fastGptChatSession.setIsArtificial(0);
|
|
|
+ fastGptChatSession.setAvatar(qwExternalContacts.getAvatar());
|
|
|
+ fastGptChatSession.setNickName(qwExternalContacts.getName());
|
|
|
+ fastGptChatSession.setCompanyId(sendUser.getCompanyId());
|
|
|
+ fastGptChatSession.setLastTime(new Date());
|
|
|
+ fastGptChatSession.setIsReply(0);
|
|
|
+ fastGptChatSessionMapper.insertFastGptChatSession(fastGptChatSession);
|
|
|
+ saveQwUserMsg(fastGptChatSession,2,count,sendUser);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private void saveQwUserMsg(FastGptChatSession fastGptChatSession,Integer sendType,String content,QwUser sendUser) {
|
|
|
+ content = replaceWxEmo(content);
|
|
|
+ if(content.isEmpty()){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ FastGptChatMsg fastGptChatMsgAi = new FastGptChatMsg();
|
|
|
+ fastGptChatMsgAi.setContent(content);
|
|
|
+ fastGptChatMsgAi.setSessionId(fastGptChatSession.getSessionId());
|
|
|
+ fastGptChatMsgAi.setRoleId(Long.parseLong(fastGptChatSession.getKfId()));
|
|
|
+ fastGptChatMsgAi.setSendType(sendType);
|
|
|
+ fastGptChatMsgAi.setCompanyId(fastGptChatSession.getCompanyId());
|
|
|
+ fastGptChatMsgAi.setCompanyUserId(sendUser.getCompanyUserId());
|
|
|
+ fastGptChatMsgAi.setUserId(fastGptChatSession.getUserId());
|
|
|
+ fastGptChatMsgAi.setUserType(1);
|
|
|
+ fastGptChatMsgAi.setMsgType(1);
|
|
|
+ fastGptChatMsgAi.setStatus(0);
|
|
|
+ fastGptChatMsgAi.setAvatar(fastGptChatSession.getAvatar());
|
|
|
+ fastGptChatMsgAi.setNickName(fastGptChatSession.getNickName());
|
|
|
+ fastGptChatMsgAi.setCreateTime(new Date());
|
|
|
+ fastGptChatMsgAi.setExtId(fastGptChatSession.getQwExtId()+"");
|
|
|
+ fastGptChatMsgService.insertFastGptChatMsg(fastGptChatMsgAi);
|
|
|
+ log.info("新增消息:"+fastGptChatMsgAi);
|
|
|
+ }
|
|
|
+ /** 过滤[] **/
|
|
|
+ private static String replaceWxEmo(String s){
|
|
|
+
|
|
|
+ if(org.springframework.util.StringUtils.isEmpty(s)) return "";
|
|
|
+ // 替换匹配到的内容
|
|
|
+ String text = s.replaceAll("\\[.*?]", "").trim();
|
|
|
+ return EmojiParser.removeAllEmojis(text);
|
|
|
+ }
|
|
|
+}
|