diff --git a/src/BuildFlow.Host/Endpoints/Workflow/WorkflowInstance/UpdateWorkflowInstanceVariablesEndpoint.cs b/src/BuildFlow.Host/Endpoints/Workflow/WorkflowInstance/UpdateWorkflowInstanceVariablesEndpoint.cs new file mode 100644 index 0000000..7211df8 --- /dev/null +++ b/src/BuildFlow.Host/Endpoints/Workflow/WorkflowInstance/UpdateWorkflowInstanceVariablesEndpoint.cs @@ -0,0 +1,30 @@ +using MediatR; +using Workflow.Application.Features.WorkflowInstances.Commands; + +namespace BuildFlow.Host.Endpoints.Workflow.WorkflowInstance; + +/// +/// 更新单个流程实例的运行时变量。用于人工干预修正流程数据(仅改 Variables,不动状态/定义版本)。 +/// +public class UpdateWorkflowInstanceVariablesEndpoint(IMediator mediator) + : Endpoint +{ + public override void Configure() + { + Put("/workflow-instances/{Id}/variables"); + Permissions("workflow-instance:manage"); + Summary(s => + { + s.Summary = "Update variables of a single workflow instance"; + }); + } + + public override async Task HandleAsync(UpdateWorkflowInstanceVariablesRequest req, CancellationToken ct) + { + var id = Route("Id"); + await mediator.Send(new UpdateWorkflowInstanceVariablesCommand(id, req.Variables), ct); + HttpContext.Response.StatusCode = 200; + HttpContext.Response.ContentType = "application/json"; + await HttpContext.Response.WriteAsync("{}", ct); + } +} diff --git a/src/BuildFlow.Host/Endpoints/Workflow/WorkflowInstance/UpdateWorkflowInstanceVariablesRequest.cs b/src/BuildFlow.Host/Endpoints/Workflow/WorkflowInstance/UpdateWorkflowInstanceVariablesRequest.cs new file mode 100644 index 0000000..83e919e --- /dev/null +++ b/src/BuildFlow.Host/Endpoints/Workflow/WorkflowInstance/UpdateWorkflowInstanceVariablesRequest.cs @@ -0,0 +1,10 @@ +namespace BuildFlow.Host.Endpoints.Workflow.WorkflowInstance; + +/// +/// 更新流程实例变量请求体。 +/// +public class UpdateWorkflowInstanceVariablesRequest +{ + /// 新的流程变量 JSON(必须是 JSON 对象,如 {"amount": 5000, "level": 3})。 + public string Variables { get; set; } = string.Empty; +} diff --git a/src/modules/workflow/Application/Features/WorkflowInstances/Commands/UpdateWorkflowInstanceVariablesCommand.cs b/src/modules/workflow/Application/Features/WorkflowInstances/Commands/UpdateWorkflowInstanceVariablesCommand.cs new file mode 100644 index 0000000..a400da3 --- /dev/null +++ b/src/modules/workflow/Application/Features/WorkflowInstances/Commands/UpdateWorkflowInstanceVariablesCommand.cs @@ -0,0 +1,11 @@ +using MediatR; + +namespace Workflow.Application.Features.WorkflowInstances.Commands; + +/// +/// 更新单个流程实例的运行时变量(Variables)命令。 +/// 用于人工干预修正流程数据(如表单填错、条件分支走错),仅改 Variables,不动状态、定义版本、token。 +/// +public record UpdateWorkflowInstanceVariablesCommand( + Guid InstanceId, + string Variables) : IRequest; diff --git a/src/modules/workflow/Application/Features/WorkflowInstances/Handlers/UpdateWorkflowInstanceVariablesCommandHandler.cs b/src/modules/workflow/Application/Features/WorkflowInstances/Handlers/UpdateWorkflowInstanceVariablesCommandHandler.cs new file mode 100644 index 0000000..e60bff9 --- /dev/null +++ b/src/modules/workflow/Application/Features/WorkflowInstances/Handlers/UpdateWorkflowInstanceVariablesCommandHandler.cs @@ -0,0 +1,43 @@ +using System.Text.Json; +using MediatR; +using Workflow.Application.Features.WorkflowInstances.Commands; +using Workflow.Infrastructure.Persistence; + +namespace Workflow.Application.Features.WorkflowInstances.Handlers; + +/// +/// 更新流程实例变量处理器。校验实例存在且 Variables 为合法 JSON 对象后覆盖写入。 +/// 不校验实例状态:Running/Suspended/Completed 均允许修正变量(人工干预场景)。 +/// +public class UpdateWorkflowInstanceVariablesCommandHandler(WorkflowDbContext db) + : IRequestHandler +{ + public async Task Handle(UpdateWorkflowInstanceVariablesCommand request, CancellationToken ct) + { + var instance = await db.WorkflowInstances.FindAsync([request.InstanceId], ct) + ?? throw new NotFoundException($"Workflow instance '{request.InstanceId}' not found."); + + // 校验 Variables 是合法 JSON 对象,避免脏数据破坏引擎条件求值(ParseVariables 会吞异常返回空, + // 但这里前置校验能给出明确错误而非静默丢失变量) + ValidateVariablesJson(request.Variables); + + instance.Variables = request.Variables; + await db.SaveChangesAsync(ct); + + return Unit.Value; + } + + private static void ValidateVariablesJson(string variables) + { + try + { + using var doc = JsonDocument.Parse(variables); + if (doc.RootElement.ValueKind != JsonValueKind.Object) + throw new BusinessException("流程变量必须是 JSON 对象(如 {\"key\":\"value\"})。"); + } + catch (JsonException ex) + { + throw new BusinessException($"流程变量不是合法的 JSON:{ex.Message}"); + } + } +}