|
|
|
@ -1,6 +1,7 @@
|
|
|
|
|
using DS.Module.Core;
|
|
|
|
|
using DS.Module.Core.Data;
|
|
|
|
|
using DS.WMS.Core.TaskPlat.Entity;
|
|
|
|
|
using DS.WMS.Core.TaskPlat.Other;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
@ -66,89 +67,32 @@ namespace DS.WMS.Core.TaskPlat
|
|
|
|
|
await tenantDb.Insertable(log).ExecuteCommandAsync();
|
|
|
|
|
logger.LogInformation(msg);
|
|
|
|
|
return (null, false, false);
|
|
|
|
|
//throw new Exception(msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var allConfigIdList = allConfigList.Select(x => x.Id);
|
|
|
|
|
var allConditionList = await tenantDb.Queryable<TaskFlowCondition>()
|
|
|
|
|
.Where(x => allConfigIdList.Contains(x.ConfigId))
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
.Where(x => allConfigIdList.Contains(x.ConfigId) && x.Type == 1)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
// 判断每项流程达成的条件数量
|
|
|
|
|
Dictionary<long, int> configMatchCount = allConfigList.ToDictionary(x => x.Id, x => 0);
|
|
|
|
|
foreach (var configItem in allConfigList)
|
|
|
|
|
{
|
|
|
|
|
var conditionListGroup = allConditionList.Where(x => x.ConfigId == configItem.Id);
|
|
|
|
|
foreach (var conditionItem in conditionListGroup)
|
|
|
|
|
var conditionItem = allConditionList.FirstOrDefault(x => x.ConfigId == configItem.Id);
|
|
|
|
|
if (conditionItem != null && !string.IsNullOrEmpty(conditionItem.Content))
|
|
|
|
|
{
|
|
|
|
|
string? valStr;
|
|
|
|
|
if (conditionItem.FieldName.Contains('.'))
|
|
|
|
|
{
|
|
|
|
|
var firstKey = conditionItem.FieldName.Split('.').First();
|
|
|
|
|
|
|
|
|
|
if (!dataContext.ContainsKey(firstKey)) continue;
|
|
|
|
|
|
|
|
|
|
var obj = dataContext.Get<object>(firstKey)!;
|
|
|
|
|
|
|
|
|
|
var propertyPath = conditionItem.FieldName.Substring(conditionItem.FieldName.IndexOf('.') + 1);
|
|
|
|
|
var (_, val, _) = GetPropertyValue(obj, propertyPath);
|
|
|
|
|
if (val == null) continue;
|
|
|
|
|
|
|
|
|
|
valStr = val.ToString();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!dataContext.ContainsKey(conditionItem.FieldName)) continue;
|
|
|
|
|
|
|
|
|
|
var obj = dataContext.Get<object>(conditionItem.FieldName)!;
|
|
|
|
|
valStr = obj.ToString();
|
|
|
|
|
}
|
|
|
|
|
var contitionContent = JsonConvert.DeserializeObject<ContitionContent>(conditionItem.Content)!;
|
|
|
|
|
|
|
|
|
|
var oldValue = configMatchCount[configItem.Id];
|
|
|
|
|
if (conditionItem.MatchType == 1)
|
|
|
|
|
if (MatchByCondition(contitionContent, dataContext))
|
|
|
|
|
{
|
|
|
|
|
if (valStr?.Equals(conditionItem.MatchValue, StringComparison.CurrentCultureIgnoreCase) == true)
|
|
|
|
|
{
|
|
|
|
|
configMatchCount[configItem.Id] = oldValue + 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
configMatchCount[configItem.Id] = oldValue - 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (conditionItem.MatchType == 2)
|
|
|
|
|
{
|
|
|
|
|
if (valStr?.Contains(conditionItem.MatchValue, StringComparison.CurrentCultureIgnoreCase) == true)
|
|
|
|
|
{
|
|
|
|
|
configMatchCount[configItem.Id] = oldValue + 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
configMatchCount[configItem.Id] = oldValue - 1;
|
|
|
|
|
}
|
|
|
|
|
configMatchCount[configItem.Id] = oldValue + 1;
|
|
|
|
|
}
|
|
|
|
|
else if (conditionItem.MatchType == 3)
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (valStr?.StartsWith(conditionItem.MatchValue, StringComparison.CurrentCultureIgnoreCase) == true)
|
|
|
|
|
{
|
|
|
|
|
configMatchCount[configItem.Id] = oldValue + 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
configMatchCount[configItem.Id] = oldValue - 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (conditionItem.MatchType == 4)
|
|
|
|
|
{
|
|
|
|
|
if (valStr?.EndsWith(conditionItem.MatchValue, StringComparison.CurrentCultureIgnoreCase) == true)
|
|
|
|
|
{
|
|
|
|
|
configMatchCount[configItem.Id] = oldValue + 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
configMatchCount[configItem.Id] = oldValue - 1;
|
|
|
|
|
}
|
|
|
|
|
configMatchCount[configItem.Id] = oldValue - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -180,13 +124,20 @@ namespace DS.WMS.Core.TaskPlat
|
|
|
|
|
}
|
|
|
|
|
var targetConfig = allConfigList.First(x => x.Id == bestMatched.Value.Key);
|
|
|
|
|
|
|
|
|
|
// 待执行的流程(节点列表)
|
|
|
|
|
var configList = await tenantDb.Queryable<TaskFlowConfig>().Where(x => x.MainConfigId == targetConfig.Id).ToListAsync();
|
|
|
|
|
var configIdList = configList.Select(x => x.Id).ToList();
|
|
|
|
|
var moduleIdList = configList.Select(x => x.ExecuteModuleId).ToList();
|
|
|
|
|
|
|
|
|
|
// 待注入的参数列表
|
|
|
|
|
var paramList = await tenantDb.Queryable<TaskFlowParam>().Where(x => configIdList.Contains(x.ConfigId)).ToListAsync();
|
|
|
|
|
|
|
|
|
|
// 待执行的模块列表
|
|
|
|
|
var moduleIdList = configList.Select(x => x.ExecuteModuleId).ToList();
|
|
|
|
|
var moduleList = await tenantDb.Queryable<TaskFlowModule>().Where(x => moduleIdList.Contains(x.Id)).ToListAsync();
|
|
|
|
|
|
|
|
|
|
// 待判断的条件列表
|
|
|
|
|
var conditionList = await tenantDb.Queryable<TaskFlowCondition>().Where(x => configIdList.Contains(x.ConfigId) && x.Type == 2).ToListAsync();
|
|
|
|
|
|
|
|
|
|
TaskFlowLog flowLog = new()
|
|
|
|
|
{
|
|
|
|
|
Id = SnowFlakeSingle.Instance.NextId(),
|
|
|
|
@ -201,41 +152,73 @@ namespace DS.WMS.Core.TaskPlat
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 执行流程
|
|
|
|
|
long? nextExecuteConfigId = targetConfig.Id;
|
|
|
|
|
List<TaskFlowConfig> waitMatchConfigList = new([targetConfig]);
|
|
|
|
|
for (int i = 0; i < configList.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (nextExecuteConfigId == null || nextExecuteConfigId == 0)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
var executeConfig = configList.FirstOrDefault(x => x.Id == nextExecuteConfigId);
|
|
|
|
|
if (executeConfig == null)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
nextExecuteConfigId = executeConfig.NextExecuteConfigId;
|
|
|
|
|
|
|
|
|
|
TaskFlowLogDetail flowLogDetail = new()
|
|
|
|
|
{
|
|
|
|
|
ConfigId = executeConfig.Id,
|
|
|
|
|
PId = flowLog.Id,
|
|
|
|
|
IsSuccess = true,
|
|
|
|
|
};
|
|
|
|
|
TaskFlowConfig? executeConfig = null;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (waitMatchConfigList == null || waitMatchConfigList.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 对节点列表里面的节点进行依次判断,取出要执行的节点
|
|
|
|
|
var matchedConfigList = new List<TaskFlowConfig>();
|
|
|
|
|
foreach (var waitMatchConfigItem in waitMatchConfigList)
|
|
|
|
|
{
|
|
|
|
|
var condition = conditionList.FirstOrDefault(x => x.ConfigId == waitMatchConfigItem.Id);
|
|
|
|
|
if (condition == null || string.IsNullOrEmpty(condition.Content))
|
|
|
|
|
{
|
|
|
|
|
matchedConfigList.Add(waitMatchConfigItem);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var contitionContent = JsonConvert.DeserializeObject<ContitionContent>(condition.Content)!;
|
|
|
|
|
if (MatchByCondition(contitionContent, dataContext))
|
|
|
|
|
{
|
|
|
|
|
matchedConfigList.Add(waitMatchConfigItem);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (matchedConfigList.Count == 1)
|
|
|
|
|
{
|
|
|
|
|
executeConfig = matchedConfigList[0];
|
|
|
|
|
}
|
|
|
|
|
else if (matchedConfigList.Count > 1)
|
|
|
|
|
{
|
|
|
|
|
executeConfig = matchedConfigList.FirstOrDefault(x => x.IsMoreMatchDefault);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (executeConfig == null)
|
|
|
|
|
{
|
|
|
|
|
executeConfig = waitMatchConfigList.FirstOrDefault(x => x.IsUnMatchDefault);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (executeConfig == null)
|
|
|
|
|
{
|
|
|
|
|
flowLog.IsComplete = false;
|
|
|
|
|
flowLog.IsSuccess = false;
|
|
|
|
|
flowLog.Note += $"【执行时未找到符合执行条件的节点,经判断条件的节点Id如下:{string.Join(',', waitMatchConfigList.Select(x => x.Id))}】";
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flowLogDetail.ConfigId = executeConfig.Id;
|
|
|
|
|
|
|
|
|
|
// 如果当前节点要执行(或者配置了默认执行节点)取出下一批要进行条件判断的节点列表
|
|
|
|
|
waitMatchConfigList = configList.Where(x => x.ParentConfigId == executeConfig.Id).ToList();
|
|
|
|
|
|
|
|
|
|
// 注入参数
|
|
|
|
|
var paramItemList = paramList.Where(x => x.ConfigId == executeConfig.Id).ToList();
|
|
|
|
|
foreach (var paramItem in paramItemList)
|
|
|
|
|
{
|
|
|
|
|
dataContext.Set(paramItem.FieldName!, paramItem.FieldValue!);
|
|
|
|
|
|
|
|
|
|
//if (dataContext.ContainsKey(paramItem.FieldName!))
|
|
|
|
|
//{
|
|
|
|
|
// dataContext[paramItem.FieldName!] = paramItem.FieldValue!;
|
|
|
|
|
//}
|
|
|
|
|
//else
|
|
|
|
|
//{
|
|
|
|
|
// dataContext.TryAdd(paramItem.FieldName!, paramItem.FieldValue!);
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var module = moduleList.FirstOrDefault(x => x.Id == executeConfig.ExecuteModuleId);
|
|
|
|
@ -375,6 +358,120 @@ namespace DS.WMS.Core.TaskPlat
|
|
|
|
|
return await Run(taskBaseType, taskId, dataContext);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 递归解析并判断条件
|
|
|
|
|
/// </summary>
|
|
|
|
|
static bool MatchByCondition(ContitionContent conditionContent, TaskFlowDataContext dataContext)
|
|
|
|
|
{
|
|
|
|
|
bool? thisScopeResult = null;
|
|
|
|
|
|
|
|
|
|
if (conditionContent == null || conditionContent.Conditions == null || conditionContent.Conditions.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var item in conditionContent.Conditions)
|
|
|
|
|
{
|
|
|
|
|
var itemResult = false;
|
|
|
|
|
|
|
|
|
|
string? valStr = null;
|
|
|
|
|
if (item.Field!.Contains('.'))
|
|
|
|
|
{
|
|
|
|
|
var firstKey = item.Field.Split('.').First();
|
|
|
|
|
|
|
|
|
|
if (dataContext.ContainsKey(firstKey))
|
|
|
|
|
{
|
|
|
|
|
var obj = dataContext.Get<object>(firstKey)!;
|
|
|
|
|
|
|
|
|
|
var propertyPath = item.Field.Substring(item.Field.IndexOf('.') + 1);
|
|
|
|
|
var (_, val, _) = GetPropertyValue(obj, propertyPath);
|
|
|
|
|
|
|
|
|
|
if (val != null)
|
|
|
|
|
valStr = val.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (dataContext.ContainsKey(item.Field))
|
|
|
|
|
{
|
|
|
|
|
var obj = dataContext.Get<object>(item.Field)!;
|
|
|
|
|
valStr = obj.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (item.Operator)
|
|
|
|
|
{
|
|
|
|
|
case "equal":
|
|
|
|
|
itemResult = valStr?.Equals(item.Value, StringComparison.OrdinalIgnoreCase) == true; break;
|
|
|
|
|
case "not_equal":
|
|
|
|
|
itemResult = valStr?.Equals(item.Value, StringComparison.OrdinalIgnoreCase) != true; break;
|
|
|
|
|
case "contains":
|
|
|
|
|
itemResult = valStr?.Contains(item.Value, StringComparison.OrdinalIgnoreCase) == true; break;
|
|
|
|
|
case "not_contain":
|
|
|
|
|
itemResult = valStr?.Contains(item.Value, StringComparison.OrdinalIgnoreCase) != true; break;
|
|
|
|
|
case "start_with":
|
|
|
|
|
itemResult = valStr?.StartsWith(item.Value, StringComparison.OrdinalIgnoreCase) == true; break;
|
|
|
|
|
case "end_with":
|
|
|
|
|
itemResult = valStr?.EndsWith(item.Value, StringComparison.OrdinalIgnoreCase) == true; break;
|
|
|
|
|
case "greater_than":
|
|
|
|
|
{
|
|
|
|
|
itemResult = double.TryParse(valStr, out double temp1) && double.TryParse(item.Value, out double temp2) && temp1 > temp2; break;
|
|
|
|
|
}
|
|
|
|
|
case "greater_than_or_equal":
|
|
|
|
|
{
|
|
|
|
|
itemResult = double.TryParse(valStr, out double temp1) && double.TryParse(item.Value, out double temp2) && temp1 >= temp2; break;
|
|
|
|
|
}
|
|
|
|
|
case "less_than":
|
|
|
|
|
{
|
|
|
|
|
itemResult = double.TryParse(valStr, out double temp1) && double.TryParse(item.Value, out double temp2) && temp1 < temp2; break;
|
|
|
|
|
}
|
|
|
|
|
case "less_than_or_equal":
|
|
|
|
|
{
|
|
|
|
|
itemResult = double.TryParse(valStr, out double temp1) && double.TryParse(item.Value, out double temp2) && temp1 <= temp2; break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (thisScopeResult == null)
|
|
|
|
|
{
|
|
|
|
|
thisScopeResult = itemResult;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (conditionContent.LogicalOperator == "and")
|
|
|
|
|
{
|
|
|
|
|
thisScopeResult = thisScopeResult.Value && itemResult;
|
|
|
|
|
}
|
|
|
|
|
else if (conditionContent.LogicalOperator == "or")
|
|
|
|
|
{
|
|
|
|
|
thisScopeResult = thisScopeResult.Value || itemResult;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//thisScopeResult ??= true; // 实际这里的thisScopeResult的值啃腚不为null
|
|
|
|
|
|
|
|
|
|
if (conditionContent.Groups != null && conditionContent.Groups.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
// 组的结果
|
|
|
|
|
var groupResult = new List<bool>();
|
|
|
|
|
foreach (var item in conditionContent.Groups)
|
|
|
|
|
{
|
|
|
|
|
// 递归调用,向组里添加结果
|
|
|
|
|
groupResult.Add(MatchByCondition(item, dataContext));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (conditionContent.LogicalOperator == "and")
|
|
|
|
|
{
|
|
|
|
|
return thisScopeResult == true && groupResult.All(a => a);
|
|
|
|
|
}
|
|
|
|
|
else if (conditionContent.LogicalOperator == "or")
|
|
|
|
|
{
|
|
|
|
|
return thisScopeResult == true || groupResult.Any(a => a);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return thisScopeResult == true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 深度获取对象属性值
|
|
|
|
|
/// </summary>
|
|
|
|
|