cjy 4 months ago
commit 69b4844268

@ -196,7 +196,7 @@ public class FlowInstanceService : ServiceBase, IFlowInstanceService
public DataResult CancelFlowInstance(CancelFlowInstanceReq req)
{
var instance = Db.Queryable<FlowInstance>().First(x => x.Id == req.Id);
if (instance.IsNull())
if (instance == null)
{
return DataResult.Failed("该工作流不存在!", MultiLanguageConst.FlowInstanceNotExist);
}
@ -266,7 +266,7 @@ public class FlowInstanceService : ServiceBase, IFlowInstanceService
public DataResult StartFlowInstance(string id)
{
var instance = Db.Queryable<FlowInstance>().First(x => x.Id == long.Parse(id));
if (instance.IsNull())
if (instance == null)
{
return DataResult.Failed("该工作流不存在!", MultiLanguageConst.FlowInstanceNotExist);
}
@ -321,7 +321,7 @@ public class FlowInstanceService : ServiceBase, IFlowInstanceService
{
var instance = GetFlowInstance(req.Id);
if (instance.IsNull())
if (instance == null)
{
return DataResult.Failed("该工作流不存在!", MultiLanguageConst.FlowInstanceNotExist);
}
@ -416,7 +416,7 @@ public class FlowInstanceService : ServiceBase, IFlowInstanceService
instance.ActivityType = runtime.NextNodeType;
instance.ActivityName = runtime.NextNode.Name;
instance.MakerList = runtime.NextNodeType == 4 ? "1" : GetNextMakers(runtime);
instance.FlowStatus = (runtime.NextNodeType == 4 ? FlowStatusEnum.Approve : FlowStatusEnum.Running);
instance.FlowStatus = runtime.NextNodeType == 4 ? FlowStatusEnum.Approve : FlowStatusEnum.Running;
}
else
{
@ -428,12 +428,16 @@ public class FlowInstanceService : ServiceBase, IFlowInstanceService
#endregion 一般审核
if (!string.IsNullOrEmpty(instance.MakerList) && instance.MakerList != "1")
{
var serializerSettings = new JsonSerializerSettings
{
// 设置为驼峰命名
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
};
instance.Content = JsonConvert.SerializeObject(runtime.ToFlowRoot(), Formatting.None, serializerSettings);
}
instance.Note = auditNote;
Db.Updateable(instance).ExecuteCommand();

@ -442,11 +442,17 @@ public class FlowRuntime
public FlowRoot ToFlowRoot()
{
var root = ChildNodes.First(x => x.Id == "root");
var list = ChildNodes.Where(x => x.Id != "root").ToList();
var info = root.Adapt<FlowRoot>();
info.Child = list.First(x => x.Pid == "root");
try
{
UpdateChild(info.Child);
}
catch
{
}
return info;
}

@ -4,13 +4,13 @@ using DS.Module.SqlSugar;
using DS.Module.UserModule;
using DS.WMS.Core.Code.Entity;
using DS.WMS.Core.Info.Entity;
using DS.WMS.Core.Op.Dtos;
using DS.WMS.Core.Op.Dtos.TaskInteraction;
using DS.WMS.Core.Op.Entity.TaskInteraction;
using DS.WMS.Core.Op.Interface;
using DS.WMS.Core.Op.Interface.TaskInteraction;
using DS.WMS.Core.Sys.Entity;
using HtmlAgilityPack;
using Mapster;
using Masuit.Tools;
using Masuit.Tools.Systems;
using Microsoft.Extensions.Configuration;
@ -19,7 +19,7 @@ using Newtonsoft.Json;
using RazorEngineCore;
using SqlSugar;
namespace DS.WMS.Core.Op.Method.TaskInteraction
namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor
{
/// <summary>
/// 用于邮件发送的执行器
@ -87,17 +87,17 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
}
string title, content = string.Empty;
var templateModel = new MailTemplateModel<SeaExportRes> { Primary = result.Data };
var templateModel = new MailTemplateModel<SeaExportOrder> { Primary = result.Data.Adapt<SeaExportOrder>() };
IRazorEngine razorEngine = new RazorEngine();
try
{
var titleTemplate = razorEngine.Compile<RazorEngineTemplateBase<MailTemplateModel<SeaExportRes>>>(mailConfig.Title);
var titleTemplate = razorEngine.Compile<RazorEngineTemplateBase<MailTemplateModel<SeaExportOrder>>>(mailConfig.Title);
title = await titleTemplate.RunAsync(x =>
{
x.Model = templateModel;
});
var contentTemplate = razorEngine.Compile<RazorEngineTemplateBase<MailTemplateModel<SeaExportRes>>>(mailConfig.Content);
var contentTemplate = razorEngine.Compile<RazorEngineTemplateBase<MailTemplateModel<SeaExportOrder>>>(mailConfig.Content);
content = await contentTemplate.RunAsync(x =>
{
x.Model = templateModel;
@ -145,6 +145,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
StringWriter writer = new();
htmlDoc.Save(writer);
content = writer.ToString();
writer.Close();
//设置收件人
List<long> receiverIds = [];
@ -152,7 +153,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
receiverIds.Add(templateModel.Primary.CarrierId);
if (mailConfig.Receiver.IsBooking)
receiverIds.Add(templateModel.Primary.CarrierId);
receiverIds.Add(templateModel.Primary.ForwarderId);
if (mailConfig.Receiver.IsYard)
receiverIds.Add(templateModel.Primary.YardId);

@ -1,9 +1,9 @@
using DS.Module.Core;
using DS.Module.Core.Data;
using DS.WMS.Core.Op.Dtos.TaskInteraction;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Op.Entity.TaskInteraction;
using DS.WMS.Core.Op.Interface.TaskInteraction;
using DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor;
using DS.WMS.Core.TaskPlat;
using SqlSugar;

@ -0,0 +1,9 @@
using RazorEngineCore;
namespace DS.WMS.Core.Op.Method.TaskInteraction
{
internal class TemplateTranslator
{
}
}

@ -10,7 +10,6 @@ namespace DS.WMS.Core.TaskPlat.Entity
[SugarTable("task_flow_condition", "任务编排流程条件表")]
public class TaskFlowCondition : BaseModelV2<long>
{
/// <summary>
/// 流程主键
/// </summary>
@ -18,22 +17,16 @@ namespace DS.WMS.Core.TaskPlat.Entity
public long ConfigId { get; set; }
/// <summary>
/// 条件字段名称
/// </summary>
[SugarColumn(ColumnDescription = "条件字段名称", IsNullable = true, Length = 255)]
public string? FieldName { get; set; }
/// <summary>
/// 符合条件情况下字段的值
/// 条件类型 1=用于匹配要执行的流程 2=用于判断流程内部要执行的节点
/// </summary>
[SugarColumn(ColumnDescription = "符合条件情况下字段的值", IsNullable = true, Length = 255)]
public string? MatchValue { get; set; }
[SugarColumn(ColumnDescription = "条件类型 1=用于匹配要执行的流程 2=用于判断流程内部要执行的节点", IsNullable = false)]
public int Type { get; set; }
/// <summary>
/// 匹配类型 1=完全相等 2=包含 3=起始 4=结尾
/// 条件表达式
/// </summary>
[SugarColumn(ColumnDescription = "匹配类型 1=完全相等 2=包含 3=起始 4=结尾", IsNullable = false)]
public int MatchType { get; set; }
[SugarColumn(ColumnDescription = "条件表达式", IsNullable = false, ColumnDataType = "text")]
public string? Content { get; set; }
}
}

@ -1,5 +1,4 @@
using DS.Module.Core;
using DS.Module.Core.Data;
using DS.Module.Core.Data;
using SqlSugar;
namespace DS.WMS.Core.TaskPlat.Entity
@ -7,7 +6,7 @@ namespace DS.WMS.Core.TaskPlat.Entity
/// <summary>
/// 任务编排流程表
///</summary>
[SugarTable("task_flow_config", "任务编排流程表")]
[SugarTable("task_flow_config_new", "任务编排流程表")]
public class TaskFlowConfig : BaseModelV2<long>
{
@ -42,16 +41,28 @@ namespace DS.WMS.Core.TaskPlat.Entity
public long? MainConfigId { get; set; }
/// <summary>
/// 下一执行流程主键
/// 父项流程主键
/// </summary>
[SugarColumn(ColumnDescription = "下一执行流程主键", IsNullable = true)]
public long? NextExecuteConfigId { get; set; }
[SugarColumn(ColumnDescription = "父项流程主键", IsNullable = true)]
public long? ParentConfigId { get; set; }
/// <summary>
/// 发生异常时是否继续执行
/// 当执行过程中发生异常时是否继续执行下一个节点
/// </summary>
[SugarColumn(ColumnDescription = "发生异常时是否继续执行", IsNullable = false, Length = 1)]
[SugarColumn(ColumnDescription = "当执行过程中发生异常时是否继续执行下一个节点", IsNullable = false, Length = 1)]
public bool IsExceptionContinue { get; set; }
/// <summary>
/// 当无匹配的执行流程时是否作为默认的执行流程
/// </summary>
[SugarColumn(ColumnDescription = "当无匹配的执行流程时是否作为默认的执行流程", IsNullable = false, Length = 1)]
public bool IsUnMatchDefault { get; set; }
/// <summary>
/// 当匹配到多项执行流程时是否作为默认的执行流程
/// </summary>
[SugarColumn(ColumnDescription = "当匹配到多项执行流程时是否作为默认的执行流程", IsNullable = false, Length = 1)]
public bool IsMoreMatchDefault { get; set; }
}
}

@ -35,6 +35,7 @@ namespace DS.WMS.Core.TaskPlat.Interface
/// <param name="taskPKId">BC任务主键</param>
/// <returns>返回回执</returns>
Task<DataResult> SyncBookingSlotChange(long taskPKId);
Task<DataResult<TaskManageExcuteResultDto>> CompareBcWithSeaExportTask(TaskFlowDataContext dataContext);
/// <summary>

@ -65,6 +65,6 @@ namespace DS.WMS.Core.TaskPlat.Interface
/// <param name="taskBaseTypeEnum">业务类型</param>
/// <param name="userInfos">要转交的人员信息列表</param>
Task<DataResult> TransferTask(long bsno, TaskBaseTypeEnum taskBaseTypeEnum, List<RecvUserInfo> userInfos);
Task<DataResult> TestTaskFlow(string taskType, long taskId);
}
}

@ -14,6 +14,7 @@ namespace DS.WMS.Core.TaskPlat.Method
{
public Task<DataResult> TestMethod11(TaskFlowDataContext dataContext)
{
//throw new ArgumentException("缺少参数Age");
var address = dataContext.Get<string>("Address");
var height = dataContext.Get<string>("Height");
var info = dataContext.Get<TaskManageOrderMessageInfo>(nameof(TaskManageOrderMessageInfo));
@ -28,7 +29,8 @@ namespace DS.WMS.Core.TaskPlat.Method
public Task<DataResult> TestMethod12(TaskFlowDataContext dataContext)
{
//throw new Exception("TestMethod12内的测试异常");
return Task.FromResult(DataResult.Successed($"TestMethod12返回的成功结果"));
//return Task.FromResult(DataResult.Successed($"TestMethod12返回的成功结果"));
return Task.FromResult(DataResult.Failed($"TestMethod12返回的失败结果"));
}
}
}

@ -1119,9 +1119,7 @@ namespace DS.WMS.Core.TaskPlat.Method
/// <summary>
/// 对比BC与海运出口订单任务台使用
/// </summary>
public async Task<DataResult<TaskManageExcuteResultDto>> ExcuteCompareTask(TaskFlowDataContext dataContext)
{
try
public async Task<DataResult<TaskManageExcuteResultDto>> CompareBcWithSeaExportTask(TaskFlowDataContext dataContext)
{
var taskBcId = dataContext.Get<long?>(TaskFlowDataNameConst.TaskBCId);
if (taskBcId == null)
@ -1129,40 +1127,45 @@ namespace DS.WMS.Core.TaskPlat.Method
throw new ArgumentException($"缺少参数:{nameof(TaskFlowDataNameConst.TaskBCId)}");
}
try
{
var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId);
var taskBcInfo = await tenantDb.Queryable<TaskBCInfo>().Where(x => x.Id == taskBcId).FirstAsync();
if (taskBcInfo == null)
{
string msg = $"执行ExcuteCompareTask时根据未获取到BC信息";
logger.LogInformation(msg);
return DataResult<TaskManageExcuteResultDto>.Failed("对比失败:" + msg);
throw new Exception($"根据BC子任务主键{taskBcId}未查询到BC信息");
}
var taskBcCtnList = await tenantDb.Queryable<TaskBCCTNInfo>().Where(x => x.P_ID == taskBcInfo.Id).ToListAsync();
// 运费协议号(约号)是唯一的,服务合同号可能不是唯一的
var seaExport = await tenantDb.Queryable<SeaExport>().Where(x => x.MBLNO == taskBcInfo.MBL_NO).FirstAsync();
if (seaExport == null)
{
throw new Exception($"根据提单号:{taskBcInfo.MBL_NO}未查询到海运出口订单信息");
}
var seaExportCtnList = await tenantDb.Queryable<OpCtn>().Where(x => x.BSNO == seaExport.Id.ToString()).ToListAsync();
// 运费协议号(约号)是唯一的,服务合同号可能不是唯一的
// BC信息
ParserBCInfoDto bcSrcDto = new ParserBCInfoDto()
{
ContractNo = taskBcInfo.CONTRACTNO,
Vessel = taskBcInfo.VESSEL,
VoyNo = taskBcInfo.VOYNO,
//TemperatureMin = taskBcInfo
//TemperatureMin = seaExport.TemperatureMin,
//TemperatureMax = seaExport.TemperatureMax,
//TemperatureSet = seaExport.TemperatureSet,
Humidity = seaExport.Humidity,
DischargePort = taskBcInfo.PORTDISCHARGE,
Destination = taskBcInfo.PLACEDELIVERY,
ETD = taskBcInfo.ETD?.ToString("yyyy-MM-dd"),
CtnList = taskBcCtnList.GroupBy(x => x.CTNALL).Select(x => new ParserBCCTNInfoDto
{
CtnALL = x.Key,
CtnNum = x.ToList().Sum(a => a.CTNNUM)
}).ToList()
};
//bcTargetDto.CtnList = dto.DataObj.CtnList.GroupBy(x => x.CtnAll)
// .Select(x =>
// {
// return new ParserBCCTNInfoDto
// {
// CtnALL = x.Key,
// CtnNum = x.ToList().Sum(a => a.CtnNum)
// };
// }).ToList();
var seaExport = await tenantDb.Queryable<SeaExport>().Where(x => x.MBLNO == taskBcInfo.MBL_NO).FirstAsync();
// 订单信息
ParserBCInfoDto bcTargetDto = new ParserBCInfoDto()
@ -1176,20 +1179,26 @@ namespace DS.WMS.Core.TaskPlat.Method
Humidity = seaExport.Humidity,
DischargePort = seaExport.DischargePort,
Destination = seaExport.Destination,
ETD = seaExport.ETD?.ToString("yyyy-MM-dd"),
//CtnList = new List<ParserBCCTNInfoDto>(),
CtnList = seaExportCtnList.GroupBy(x => x.CtnAll).Select(x => new ParserBCCTNInfoDto
{
CtnALL = x.Key,
CtnNum = x.ToList().Sum(a => a.CtnNum)
}).ToList()
};
//if (seaExport.CargoId == "R" && seaExport.EdiRemark)
//{
//}
}
catch (Exception)
catch (Exception ex)
{
throw;
logger.LogInformation("对比失败:" + ex.Message);
return DataResult<TaskManageExcuteResultDto>.Failed("对比失败:" + ex.Message);
}
return default;
return DataResult<TaskManageExcuteResultDto>.Success(default);
}
#region 生成并推送邮件

@ -9,6 +9,7 @@ using DS.Module.SqlSugar;
using DS.Module.UserModule;
using DS.WMS.Core.Code.Dtos;
using DS.WMS.Core.Code.Interface;
using DS.WMS.Core.Invoice.Dtos;
using DS.WMS.Core.Map.Dtos;
using DS.WMS.Core.Map.Interface;
using DS.WMS.Core.Op.Entity;
@ -2205,10 +2206,9 @@ namespace DS.WMS.Core.TaskPlat.Method
IsPublic = t.IS_PUBLIC
}).ToListAsync();
//var sql = tenantDb.Queryable<TaskBaseInfo>()
// .LeftJoin<TaskBaseAllocation>((t, a) => t.Id == a.TaskId)
// .Where(whereList)
// .Where((t, a) => t.IS_PUBLIC == 1 || (t.IS_PUBLIC == 0 && a.Status != null && (t.CreateBy == userId || a.UserId == userId)))
// .GroupBy((t, a) => new { t.TASK_TYPE, t.STATUS, a.Status, t.IS_PUBLIC })
// .Select((t, a) => new
@ -2748,6 +2748,36 @@ namespace DS.WMS.Core.TaskPlat.Method
return DataResult<CodePortRes>.FailedData(portInfo);
}
public async Task<DataResult> TestTaskFlow(string taskType, long taskId)
{
var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId);
var taskTypeEnum = (TaskBaseTypeEnum)Enum.Parse(typeof(TaskBaseTypeEnum), taskType);
TaskManageOrderMessageInfo p1 = new TaskManageOrderMessageInfo()
{
Main = new TaskManageOrderMessageMainInfo()
{
BCInfo = new TaskManageOrderBCInfo()
{
Vessel = "TESTVESSEL"
}
}
};
TaskFlowDataContext dataContext = new(
((TaskFlowDataNameConst.TaskManageOrderMessageInfo), p1),
(("Name"), "QD-ZXF"),
(("Age"), 19),
(("Height"), 160)
);
TaskFlowRuner taskFlow = new TaskFlowRuner(tenantDb, serviceProvider);
await taskFlow.Run(taskTypeEnum, taskId, dataContext);
return DataResult.Successed("测试成功");
}
#endregion
}
}

@ -0,0 +1,37 @@
namespace DS.WMS.Core.TaskPlat.Other
{
public class ContitionContent
{
/// <summary>
/// 逻辑操作符
/// </summary>
public string LogicalOperator { get; set; }
/// <summary>
/// 条件组
/// </summary>
public List<ConditionDetail> Conditions { get; set; }
/// <summary>
/// 条件组
/// </summary>
public List<ContitionContent> Groups { get; set; }
}
public class ConditionDetail
{
/// <summary>
/// 字段
/// </summary>
public string Field { get; set; }
/// <summary>
/// 操作符
/// </summary>
public string Operator { get; set; }
/// <summary>
/// 值
/// </summary>
public string Value { get; set; }
}
}

@ -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,81 +67,24 @@ 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))
.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 (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;
}
}
else if (conditionItem.MatchType == 3)
{
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)
if (MatchByCondition(contitionContent, dataContext))
{
configMatchCount[configItem.Id] = oldValue + 1;
}
@ -148,7 +92,7 @@ namespace DS.WMS.Core.TaskPlat
{
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)
TaskFlowLogDetail flowLogDetail = new()
{
PId = flowLog.Id,
IsSuccess = true,
};
TaskFlowConfig? executeConfig = null;
try
{
if (waitMatchConfigList == null || waitMatchConfigList.Count == 0)
{
break;
}
var executeConfig = configList.FirstOrDefault(x => x.Id == nextExecuteConfigId);
if (executeConfig == null)
// 对节点列表里面的节点进行依次判断,取出要执行的节点
var matchedConfigList = new List<TaskFlowConfig>();
foreach (var waitMatchConfigItem in waitMatchConfigList)
{
break;
var condition = conditionList.FirstOrDefault(x => x.ConfigId == waitMatchConfigItem.Id);
if (condition == null || string.IsNullOrEmpty(condition.Content))
{
matchedConfigList.Add(waitMatchConfigItem);
continue;
}
nextExecuteConfigId = executeConfig.NextExecuteConfigId;
TaskFlowLogDetail flowLogDetail = new()
var contitionContent = JsonConvert.DeserializeObject<ContitionContent>(condition.Content)!;
if (MatchByCondition(contitionContent, dataContext))
{
ConfigId = executeConfig.Id,
PId = flowLog.Id,
IsSuccess = true,
};
try
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>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<NameOfLastUsedPublishProfile>D:\Code\ds8-solution-pro\ds-wms-service\DS.WMS.OpApi\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
<NameOfLastUsedPublishProfile>D:\Source\Repos\DS8\ds-wms-service\DS.WMS.OpApi\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
<Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
<Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
</PropertyGroup>

@ -1,10 +1,14 @@
using DS.Module.Core;
using DS.Module.Core.Attributes;
using DS.Module.Core.Data;
using DS.Module.DjyServiceStatus;
using DS.WMS.Core.Invoice.Dtos;
using DS.WMS.Core.TaskPlat;
using DS.WMS.Core.TaskPlat.Dtos;
using DS.WMS.Core.TaskPlat.Interface;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
namespace DS.WMS.TaskApi.Controllers;
@ -207,4 +211,13 @@ public class TaskManageController : ApiController
return PhysicalFile(fileFullPath, "application/octet-stream", fileName);
}
/// <summary>
/// 测试执行任务编排
/// </summary>
/// <returns></returns>
[HttpGet("TestTaskFlow")]
public async Task<DataResult> TestTaskFlow([FromQuery] string taskType, [FromQuery] long taskId)
{
return await taskManageService.TestTaskFlow(taskType, taskId);
}
}

@ -46,7 +46,6 @@ builder.Services.AddSaasDbInstall();//
builder.Services.AddMultiLanguageInstall();//多语言服务
builder.Services.AddDjyModuleInstall();//Djy服务
builder.Services.AddRuleEngineModuleInstall();//Djy规则引擎校验服务
builder.Services.AddTaskPlatMapsterSetup(); // 全局的Mapster自定义映射规则
// builder.Services.AddEndpointsApiExplorer();
// builder.Services.AddSwaggerGen();

Loading…
Cancel
Save