CreateOrUpdateTaskTemplateCommandHandler.cs 10.2 KB
using MassTransit;
using Microsoft.Extensions.Logging;
using Rcs.Application.Common;
using Rcs.Application.MessageBus.Commands;
using Rcs.Domain.Entities;
using Rcs.Domain.Repositories;
using Rcs.Domain.Enums;

namespace Rcs.Infrastructure.MessageBus.Handlers.Commands;

public class CreateOrUpdateTaskTemplateCommandHandler : IConsumer<CreateOrUpdateTaskTemplateCommand>
{
    private readonly ILogger<CreateOrUpdateTaskTemplateCommandHandler> _logger;
    private readonly ITaskTemplateRepository _taskTemplateRepository;

    public CreateOrUpdateTaskTemplateCommandHandler(
        ILogger<CreateOrUpdateTaskTemplateCommandHandler> logger,
        ITaskTemplateRepository taskTemplateRepository)
    {
        _logger = logger;
        _taskTemplateRepository = taskTemplateRepository;
    }

    public async Task Consume(ConsumeContext<CreateOrUpdateTaskTemplateCommand> context)
    {
        var command = context.Message;

        try
        {
            // 默认模板唯一性校验 @author zzy
            if (command.IsDefault)
            {
                Guid? excludeId = Guid.TryParse(command.TemplateId, out var tid) ? tid : null;
                var existingDefault = await _taskTemplateRepository.GetDefaultTemplateAsync(
                    (RobotType)command.RobotType,
                    command.Manufacturer,
                    excludeId,
                    context.CancellationToken);

                if (existingDefault != null)
                {
                    throw new InvalidOperationException(
                        $"机器人类型 {(RobotType)command.RobotType} 和制造商 {command.Manufacturer ?? ""} 已存在默认模板:{existingDefault.TemplateName}");
                }
            }

            if(!Guid.TryParse(command.TemplateId, out Guid templateId))
            {
                // 创建新模板
                var existingTemplate = await _taskTemplateRepository.GetByTemplateCodeAsync(
                    command.TemplateCode,
                    context.CancellationToken);

                if (existingTemplate != null)
                {
                    throw new InvalidOperationException($"模板编码 {command.TemplateCode} 已存在");
                }

                var template = TaskTemplate.Create(
                    command.TemplateCode,
                    command.TemplateName,
                    (RobotType)(command.RobotType),
                    command.Description,
                    command.Manufacturer,
                    command.IsEnabled,
                    command.IsDefault
                );

                // 创建任务步骤
                foreach (var stepDto in command.TaskSteps)
                {
                    var step = new TaskStep
                    {
                        StepId = Guid.NewGuid(),
                        TemplateId = template.TemplateId,
                        Type = (TaskStepType)stepDto.Type,
                        StepName = stepDto.StepName,
                        Description = stepDto.Description,
                        Order = stepDto.Order,
                        CreatedAt = DateTime.Now,
                        UpdatedAt = DateTime.Now
                    };

                    // 创建步骤属性
                    foreach (var propDto in stepDto.Properties)
                    {
                        var property = new StepProperty
                        {
                            PropertyId = Guid.NewGuid(),
                            StepId = step.StepId,
                            PropertyType = (StepPropertyType)propDto.PropertyType,
                            NodeValue = (NodeValueType)propDto.NodeValue,
                            AfterActionType = (AfterActionType)propDto.AfterActionType,
                            RequestMethod = propDto.RequestMethod,
                            RequestUrl = propDto.RequestUrl,
                            RequestParams = propDto.RequestParams,
                            RepeatCount = propDto.RepeatCount,
                            IntervalTimeMs = propDto.IntervalTimeMs,
                            WaitResponseFlag = propDto.WaitResponseFlag,
                            ResponseValidationRule = propDto.ResponseValidationRule,
                            Description = propDto.Description,
                            ExtraProperties = propDto.ExtraProperties,
                            CreatedAt = DateTime.Now,
                            UpdatedAt = DateTime.Now
                        };

                        // 创建动作
                        foreach (var actionDto in propDto.Actions)
                        {
                            var action = new StepAction
                            {
                                ActionId = Guid.NewGuid(),
                                PropertyId = property.PropertyId,
                                Type = actionDto.Type,
                                StepName = actionDto.StepName,
                                Description = actionDto.Description,
                                BlockingType = (ActionBlockType)actionDto.BlockingType,
                                Order = actionDto.Order,
                                CreatedAt = DateTime.Now,
                                UpdatedAt = DateTime.Now
                            };
                            property.Actions.Add(action);
                        }
                        
                        step.Properties.Add(property);
                    }

                    template.TaskSteps.Add(step);
                }

                await _taskTemplateRepository.AddAsync(template, context.CancellationToken);
            }
            else
            {
                // 更新模板
                var template = await _taskTemplateRepository.GetWithFullDetailsAsync(
                    templateId,
                    context.CancellationToken);
                if (template == null)
                    throw new InvalidOperationException($"未找到模板ID为 {templateId} 的任务模板");

                template.Update(
                    command.TemplateCode,
                    command.TemplateName,
                    (RobotType)(command.RobotType),
                    command.Description,
                    command.Manufacturer,
                    command.IsEnabled,
                    command.IsDefault
                );

                // 手动删除所有子实体
                foreach (var step in template.TaskSteps.ToList())
                {
                    foreach (var prop in step.Properties.ToList())
                    {
                        foreach (var action in prop.Actions.ToList())
                        {
                            prop.Actions.Remove(action);
                        }
                        step.Properties.Remove(prop);
                    }
                    template.TaskSteps.Remove(step);
                }

                // 重新创建步骤
                foreach (var stepDto in command.TaskSteps)
                {
                    var step = new TaskStep
                    {
                        StepId = Guid.NewGuid(),
                        TemplateId = template.TemplateId,
                        Type = (TaskStepType)stepDto.Type,
                        StepName = stepDto.StepName,
                        Description = stepDto.Description,
                        Order = stepDto.Order,
                        CreatedAt = DateTime.Now,
                        UpdatedAt = DateTime.Now
                    };

                    // 创建步骤属性
                    foreach (var propDto in stepDto.Properties)
                    {
                        var property = new StepProperty
                        {
                            PropertyId = Guid.NewGuid(),
                            StepId = step.StepId,
                            PropertyType = (StepPropertyType)propDto.PropertyType,
                            NodeValue = (NodeValueType)propDto.NodeValue,
                            AfterActionType = (AfterActionType)propDto.AfterActionType,
                            RequestMethod = propDto.RequestMethod,
                            RequestUrl = propDto.RequestUrl,
                            RequestParams = propDto.RequestParams,
                            RepeatCount = propDto.RepeatCount,
                            IntervalTimeMs = propDto.IntervalTimeMs,
                            WaitResponseFlag = propDto.WaitResponseFlag,
                            ResponseValidationRule = propDto.ResponseValidationRule,
                            Description = propDto.Description,
                            ExtraProperties = propDto.ExtraProperties,
                            CreatedAt = DateTime.Now,
                            UpdatedAt = DateTime.Now
                        };

                        // 创建动作
                        foreach (var actionDto in propDto.Actions)
                        {
                            var action = new StepAction
                            {
                                ActionId = Guid.NewGuid(),
                                PropertyId = property.PropertyId,
                                Type = actionDto.Type,
                                StepName = actionDto.StepName,
                                Description = actionDto.Description,
                                BlockingType = (ActionBlockType)actionDto.BlockingType,
                                Order = actionDto.Order,
                                CreatedAt = DateTime.Now,
                                UpdatedAt = DateTime.Now
                            };
                            property.Actions.Add(action);
                        }
                        
                        step.Properties.Add(property);
                    }

                    template.TaskSteps.Add(step);
                }

                await _taskTemplateRepository.UpdateAsync(template, context.CancellationToken);
            }

            await context.RespondAsync(ApiResponse.Successful());
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "创建或更新任务模板失败");
            await context.RespondAsync(ApiResponse.Failed(ex.Message));
        }
    }
}