using Abp; using Abp.Dependency; using Abp.Domain.Repositories; using Abp.Domain.Services; using Abp.Domain.Uow; using Abp.Json; using Abp.UI; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using VberZero.Workflow.DesignInfo; using VberZero.Workflow.StepBodies; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Models.DefinitionStorage.v1; using WorkflowCore.Services.DefinitionStorage; namespace VberZero.Workflow; public class VberWorkflowManager : DomainService, IVberWorkflowManager, ITransientDependency { protected readonly WorkflowStepBodyManager _workflowStepBodyManager; protected IWorkflowHost _workflowHost; protected readonly IWorkflowController _workflowService; protected readonly IWorkflowRegistry _registry; public IVberPersistenceProvider PersistenceProvider { get; } protected readonly ISearchIndex _searchService; protected readonly IDefinitionLoader _definitionLoader; protected readonly IRepository _workflowDefinitionRepository; protected IReadOnlyCollection _stepBodies; public IQueryable WorkflowDefinitions => _workflowDefinitionRepository.GetAll(); public VberWorkflowManager(WorkflowStepBodyManager workflowStepBodyManager, IWorkflowHost workflowHost, IWorkflowController workflowService, IWorkflowRegistry registry, IVberPersistenceProvider workflowStore, ISearchIndex searchService, IDefinitionLoader definitionLoader, IRepository workflowDefinitionRepository ) { _workflowStepBodyManager = workflowStepBodyManager; _workflowHost = workflowHost; _workflowService = workflowService; _registry = registry; PersistenceProvider = workflowStore; _searchService = searchService; _definitionLoader = definitionLoader; _workflowDefinitionRepository = workflowDefinitionRepository; _stepBodies = _workflowStepBodyManager.GetAllStepBodies(); } /// /// 终止流程 /// /// /// public virtual async Task TerminateWorkflow(string workflowId) { return await _workflowService.TerminateWorkflow(workflowId); } public virtual WorkflowDefinition GetDefinition(string workflowId, int? version = null) { return _registry.GetDefinition(workflowId, version); } /// /// 初始化注册流程 /// internal void Initialize() { using (UnitOfWorkManager.Begin()) { using (UnitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant)) { var definitions = WorkflowDefinitions.ToList(); foreach (var workflow in definitions) { LoadDefinition(workflow); } } } } /// /// /// /// public virtual IEnumerable GetAllStepBodies() { return _stepBodies; } public virtual async Task PublishEventAsync(string eventName, string eventKey, object eventData) { await _workflowHost.PublishEvent(eventName, eventKey, eventData); } /// /// 创建流程 /// /// /// [UnitOfWork] public virtual async Task CreateAsync(WorkflowDefinitionInfo entity) { LoadDefinition(entity); await _workflowDefinitionRepository.InsertAsync(entity); } /// /// 删除指定版本 /// /// /// /// [UnitOfWork] public virtual async Task DeleteAsync(string id, int version) { var entity = await _workflowDefinitionRepository.FirstOrDefaultAsync(a => a.Id == id && a.Version == version); var all = await PersistenceProvider.GetAllRunnablePersistedWorkflow(entity.Id, entity.Version); if (all.Any()) { throw new UserFriendlyException($"编号:{entity.Id},版本:{entity.Version}的流程无法删除!还有没有执行完的流程!"); } if (_registry.IsRegistered(entity.Id, entity.Version)) { _registry.DeregisterWorkflow(entity.Id, entity.Version); } await _workflowDefinitionRepository.DeleteAsync(entity); } /// /// 删除全部版本 /// /// /// [UnitOfWork] public virtual async Task DeleteAsync(string id) { var entities = await _workflowDefinitionRepository.GetAllListAsync(a => a.Id == id); foreach (var entity in entities) { await DeleteAsync(entity.Id, entity.Version); } } /// /// 更新 /// /// /// [UnitOfWork] public virtual async Task UpdateAsync(WorkflowDefinitionInfo entity) { if (_registry.IsRegistered(entity.Id, entity.Version)) { _registry.DeregisterWorkflow(entity.Id, entity.Version); } LoadDefinition(entity); await _workflowDefinitionRepository.UpdateAsync(entity); } /// /// 启动工作流 /// /// public virtual async Task StartWorkflow(string id, int version, Dictionary inputs, string reference = null) { if (!_registry.IsRegistered(id, version)) { throw new UserFriendlyException("工作流未定义!"); } return await _workflowHost.StartWorkflow(id, version, inputs, reference); } /// /// 注册工作流 /// /// /// internal WorkflowDefinition LoadDefinition(WorkflowDefinitionInfo input) { if (_registry.IsRegistered(input.Id, input.Version)) { throw new AbpException($"工作流[{input.Id}]已定义 "); } var source = new DefinitionSourceV1 { Id = input.Id, Version = input.Version, Description = input.Title, DataType = $"{typeof(Dictionary).FullName}, {typeof(Dictionary).Assembly.FullName}" }; BuildWorkflow(input.Nodes, source, _stepBodies, input.Nodes.First(u => u.Key.ToLower().StartsWith("start"))); var json = source.ToJsonString(); Logger.DebugFormat("Workflow Json:{0}", json); var def = _definitionLoader.LoadDefinition(json, Deserializers.Json); return def; } protected virtual void BuildWorkflow(IEnumerable allNodes, DefinitionSourceV1 source, IEnumerable stepBodies, WorkflowNode node) { if (source.Steps.Any(u => u.Id == node.Key)) { return; } var stepSource = new StepSourceV1 { Id = node.Key, Name = node.Key }; VberWorkflowStepBody stepBody = stepBodies.FirstOrDefault(u => node.StepBody != null && u.Name == node.StepBody.Name) ?? new VberWorkflowStepBody() { StepBodyType = typeof(NullStepBody) }; stepSource.StepType = $"{stepBody.StepBodyType.FullName}, {stepBody.StepBodyType.Assembly.FullName}"; foreach (var input in stepBody.Inputs) { var value = input.Value.Value; var key = FirstToLower(input.Key); if (node.StepBody.Inputs.ContainsKey(key)) { value = node.StepBody.Inputs[key].Value; } if (!(value is IDictionary || value is IDictionary)) { value = $"\"{value}\""; } stepSource.Inputs.TryAdd(input.Key, value); } source.Steps.Add(stepSource); BuildBranching(allNodes, source, stepSource, stepBodies, node.NextNodes); } protected virtual void BuildBranching(IEnumerable allNodes, DefinitionSourceV1 source, StepSourceV1 stepSource, IEnumerable stepBodies, IEnumerable nodes) { foreach (var nextNode in nodes) { var node = allNodes.First(u => u.Key == nextNode.NodeId); stepSource.SelectNextStep[nextNode.NodeId] = "1==1"; if (nextNode.Conditions.Any()) { List expList = new List(); foreach (var cond in nextNode.Conditions) { if (cond.Value is string && (!decimal.TryParse(cond.Value.ToString(), out _))) { if (cond.Operator != "==" && cond.Operator != "!=") { throw new AbpException($" if {cond.Field} is type of 'String', the Operator must be \"==\" or \"!=\""); } expList.Add($"data[\"{cond.Field}\"].ToString() {cond.Operator} \"{cond.Value}\""); continue; } expList.Add($"decimal.Parse(data[\"{cond.Field}\"].ToString()) {cond.Operator} {cond.Value}"); } stepSource.SelectNextStep[nextNode.NodeId] = string.Join(" && ", expList); } BuildWorkflow(allNodes, source, stepBodies, node); } } private string FirstToLower(string str) { return str.Substring(0, 1).ToLower() + str.Substring(1); } }