|
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.fs.common.constant.Constants;
|
|
import com.fs.common.constant.Constants;
|
|
|
import com.fs.common.core.redis.RedisCacheT;
|
|
import com.fs.common.core.redis.RedisCacheT;
|
|
|
|
|
+import com.fs.common.utils.StringUtils;
|
|
|
import com.fs.common.utils.spring.SpringUtils;
|
|
import com.fs.common.utils.spring.SpringUtils;
|
|
|
import com.fs.company.domain.*;
|
|
import com.fs.company.domain.*;
|
|
|
import com.fs.company.mapper.CompanyWxClientMapper;
|
|
import com.fs.company.mapper.CompanyWxClientMapper;
|
|
@@ -11,6 +12,7 @@ import com.fs.company.mapper.CompanyWorkflowNodeMapper;
|
|
|
import com.fs.company.param.ExecutionContext;
|
|
import com.fs.company.param.ExecutionContext;
|
|
|
import com.fs.company.service.IWorkflowNode;
|
|
import com.fs.company.service.IWorkflowNode;
|
|
|
import com.fs.company.vo.AiAddWxWorkflowConditionVo;
|
|
import com.fs.company.vo.AiAddWxWorkflowConditionVo;
|
|
|
|
|
+import com.fs.company.vo.AiCallWorkflowConditionVo;
|
|
|
import com.fs.company.vo.ExecutionResult;
|
|
import com.fs.company.vo.ExecutionResult;
|
|
|
import com.fs.enums.ExecutionStatusEnum;
|
|
import com.fs.enums.ExecutionStatusEnum;
|
|
|
import com.fs.enums.NodeTypeEnum;
|
|
import com.fs.enums.NodeTypeEnum;
|
|
@@ -20,6 +22,7 @@ import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* @author MixLiu
|
|
* @author MixLiu
|
|
@@ -65,31 +68,37 @@ public class AiAddWxTaskNode extends AbstractWorkflowNode {
|
|
|
|
|
|
|
|
// 判断加微是否成功 (isAdd: 0否 1是 2待添加 3作废)
|
|
// 判断加微是否成功 (isAdd: 0否 1是 2待添加 3作废)
|
|
|
boolean addSuccess = wxClient != null && Integer.valueOf(1).equals(wxClient.getIsAdd());
|
|
boolean addSuccess = wxClient != null && Integer.valueOf(1).equals(wxClient.getIsAdd());
|
|
|
-
|
|
|
|
|
|
|
+ //回调加微成功
|
|
|
if (addSuccess) {
|
|
if (addSuccess) {
|
|
|
|
|
+ List<CompanyWorkflowEdge> cList = edges.stream().filter(a ->
|
|
|
|
|
+ StringUtils.isNotBlank(a.getConditionExpr()) && JSONObject.parseArray(a.getConditionExpr(), AiCallWorkflowConditionVo.class).get(0).isAdd())
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ if(null != cList && !cList.isEmpty() && nodeKey.equals(exec.getCurrentNodeKey())){
|
|
|
|
|
+ super.runNextNode(context, cList.get(0));
|
|
|
|
|
+ }
|
|
|
// 加微成功,设置为等待状态,等待下一次回调
|
|
// 加微成功,设置为等待状态,等待下一次回调
|
|
|
- log.info("加微成功,设置工作流为等待状态 - workflowInstanceId: {}", context.getWorkflowInstanceId());
|
|
|
|
|
- super.asyncWorkflowForBlockingNode(context.getWorkflowInstanceId(), context.getCurrentNodeKey(),
|
|
|
|
|
- context, ExecutionStatusEnum.WAITING);
|
|
|
|
|
- return ExecutionResult.waiting().nextNodeKey("").build();
|
|
|
|
|
|
|
+// log.info("加微成功,设置工作流为等待状态 - workflowInstanceId: {}", context.getWorkflowInstanceId());
|
|
|
|
|
+// super.asyncWorkflowForBlockingNode(context.getWorkflowInstanceId(), context.getCurrentNodeKey(),
|
|
|
|
|
+// context, ExecutionStatusEnum.WAITING);
|
|
|
|
|
+// return ExecutionResult.waiting().nextNodeKey("").build();
|
|
|
} else {
|
|
} else {
|
|
|
|
|
+ List<CompanyWorkflowEdge> cList = edges.stream().filter(a ->
|
|
|
|
|
+ StringUtils.isNotBlank(a.getConditionExpr()) && !JSONObject.parseArray(a.getConditionExpr(), AiCallWorkflowConditionVo.class).get(0).isAdd())
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
// 加微失败,根据条件判断走哪条边
|
|
// 加微失败,根据条件判断走哪条边
|
|
|
- for (CompanyWorkflowEdge edge : edges) {
|
|
|
|
|
- if (edge.getConditionExpr() == null || edge.getConditionExpr().isEmpty()) {
|
|
|
|
|
- continue; // 跳过无条件边
|
|
|
|
|
- }
|
|
|
|
|
- AiAddWxWorkflowConditionVo condition = JSONObject.parseObject(edge.getConditionExpr(), AiAddWxWorkflowConditionVo.class);
|
|
|
|
|
|
|
+ CompanyWorkflowEdge edge = cList.get(0);
|
|
|
|
|
+ AiCallWorkflowConditionVo condition = JSONObject.parseObject(edge.getConditionExpr(), AiCallWorkflowConditionVo.class);
|
|
|
// 匹配失败条件
|
|
// 匹配失败条件
|
|
|
- if (!condition.isAddSuccess()) {
|
|
|
|
|
|
|
+ if (!condition.isAdd()) {
|
|
|
log.info("加微失败,执行失败分支 - workflowInstanceId: {}", context.getWorkflowInstanceId());
|
|
log.info("加微失败,执行失败分支 - workflowInstanceId: {}", context.getWorkflowInstanceId());
|
|
|
this.runNextNode(context, edge);
|
|
this.runNextNode(context, edge);
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
log.error("加微失败但未找到失败分支 - workflowInstanceId: {}", context.getWorkflowInstanceId());
|
|
log.error("加微失败但未找到失败分支 - workflowInstanceId: {}", context.getWorkflowInstanceId());
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
|
|
+ return null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -101,66 +110,70 @@ public class AiAddWxTaskNode extends AbstractWorkflowNode {
|
|
|
@Override
|
|
@Override
|
|
|
protected ExecutionResult doExecute(ExecutionContext context) {
|
|
protected ExecutionResult doExecute(ExecutionContext context) {
|
|
|
if (!isAsync()) {
|
|
if (!isAsync()) {
|
|
|
- return ExecutionResult.failure().nextNodeKey("").build();
|
|
|
|
|
|
|
+ return ExecutionResult.failure().nextNodeKey(null).build();
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
try {
|
|
try {
|
|
|
- // 1. 获取业务数据
|
|
|
|
|
- CompanyVoiceRoboticBusiness business = super.getRoboticBusiness(context.getWorkflowInstanceId());
|
|
|
|
|
- if (business == null) {
|
|
|
|
|
- return ExecutionResult.failure().errorMessage("未找到业务数据").build();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 2. 通过 wxClientId 获取加微客户记录
|
|
|
|
|
- Long wxClientId = business.getWxClientId();
|
|
|
|
|
- if (wxClientId == null) {
|
|
|
|
|
- return ExecutionResult.failure().errorMessage("业务数据中缺少wxClientId").build();
|
|
|
|
|
- }
|
|
|
|
|
- CompanyWxClient wxClient = companyWxClientMapper.selectById(wxClientId);
|
|
|
|
|
- if (wxClient == null) {
|
|
|
|
|
- return ExecutionResult.failure().errorMessage("未找到加微客户记录: " + wxClientId).build();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 3. 验证加微数据是否已准备好
|
|
|
|
|
- Long accountId = wxClient.getAccountId();
|
|
|
|
|
- if (accountId == null) {
|
|
|
|
|
- return ExecutionResult.failure().errorMessage("加微客户记录中缺少accountId,请先分配微信账号").build();
|
|
|
|
|
- }
|
|
|
|
|
- Long dialogId = wxClient.getDialogId();
|
|
|
|
|
- if (dialogId == null) {
|
|
|
|
|
- return ExecutionResult.failure().errorMessage("加微客户记录中缺少dialogId,请先设置话术").build();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 4. 确保 isAdd = 0(未添加状态),这样定时任务才会处理
|
|
|
|
|
- if (!Integer.valueOf(0).equals(wxClient.getIsAdd())) {
|
|
|
|
|
- log.warn("加微客户记录状态不是未添加(0),当前状态: {} - wxClientId: {}", wxClient.getIsAdd(), wxClientId);
|
|
|
|
|
- if (Integer.valueOf(1).equals(wxClient.getIsAdd())) {
|
|
|
|
|
- return ExecutionResult.failure().errorMessage("该客户已加微成功,无需重复添加").build();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- Long roboticId = business.getRoboticId();
|
|
|
|
|
- log.info("准备加微任务数据 - workflowInstanceId: {}, roboticId: {}, wxClientId: {}, accountId: {}",
|
|
|
|
|
- context.getWorkflowInstanceId(), roboticId, wxClientId, accountId);
|
|
|
|
|
-
|
|
|
|
|
- // 5. 设置 Redis 任务状态为 ADD_WX,让定时任务执行加微
|
|
|
|
|
- String taskKey = Constants.TASK_ID + roboticId;
|
|
|
|
|
- redisCache.setCacheObject(taskKey, Constants.ADD_WX);
|
|
|
|
|
- log.info("设置任务状态为加微 - key: {}, value: {}", taskKey, Constants.ADD_WX);
|
|
|
|
|
-
|
|
|
|
|
- // 6. 设置加微超时检测时间到 Redis
|
|
|
|
|
- int timeoutMinutes = getTimeoutFromProperties();
|
|
|
|
|
- long timeoutTimestamp = System.currentTimeMillis() + timeoutMinutes * 60 * 1000L;
|
|
|
|
|
- String timeoutKey = Constants.WORKFLOW_ADD_WX_TIMEOUT + context.getWorkflowInstanceId() + ":" + wxClientId;
|
|
|
|
|
- redisCache.setCacheObject(timeoutKey, String.valueOf(timeoutTimestamp));
|
|
|
|
|
- log.info("设置加微超时检测 - key: {}, timeout: {}分钟, 超时时间戳: {}",
|
|
|
|
|
- timeoutKey, timeoutMinutes, timeoutTimestamp);
|
|
|
|
|
-
|
|
|
|
|
- // 7. 设置工作流为暂停状态,等待加微回调
|
|
|
|
|
super.asyncWorkflowForBlockingNode(context.getWorkflowInstanceId(), context.getCurrentNodeKey(), context, ExecutionStatusEnum.PAUSED);
|
|
super.asyncWorkflowForBlockingNode(context.getWorkflowInstanceId(), context.getCurrentNodeKey(), context, ExecutionStatusEnum.PAUSED);
|
|
|
|
|
+ return ExecutionResult.paused()
|
|
|
|
|
+ .outputData(context.getVariables())
|
|
|
|
|
+ .nextNodeKey("").build();
|
|
|
|
|
|
|
|
- // 8. 返回 paused 状态,nextNodeKey 为空字符串(不自动流转)
|
|
|
|
|
- return ExecutionResult.paused().nextNodeKey("").build();
|
|
|
|
|
|
|
+// // 1. 获取业务数据
|
|
|
|
|
+// CompanyVoiceRoboticBusiness business = super.getRoboticBusiness(context.getWorkflowInstanceId());
|
|
|
|
|
+// if (business == null) {
|
|
|
|
|
+// return ExecutionResult.failure().errorMessage("未找到业务数据").build();
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 2. 通过 wxClientId 获取加微客户记录
|
|
|
|
|
+// Long wxClientId = business.getWxClientId();
|
|
|
|
|
+// if (wxClientId == null) {
|
|
|
|
|
+// return ExecutionResult.failure().errorMessage("业务数据中缺少wxClientId").build();
|
|
|
|
|
+// }
|
|
|
|
|
+// CompanyWxClient wxClient = companyWxClientMapper.selectById(wxClientId);
|
|
|
|
|
+// if (wxClient == null) {
|
|
|
|
|
+// return ExecutionResult.failure().errorMessage("未找到加微客户记录: " + wxClientId).build();
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 3. 验证加微数据是否已准备好
|
|
|
|
|
+// Long accountId = wxClient.getAccountId();
|
|
|
|
|
+// if (accountId == null) {
|
|
|
|
|
+// return ExecutionResult.failure().errorMessage("加微客户记录中缺少accountId,请先分配微信账号").build();
|
|
|
|
|
+// }
|
|
|
|
|
+// Long dialogId = wxClient.getDialogId();
|
|
|
|
|
+// if (dialogId == null) {
|
|
|
|
|
+// return ExecutionResult.failure().errorMessage("加微客户记录中缺少dialogId,请先设置话术").build();
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 4. 确保 isAdd = 0(未添加状态),这样定时任务才会处理
|
|
|
|
|
+// if (!Integer.valueOf(0).equals(wxClient.getIsAdd())) {
|
|
|
|
|
+// log.warn("加微客户记录状态不是未添加(0),当前状态: {} - wxClientId: {}", wxClient.getIsAdd(), wxClientId);
|
|
|
|
|
+// if (Integer.valueOf(1).equals(wxClient.getIsAdd())) {
|
|
|
|
|
+// return ExecutionResult.failure().errorMessage("该客户已加微成功,无需重复添加").build();
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// Long roboticId = business.getRoboticId();
|
|
|
|
|
+// log.info("准备加微任务数据 - workflowInstanceId: {}, roboticId: {}, wxClientId: {}, accountId: {}",
|
|
|
|
|
+// context.getWorkflowInstanceId(), roboticId, wxClientId, accountId);
|
|
|
|
|
+//
|
|
|
|
|
+// // 5. 设置 Redis 任务状态为 ADD_WX,让定时任务执行加微
|
|
|
|
|
+// String taskKey = getDelayAddWxKeyPrefix() Constants.TASK_ID + roboticId;
|
|
|
|
|
+// redisCache.setCacheObject(taskKey, Constants.ADD_WX);
|
|
|
|
|
+// log.info("设置任务状态为加微 - key: {}, value: {}", taskKey, Constants.ADD_WX);
|
|
|
|
|
+//
|
|
|
|
|
+// // 6. 设置加微超时检测时间到 Redis
|
|
|
|
|
+// int timeoutMinutes = getTimeoutFromProperties();
|
|
|
|
|
+// long timeoutTimestamp = System.currentTimeMillis() + timeoutMinutes * 60 * 1000L;
|
|
|
|
|
+// String timeoutKey = Constants.WORKFLOW_ADD_WX_TIMEOUT + context.getWorkflowInstanceId() + ":" + wxClientId;
|
|
|
|
|
+// redisCache.setCacheObject(timeoutKey, String.valueOf(timeoutTimestamp));
|
|
|
|
|
+// log.info("设置加微超时检测 - key: {}, timeout: {}分钟, 超时时间戳: {}",
|
|
|
|
|
+// timeoutKey, timeoutMinutes, timeoutTimestamp);
|
|
|
|
|
+//
|
|
|
|
|
+// // 7. 设置工作流为暂停状态,等待加微回调
|
|
|
|
|
+// super.asyncWorkflowForBlockingNode(context.getWorkflowInstanceId(), context.getCurrentNodeKey(), context, ExecutionStatusEnum.PAUSED);
|
|
|
|
|
+//
|
|
|
|
|
+// // 8. 返回 paused 状态,nextNodeKey 为空字符串(不自动流转)
|
|
|
|
|
+// return ExecutionResult.paused().nextNodeKey("").build();
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.error("准备加微任务数据异常 - workflowInstanceId: {}", context.getWorkflowInstanceId(), e);
|
|
log.error("准备加微任务数据异常 - workflowInstanceId: {}", context.getWorkflowInstanceId(), e);
|
|
@@ -180,8 +193,9 @@ public class AiAddWxTaskNode extends AbstractWorkflowNode {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 运行下一个节点
|
|
* 运行下一个节点
|
|
|
|
|
+ *
|
|
|
* @param context 执行上下文
|
|
* @param context 执行上下文
|
|
|
- * @param edge 边
|
|
|
|
|
|
|
+ * @param edge 边
|
|
|
*/
|
|
*/
|
|
|
@Override
|
|
@Override
|
|
|
protected void runNextNode(ExecutionContext context, CompanyWorkflowEdge edge) {
|
|
protected void runNextNode(ExecutionContext context, CompanyWorkflowEdge edge) {
|
|
@@ -224,7 +238,7 @@ public class AiAddWxTaskNode extends AbstractWorkflowNode {
|
|
|
* 如果返回 false 表示已经被其他路径执行过了,不再执行
|
|
* 如果返回 false 表示已经被其他路径执行过了,不再执行
|
|
|
*
|
|
*
|
|
|
* @param workflowInstanceId 工作流实例ID
|
|
* @param workflowInstanceId 工作流实例ID
|
|
|
- * @param wxClientId 加微客户ID
|
|
|
|
|
|
|
+ * @param wxClientId 加微客户ID
|
|
|
* @return 是否可以执行
|
|
* @return 是否可以执行
|
|
|
*/
|
|
*/
|
|
|
public static boolean tryMarkAsExecuted(String workflowInstanceId, Long wxClientId) {
|
|
public static boolean tryMarkAsExecuted(String workflowInstanceId, Long wxClientId) {
|
|
@@ -244,7 +258,7 @@ public class AiAddWxTaskNode extends AbstractWorkflowNode {
|
|
|
* 清除超时检测 Key
|
|
* 清除超时检测 Key
|
|
|
*
|
|
*
|
|
|
* @param workflowInstanceId 工作流实例ID
|
|
* @param workflowInstanceId 工作流实例ID
|
|
|
- * @param wxClientId 加微客户ID
|
|
|
|
|
|
|
+ * @param wxClientId 加微客户ID
|
|
|
*/
|
|
*/
|
|
|
public static void clearTimeoutKey(String workflowInstanceId, Long wxClientId) {
|
|
public static void clearTimeoutKey(String workflowInstanceId, Long wxClientId) {
|
|
|
String timeoutKey = Constants.WORKFLOW_ADD_WX_TIMEOUT + workflowInstanceId + ":" + wxClientId;
|
|
String timeoutKey = Constants.WORKFLOW_ADD_WX_TIMEOUT + workflowInstanceId + ":" + wxClientId;
|
|
@@ -265,4 +279,38 @@ public class AiAddWxTaskNode extends AbstractWorkflowNode {
|
|
|
}
|
|
}
|
|
|
return String.format(DELAY_ADD_WX_KEY, nowDay.getHours(), nowDay.getMinutes());
|
|
return String.format(DELAY_ADD_WX_KEY, nowDay.getHours(), nowDay.getMinutes());
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 完成加微动作
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param workflowInstanceId
|
|
|
|
|
+ */
|
|
|
|
|
+ public void doneAddwx(String workflowInstanceId) {
|
|
|
|
|
+ ExecutionContext context = createExecutionContext(workflowInstanceId, nodeKey);
|
|
|
|
|
+ context.setVariable("lastNodeKey", nodeKey);
|
|
|
|
|
+ //启动定时节点倒计时
|
|
|
|
|
+ CompanyAiWorkflowExec exec = companyAiWorkflowExecMapper.selectByWorkflowInstanceId(context.getWorkflowInstanceId());
|
|
|
|
|
+ if (!exec.getCurrentNodeKey().equals(nodeKey)) {
|
|
|
|
|
+ //当前节点已流转
|
|
|
|
|
+ log.error("当前节点已流转 ,目标:{},实际:{}", nodeKey, exec.getCurrentNodeKey());
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ List<CompanyWorkflowEdge> edges = companyWorkflowEdgeMapper.selectListByWorkflowIdAndNodeKey(exec.getWorkflowId(), nodeKey);
|
|
|
|
|
+ edges.forEach(edge -> {
|
|
|
|
|
+ List<AiCallWorkflowConditionVo> conditions = JSONObject.parseArray(edge.getConditionExpr(), AiCallWorkflowConditionVo.class);
|
|
|
|
|
+ if (null == conditions || conditions.isEmpty()) {
|
|
|
|
|
+ super.runNextNode(context, edge);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ AiCallWorkflowConditionVo condition = conditions.get(0);
|
|
|
|
|
+ //节点包含延时条件
|
|
|
|
|
+ if (null != condition.getAddTime() && !condition.isAdd()) {
|
|
|
|
|
+ long l = System.currentTimeMillis() + condition.getAddTime() * 60 * 1000;
|
|
|
|
|
+ String redisKey = getDelayAddWxKeyPrefix(l) + workflowInstanceId;
|
|
|
|
|
+ ExecutionContext nextContext = context.clone();
|
|
|
|
|
+ nextContext.setCurrentNodeKey(edge.getTargetNodeKey());
|
|
|
|
|
+ super.redisCache.setCacheObject(redisKey, nextContext);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|