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()); input.Add("_id", "mqeuhpvg-1o5m6i612c4o4ph"); data.Add(input); return data; } } }