using System.Text.RegularExpressions;
using Common;
using Feign;
using Infrastructure;
using LitJson;
using Mapster;
using Model;
using Model.Custom;
using Model.Source;
using Services;
namespace Util.Logic
{
public class LogicHelper
{
///
/// 获取逻辑项目的Json数据
///
/// 项目ID
/// 请求参数
public static Dictionary DoLogic(int projectId, string requestId, string env, string request, int nodeKind = 1)
{
Dictionary result = new Dictionary();
LogicProject logicProject = new LogicProject();
if (nodeKind == 1)
{
var logicProjectService = App.GetService();
logicProject = logicProjectService.GetById(projectId);
}
else if (nodeKind == 2)
{
var testProjectService = App.GetService();
logicProject = testProjectService.GetById(projectId).Adapt();
}
else if (nodeKind == 3)
{
var serverProjectService = App.GetService();
logicProject = serverProjectService.GetById(projectId).Adapt();
}
if(logicProject == null)
{
return new Dictionary();
}
List logDic = new List();
try
{
// 记录日志
logDic.Add(new LogItem()
{
title = "开始节点" + env,
param = new Dictionary()
{
{ "请求参数", request },
{ "项目ID", projectId },
{ "请求ID", requestId },
}
});
var logicLogRecordService = App.GetService();
var logId = logicLogRecordService.addLogicLogRecord(new LogicLogRecord()
{
createTime = DateTime.Now,
requestId = requestId,
requestParam = request,
logicProjectName = logicProject.projectName,
logicId = logicProject.id,
});
// var logRecord = logicLogRecordService.getLogicLogRecordQuery(new LogicLogRecord(){ id = logId });
string jsonData = logicProject.setData ?? string.Empty;
if(string.IsNullOrEmpty(jsonData))
{
return new Dictionary();
}
JsonData requestObj = JsonMapper.ToObject(request);
JsonData jsonDataObj = JsonMapper.ToObject(jsonData);
JsonData nodes = jsonDataObj["nodes"]; // 节点数据
List nodeList = new List(); // 节点列表
foreach(JsonData node in nodes)
{
JsonData id = node["id"];
JsonData type = node["type"];
NodeList nodeListObj = new NodeList();
nodeListObj.nodeId = id.ToString();
nodeListObj.nodeType = type.ToString();
nodeListObj.nodeData = node;
nodeList.Add(nodeListObj);
}
List edgeList = new List(); // 边列表
JsonData edges = jsonDataObj["edges"]; // 边数据
foreach(JsonData edge in edges)
{
JsonData source = edge["source"];
JsonData target = edge["target"];
JsonData edgeId = edge["id"];
EdgeList edgeListObj = new EdgeList();
edgeListObj.source = source.ToString();
edgeListObj.target = target.ToString();
edgeListObj.id = edgeId.ToString();
edgeListObj.edgeData = edge;
edgeList.Add(edgeListObj);
}
string startNodeId = "start"; // 起始节点ID
// 获取起始节点数据
List paramList = new List();
NodeList startNode = nodeList.FirstOrDefault(x => x.nodeId == startNodeId) ?? new NodeList();
JsonData nodeData = startNode.nodeData;
JsonData input = nodeData["data"]["formData"]["input"]["value"];
for(int i = 0; i < input.Count; i++)
{
JsonData item = input[i];
string paramName = item["label"].ToString();
string paramType = item["type"][0].ToString();
string paramValue = requestObj[paramName].ToString();
ParamList paramListObj = new ParamList();
paramListObj.nodeId = startNodeId;
paramListObj.paramName = paramName;
paramListObj.paramType = paramType;
paramListObj.paramValue = paramValue;
paramListObj.paramAttribute = "startinput";
paramList.Add(paramListObj);
}
//获取数据库信息
List dbIdValues = LitJsonHelper.FindAllValuesByKey(jsonDataObj, "dbId");
if(dbIdValues.Count > 0) dbIdValues = dbIdValues.Where(m => !string.IsNullOrEmpty(m)).Distinct().ToList();
List dbTableIdValues = LitJsonHelper.FindAllValuesByKey(jsonDataObj, "dbTableId");
if(dbTableIdValues.Count > 0) dbTableIdValues = dbTableIdValues.Where(m => !string.IsNullOrEmpty(m)).Distinct().ToList();
string dbIdList = string.Join(",", dbIdValues);
List databaseInfos = ISource.getDatabaseInfoListByIds(dbIdList);
// 获取数据库表信息
string dbTableIdList = string.Join(",", dbTableIdValues);
List tables = ISource.getDatabaseTableListByIds(dbTableIdList);
// 从起始节点开始
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, startNodeId, new Dictionary(), logDic, env);
// 返回结果
foreach(ParamList item in paramList.Where(m => m.paramAttribute == "endoutput").ToList())
{
result.Add(item.paramName, item.paramValue);
}
startNodeId = "end"; // 起始节点ID
// 获取起始节点数据
startNode = nodeList.FirstOrDefault(x => x.nodeId == startNodeId) ?? new NodeList();
nodeData = startNode.nodeData;
input = nodeData["data"]["formData"]["output"]["value"];
for(int i = 0; i < input.Count; i++)
{
JsonData item = input[i];
string paramName = item["label"].ToString();
string paramType = item["type"][0].ToString();
string paramValue = item["value"].ToString();
if (paramValue.Contains('.'))
{
string nodeId = paramValue.Substring(0, paramValue.IndexOf(":"));
paramValue = paramValue.Substring(paramValue.LastIndexOf(".") + 1);
var paramData = paramList.FirstOrDefault(x => x.paramName == paramValue && x.nodeId == nodeId);
if (paramData != null)
{
paramValue = paramData.paramValueTransfer;
}
}
result.Add(paramName, paramValue);
}
string logPath = "/logRecord/";
string logString = JsonMapper.ToJson(logDic);
logString = UnicodeToChinese(logString);
Function.WritePage(logPath, requestId + ".json", logString);
OssHelper.Instance.Upload(Function.getPath(logPath + requestId + ".json"));
// logRecord.logicLogFilePath = logPath + requestId + ".json";
// logicLogRecordService.updateLogicLogRecord(logRecord);
}
catch(Exception ex)
{
RedisServer.Cache.Set("logic_error_" + requestId, ex.ToString());
RedisServer.Cache.Set("logic_log_" + requestId, JsonMapper.ToJson(logDic));
// Function.WriteLog(ex.ToString(), "逻辑异常");
Utils.WriteLog(ex.ToString(), "逻辑异常");
try
{
logDic.Add(new LogItem()
{
title = "error",
detail = ex.ToString(),
});
string logPath = "/logRecord/";
string logString = JsonMapper.ToJson(logDic);
logString = UnicodeToChinese(logString);
Function.WritePage(logPath, requestId + ".json", logString);
OssHelper.Instance.Upload(Function.getPath(logPath + requestId + ".json"));
} catch
{
}
}
try
{
Task.Run(async () =>
{
await Task.Delay(1000);
// 延迟后执行查询/补偿逻辑
updateLogPath(requestId, "/logRecord/" + requestId + ".json");
});
}
catch(Exception ex)
{
}
return result;
}
public static void updateLogPath(string requestId, string logPath)
{
var logicLogRecordService = App.GetService();
LogicLogRecord logRecord = logicLogRecordService.getLogicLogRecordQuery(requestId);
logRecord.logicLogFilePath = logPath;
logicLogRecordService.updateLogicLogRecord(logRecord);
}
public static string UnicodeToChinese(string input)
{
return Regex.Replace(input, @"\\u([0-9a-fA-F]{4})", m =>
{
int code = Convert.ToInt32(m.Groups[1].Value, 16);
return ((char)code).ToString();
});
}
///
/// 运行逻辑项目的Json数据
///
/// 边列表
/// 起始节点ID
public static void sortEdge(string requestId, List databaseInfos, List tables, List edgeList, List nodeList, List paramList, string startNodeId, Dictionary doEdgeCount, List logDic, string env)
{
var edges = edgeList.Where(m => m.source == startNodeId).ToList();
foreach(EdgeList item in edges)
{
doNode(requestId, databaseInfos, tables, edgeList, nodeList, paramList, item.target, doEdgeCount, logDic, env);
}
}
///
/// 执行节点
///
/// 边列表
/// 起始节点ID
public static void doNode(string requestId, List databaseInfos, List tables, List edgeList, List nodeList, List paramList, string nodeId, Dictionary doEdgeCount, List logDic, string env)
{
NodeList node = nodeList.FirstOrDefault(x => x.nodeId == nodeId) ?? new NodeList();
var edges = edgeList.Where(m => m.source == nodeId).ToList();
int targetEdgeCount = edgeList.Count(m => m.target == nodeId);
//记录同一层级的节点执行计数,保证当前层级的所有节点都执行完后,再执行下一层级的节点
// if(doEdgeCount.ContainsKey(nodeId))
// {
// doEdgeCount[nodeId]++;
// }
// else
// {
// doEdgeCount.Add(nodeId, 1);
// }
// if(doEdgeCount[nodeId] < targetEdgeCount && targetEdgeCount > 1)
// {
// return;
// }
switch(node.nodeType)
{
case "ifelse": // 如果-否则节点
var ifElseResult = LogicNodeHelper.ifElse(node, paramList, logDic);
if(ifElseResult.Count > 0)
{
int ifIndex = 0;
foreach(bool result in ifElseResult)
{
if(result)
{
string checkIdString = nodeId + "condition-" + ifIndex;
var items = edges.Where(m => m.id.Contains(checkIdString)).ToList();
foreach(EdgeList item in items)
{
doNode(requestId, databaseInfos, tables, edgeList, nodeList, paramList, item.target, doEdgeCount, logDic, env);
}
break;
}
ifIndex += 1;
}
}
if(ifElseResult.Count(m => m) == 0)
{
string elseString = nodeId + "condition-else";
var elseItems = edges.Where(m => m.id.Contains(elseString)).ToList();
foreach(EdgeList item in elseItems)
{
doNode(requestId, databaseInfos, tables, edgeList, nodeList, paramList, item.target, doEdgeCount, logDic, env);
}
}
break;
case "iteration": // 迭代节点
LogicNodeHelper.iterationChildStart(node, paramList, logDic);
bool op = true;
while (op)
{
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId + "-child-start-node", doEdgeCount, logDic, env);
op = RedisServer.Cache.Get("break_" + requestId + "_" + node.nodeId) != "1";
JsonData upField = node.nodeData["data"]["formData"]["output"]["value"]; // 递归字段
foreach(JsonData item in upField)
{
string paramName = item["label"].ToString(); // 递归字段名
string paramValue = item["value"].ToString(); // 递归字段值
var param = paramList.FirstOrDefault(x => x.paramName == paramName && x.paramAttribute == "iterationInputField");
if (param != null)
{
var upParam = paramList.FirstOrDefault(x => x.paramName == paramValue && x.paramAttribute == "iterationInputField");
if(upParam != null)
{
param.paramValue = upParam.paramValue;
}
else
{
param.paramValue = "0";
}
}
}
}
RedisServer.Cache.Del("break_" + requestId + "_" + node.nodeId);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "child_start": // 子流程起始节点
// LogicNodeHelper.iterationChildStart(node, paramList);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "break": // 跳出循环
LogicNodeHelper.iterationBreak(node, requestId, logDic);
// 跳出循环后,继续执行循环后面的节点
string parentNodeId = node.nodeData["parentNode"]?.ToString() ?? string.Empty;
EdgeList breakEdge = edgeList.FirstOrDefault(x => x.source == parentNodeId) ?? new EdgeList();
if(string.IsNullOrEmpty(breakEdge.source))
{
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, breakEdge.target, doEdgeCount, logDic, env);
}
break;
case "loop": // 循环节点
List> loopResult = LogicNodeHelper.loop(node, paramList, logDic);
foreach(Dictionary subLoop in loopResult)
{
if(RedisServer.Cache.Get("break_" + node.nodeId) == "1")
{
break;
}
else
{
foreach(string key in subLoop.Keys)
{
var loopParam = paramList.FirstOrDefault(x => x.paramName == key && x.nodeId == node.nodeId && x.paramAttribute == "loop");
if(loopParam != null)
{
loopParam.paramValue = subLoop[key]?.ToString();
}
else
{
paramList.Add(new ParamList()
{
nodeId = node.nodeId,
paramAttribute = "loop",
paramName = key,
paramType = "string",
paramValue = subLoop[key]?.ToString(),
});
}
}
doEdgeCount.Remove(node.nodeId + "-child-start-node");
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId + "-child-start-node", doEdgeCount, logDic, env);
}
}
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "code-execute": // 代码执行节点
LogicNodeHelper.codeExecute(node, paramList, logDic);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "sql-execute": // SQL执行节点
LogicDatabaseNodeHelper.dbSqlQuery(node, databaseInfos, paramList, logDic, env);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "insert-data": // 插入数据节点
LogicDatabaseNodeHelper.dbInsert(node, databaseInfos, tables, paramList, logDic, env);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "update-data": // 更新数据节点
LogicDatabaseNodeHelper.dbUpdate(node, databaseInfos, tables, paramList, logDic, env);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "query-data": // 查询数据节点
LogicDatabaseNodeHelper.dbQuery(node, databaseInfos, tables, paramList, logDic, env);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "delete-data": // 删除数据节点
LogicDatabaseNodeHelper.dbDelete(node, databaseInfos, tables, paramList, logDic, env);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "setredis": // 设置Redis值节点
LogicCacheNodeHelper.setRedisObject(node, paramList, logDic);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "getredis": // 获取Redis值节点
LogicCacheNodeHelper.getRedisObject(node, paramList, logDic);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "http-request": // HTTP请求节点
LogicToolNodeHelper.httpRequest(node, paramList, logDic);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "apiSource": // 内部API请求节点
LogicToolNodeHelper.apiSourceRequest(node, paramList, logDic);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "var-aggregate": // 变量聚合节点
LogicNodeHelper.varAggregate(node, paramList, logDic);
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "document-extractor": // 文档提取节点
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "document-export": // 文档导出节点
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
case "end": // 结束节点
break;
default:
sortEdge(requestId, databaseInfos, tables, edgeList, nodeList, paramList, node.nodeId, doEdgeCount, logDic, env);
break;
}
}
public static string GetExpressionVal(string str)
{
if(str == "#{now}#") return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
if(str == "#{today}#") return DateTime.Now.ToString("yyyy-MM-dd");
if(str == "#{this_month}#") return DateTime.Now.ToString("yyyy-MM");
if(str.StartsWith("#{now") && str.EndsWith("DAY}#")) return DateTime.Now.AddDays(int.Parse(str.Replace("#", "").Replace("{", "").Replace("}", "").Split(',')[1])).ToString("yyyy-MM-dd HH:mm:ss");
if(str.StartsWith("#{now") && str.EndsWith("MONTH}#")) return DateTime.Now.AddMonths(int.Parse(str.Replace("#", "").Replace("{", "").Replace("}", "").Split(',')[1])).ToString("yyyy-MM-dd HH:mm:ss");
if(str.StartsWith("#{today") && str.EndsWith("DAY}#")) return DateTime.Now.AddDays(int.Parse(str.Replace("#", "").Replace("{", "").Replace("}", "").Split(',')[1])).ToString("yyyy-MM-dd");
if(str.StartsWith("#{today") && str.EndsWith("MONTH}#")) return DateTime.Now.AddMonths(int.Parse(str.Replace("#", "").Replace("{", "").Replace("}", "").Split(',')[1])).ToString("yyyy-MM-dd");
if(str.StartsWith("#{this_month") && str.EndsWith("DAY}#")) return DateTime.Now.AddDays(int.Parse(str.Replace("#", "").Replace("{", "").Replace("}", "").Split(',')[1])).ToString("yyyy-MM");
if(str.StartsWith("#{this_month") && str.EndsWith("MONTH}#")) return DateTime.Now.AddMonths(int.Parse(str.Replace("#", "").Replace("{", "").Replace("}", "").Split(',')[1])).ToString("yyyy-MM");
if(str.StartsWith("#{") && str.EndsWith("DAY}#")) return DateTime.Parse(str.Replace("#", "").Replace("{", "").Replace("}", "").Split(',')[0]).AddDays(int.Parse(str.Replace("#", "").Replace("{", "").Replace("}", "").Split(',')[1])).ToString("yyyy-MM-dd HH:mm:ss");
if(str.StartsWith("#{") && str.EndsWith("MONTH}#")) return DateTime.Parse(str.Replace("#", "").Replace("{", "").Replace("}", "").Split(',')[0]).AddMonths(int.Parse(str.Replace("#", "").Replace("{", "").Replace("}", "").Split(',')[1])).ToString("yyyy-MM-dd HH:mm:ss");
if(str.StartsWith("#{split") && str.EndsWith("}#"))
{
string[] data = str.Replace("#{", "").Replace("}#", "").Split(',');
string text = data[1];
string splitTag = data[2];
string index = data[3];
return text.Split(new string[]{ splitTag }, StringSplitOptions.None)[int.Parse(index)];
}
else if(str.StartsWith("#{") && str.EndsWith("}#"))
{
string[] data = str.Replace("#{", "").Replace("}#", "").Split(',');
string tag = data[0];
string format = data[data.Length - 1];
if(format.StartsWith("yyyy"))
{
if(tag == "now")
{
if(data.Length == 2)
{
return DateTime.Now.ToString(format);
}
else if(data.Length == 4)
{
if(data[2] == "DAY") return DateTime.Now.AddDays(int.Parse(data[1])).ToString(format);
if(data[2] == "MONTH") return DateTime.Now.AddMonths(int.Parse(data[1])).ToString(format);
}
}
else
{
if(data.Length == 2)
{
return DateTime.Parse(tag).ToString(format);
}
else if(data.Length == 4)
{
if(data[2] == "DAY") return DateTime.Parse(tag).AddDays(int.Parse(data[1])).ToString(format);
if(data[2] == "MONTH") return DateTime.Parse(tag).AddMonths(int.Parse(data[1])).ToString(format);
}
}
}
}
return str;
}
public static string MatchExpressionVal(string str)
{
if(string.IsNullOrEmpty(str)) return str;
MatchCollection mc = Regex.Matches(str, "#\\{.*?\\}#");
foreach(Match m in mc)
{
str = str.Replace(m.Value, GetExpressionVal(m.Value));
}
return str;
}
public static List> initNodeData(string nodeType)
{
if(string.IsNullOrEmpty(nodeType)) return new List>();
var data = new List>();
if(nodeType == "json")
{
var item = new Dictionary();
item.Add("title", "标题1");
item.Add("detail", "介绍1");
item.Add("id", 1);
var children = new List>();
var childItem = new Dictionary();
childItem.Add("title", "子标题1");
childItem.Add("detail", "子介绍1");
childItem.Add("id", 3);
children.Add(childItem);
childItem = new Dictionary();
childItem.Add("title", "子标题2");
childItem.Add("detail", "子介绍2");
childItem.Add("id", 4);
children.Add(childItem);
item.Add("children", children);
data.Add(item);
return data;
}
var input = new Dictionary();
input.Add("label", "user_id");
input.Add("required", true);
input.Add("type", new List() { "number" });
input.Add("desc", "");
input.Add("children", new List