|
|
|
|
using DS.Module.Core.Data;
|
|
|
|
|
|
|
|
|
|
namespace DS.Module.Core.Condition
|
|
|
|
|
{
|
|
|
|
|
public class ConditionHelper
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 根据ContitionContent条件,从数据上下文TaskFlowDataContext中取出指定数据,然后判断条件是否符合
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static bool IsPass(ConditionContent conditionContent, TaskFlowDataContext dataContext)
|
|
|
|
|
{
|
|
|
|
|
bool? thisScopeResult = null;
|
|
|
|
|
|
|
|
|
|
if (conditionContent == null || conditionContent.Conditions == null || conditionContent.Conditions.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IDictionary<string, object>? dataDic = null;
|
|
|
|
|
if (!string.IsNullOrEmpty(conditionContent.SourceName) && dataContext.ContainsKey(conditionContent.SourceName))
|
|
|
|
|
{
|
|
|
|
|
dataDic = dataContext[conditionContent.SourceName] as IDictionary<string, object>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var item in conditionContent.Conditions)
|
|
|
|
|
{
|
|
|
|
|
var itemResult = false;
|
|
|
|
|
|
|
|
|
|
object? val = null;
|
|
|
|
|
|
|
|
|
|
if (dataDic != null && dataDic.TryGetValue(item.Field, out val))
|
|
|
|
|
{ }
|
|
|
|
|
else if (dataContext.ContainsKey(item.Field))
|
|
|
|
|
{
|
|
|
|
|
val = dataContext.Get<object>(item.Field)!;
|
|
|
|
|
}
|
|
|
|
|
else if (item.Field!.Contains('.'))
|
|
|
|
|
{
|
|
|
|
|
var firstKey = item.Field.Split('.').First();
|
|
|
|
|
|
|
|
|
|
if (dataContext.ContainsKey(firstKey))
|
|
|
|
|
{
|
|
|
|
|
var firstVal = dataContext.Get<object>(firstKey)!;
|
|
|
|
|
if (firstVal != null)
|
|
|
|
|
{
|
|
|
|
|
var propertyPath = item.Field.Substring(item.Field.IndexOf('.') + 1);
|
|
|
|
|
|
|
|
|
|
val = GetPropertyValue(firstVal, propertyPath).val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (item.ValueType)
|
|
|
|
|
{
|
|
|
|
|
case "bool":
|
|
|
|
|
{
|
|
|
|
|
bool? judgeVal = null;
|
|
|
|
|
if (val is bool || (val != null && val.GetType() == typeof(bool?)))
|
|
|
|
|
{
|
|
|
|
|
judgeVal = (bool?)val;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (bool.TryParse(val?.ToString(), out bool result))
|
|
|
|
|
{
|
|
|
|
|
judgeVal = result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
bool conditionVal = false;
|
|
|
|
|
switch (item.Value)
|
|
|
|
|
{
|
|
|
|
|
case "是":
|
|
|
|
|
case "true":
|
|
|
|
|
case "True":
|
|
|
|
|
conditionVal = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
switch (item.Operator)
|
|
|
|
|
{
|
|
|
|
|
case "equal":
|
|
|
|
|
itemResult = judgeVal == conditionVal; break;
|
|
|
|
|
case "not_equal":
|
|
|
|
|
itemResult = judgeVal != conditionVal; break;
|
|
|
|
|
case "empty":
|
|
|
|
|
itemResult = judgeVal == null; break;
|
|
|
|
|
case "not_empty":
|
|
|
|
|
itemResult = judgeVal != null; break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "number":
|
|
|
|
|
{
|
|
|
|
|
double? judgeVal = null;
|
|
|
|
|
if (val is System.ValueType)
|
|
|
|
|
{
|
|
|
|
|
judgeVal = Convert.ToDouble(val);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (double.TryParse(val?.ToString(), out double result))
|
|
|
|
|
{
|
|
|
|
|
judgeVal = result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
double? conditionVal = null;
|
|
|
|
|
if (double.TryParse(item.Value, out double temp))
|
|
|
|
|
{
|
|
|
|
|
conditionVal = temp;
|
|
|
|
|
}
|
|
|
|
|
switch (item.Operator)
|
|
|
|
|
{
|
|
|
|
|
case "equal":
|
|
|
|
|
itemResult = judgeVal == conditionVal; break;
|
|
|
|
|
case "not_equal":
|
|
|
|
|
itemResult = judgeVal != conditionVal; break;
|
|
|
|
|
case "empty":
|
|
|
|
|
itemResult = judgeVal == null; break;
|
|
|
|
|
case "not_empty":
|
|
|
|
|
itemResult = judgeVal != null; break;
|
|
|
|
|
case "greater_than":
|
|
|
|
|
itemResult = judgeVal != null && conditionVal != null && judgeVal > conditionVal; break;
|
|
|
|
|
case "greater_than_or_equal":
|
|
|
|
|
itemResult = judgeVal != null && conditionVal != null && judgeVal >= conditionVal; break;
|
|
|
|
|
case "less_than":
|
|
|
|
|
itemResult = judgeVal != null && conditionVal != null && judgeVal < conditionVal; break;
|
|
|
|
|
case "less_than_or_equal":
|
|
|
|
|
itemResult = judgeVal != null && conditionVal != null && judgeVal <= conditionVal; break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "datetime":
|
|
|
|
|
{
|
|
|
|
|
DateTime? judgeVal = null;
|
|
|
|
|
if (val is DateTime || (val != null && val.GetType() == typeof(DateTime?)))
|
|
|
|
|
{
|
|
|
|
|
judgeVal = (DateTime?)val;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (DateTime.TryParse(val?.ToString(), out DateTime result))
|
|
|
|
|
{
|
|
|
|
|
judgeVal = result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DateTime? conditionVal = null;
|
|
|
|
|
if (DateTime.TryParse(item.Value, out DateTime temp))
|
|
|
|
|
{
|
|
|
|
|
conditionVal = temp;
|
|
|
|
|
}
|
|
|
|
|
switch (item.Operator)
|
|
|
|
|
{
|
|
|
|
|
case "equal":
|
|
|
|
|
itemResult = judgeVal == conditionVal; break;
|
|
|
|
|
case "not_equal":
|
|
|
|
|
itemResult = judgeVal != conditionVal; break;
|
|
|
|
|
case "empty":
|
|
|
|
|
itemResult = judgeVal == null; break;
|
|
|
|
|
case "not_empty":
|
|
|
|
|
itemResult = judgeVal != null; break;
|
|
|
|
|
case "greater_than":
|
|
|
|
|
itemResult = judgeVal != null && conditionVal != null && judgeVal > conditionVal; break;
|
|
|
|
|
case "greater_than_or_equal":
|
|
|
|
|
itemResult = judgeVal != null && conditionVal != null && judgeVal >= conditionVal; break;
|
|
|
|
|
case "less_than":
|
|
|
|
|
itemResult = judgeVal != null && conditionVal != null && judgeVal < conditionVal; break;
|
|
|
|
|
case "less_than_or_equal":
|
|
|
|
|
itemResult = judgeVal != null && conditionVal != null && judgeVal <= conditionVal; break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
case "string":
|
|
|
|
|
{
|
|
|
|
|
string judgeVal = val?.ToString() ?? "";
|
|
|
|
|
string conditionVal = item.Value ??= "";
|
|
|
|
|
switch (item.Operator)
|
|
|
|
|
{
|
|
|
|
|
case "equal":
|
|
|
|
|
itemResult = judgeVal.Equals(conditionVal, StringComparison.OrdinalIgnoreCase); break;
|
|
|
|
|
case "not_equal":
|
|
|
|
|
itemResult = !judgeVal.Equals(conditionVal, StringComparison.OrdinalIgnoreCase); break;
|
|
|
|
|
case "contains":
|
|
|
|
|
itemResult = judgeVal.Contains(conditionVal, StringComparison.OrdinalIgnoreCase); break;
|
|
|
|
|
case "not_contain":
|
|
|
|
|
itemResult = !judgeVal.Contains(conditionVal, StringComparison.OrdinalIgnoreCase); break;
|
|
|
|
|
case "empty":
|
|
|
|
|
itemResult = string.IsNullOrWhiteSpace(judgeVal); break;
|
|
|
|
|
case "not_empty":
|
|
|
|
|
itemResult = !string.IsNullOrWhiteSpace(judgeVal); break;
|
|
|
|
|
case "start_with":
|
|
|
|
|
itemResult = judgeVal.StartsWith(conditionVal, StringComparison.OrdinalIgnoreCase); break;
|
|
|
|
|
case "end_with":
|
|
|
|
|
itemResult = judgeVal.EndsWith(conditionVal, StringComparison.OrdinalIgnoreCase); break;
|
|
|
|
|
}
|
|
|
|
|
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(IsPass(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>
|
|
|
|
|
/// <param name="condition"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static int GetConditionCount(ConditionContent condition)
|
|
|
|
|
{
|
|
|
|
|
int n = condition.Conditions?.Count ?? 0;
|
|
|
|
|
if (condition.Groups != null && condition.Groups.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
n += condition.Groups.Sum(GetConditionCount);
|
|
|
|
|
}
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 深度获取对象属性值
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="obj">对象</param>
|
|
|
|
|
/// <param name="propertyPath">属性路径</param>
|
|
|
|
|
static (bool isOk, object? val, string? otherPropertyPath) GetPropertyValue(object obj, string propertyPath)
|
|
|
|
|
{
|
|
|
|
|
var propertyName = propertyPath.Split('.').FirstOrDefault();
|
|
|
|
|
var type = obj.GetType();
|
|
|
|
|
|
|
|
|
|
var property = type.GetProperty(propertyName);
|
|
|
|
|
if (property == null)
|
|
|
|
|
{
|
|
|
|
|
return (true, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (property.PropertyType.IsClass && property.PropertyType != typeof(string))
|
|
|
|
|
{
|
|
|
|
|
var val = property.GetValue(obj);
|
|
|
|
|
if (val == null)
|
|
|
|
|
{
|
|
|
|
|
return (true, null, null);
|
|
|
|
|
}
|
|
|
|
|
var otherPropertyPath = propertyPath.Substring(propertyPath.IndexOf('.') + 1);
|
|
|
|
|
return GetPropertyValue(val, otherPropertyPath);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var val = property.GetValue(obj);
|
|
|
|
|
return (true, val, null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|