diff --git a/OpenAuth.App/Flow/FlowRuntime.cs b/OpenAuth.App/Flow/FlowRuntime.cs index a163df0b..a458570a 100644 --- a/OpenAuth.App/Flow/FlowRuntime.cs +++ b/OpenAuth.App/Flow/FlowRuntime.cs @@ -538,6 +538,57 @@ namespace OpenAuth.App.Flow } } + /// + /// 撤销当前节点的审批 + /// + public void UndoVerification() + { + // 已结束的流程不能撤销 + if (flowInstance.IsFinish == FlowInstanceStatus.Finished + || flowInstance.IsFinish == FlowInstanceStatus.Rejected) + { + throw new Exception("流程已结束,不能撤销"); + } + + if(Nodes[previousId].type == FlowNode.START) + { + throw new Exception("没有任何审批,不能撤销!你可以删除或召回这个流程"); + } + + // 恢复到上一个节点 + currentNodeId = flowInstance.PreviousId; + flowInstance.ActivityId = currentNodeId; + flowInstance.ActivityType = GetNodeType(currentNodeId); + flowInstance.ActivityName = Nodes[currentNodeId].name; + //向前查找ActivityId的前一个结点,即连线指向ActivityId的节点 + flowInstance.PreviousId = GetPreNode().id; + flowInstance.MakerList = GetNodeMarkers(Nodes[currentNodeId]); + + // 清除当前节点的审批状态 + currentNode.setInfo.Taged = null; + currentNode.setInfo.UserId = ""; + currentNode.setInfo.UserName = ""; + currentNode.setInfo.Description = ""; + currentNode.setInfo.TagedTime = ""; + + //删除当前节点的扭转记录 + var user = AutofacContainerModule.GetService().GetCurrentUser().User; + var SugarClient = AutofacContainerModule.GetService(); + SugarClient.Deleteable().Where(u => u.InstanceId == flowInstanceId && u.CreateUserId == user.Id && u.FromNodeId == currentNodeId).ExecuteCommand(); + + //删除当前节点的审批记录(只删除最新的一条) + var latestRecord = SugarClient.Queryable() + .Where(u => u.InstanceId == flowInstanceId && u.CreateUserId == user.Id) + .OrderByDescending(u => u.CreateDate) + .First(); + if (latestRecord != null) + { + SugarClient.Deleteable() + .Where(u => u.Id == latestRecord.Id) + .ExecuteCommand(); + } + } + #endregion 共有方法 #region 获取节点审批人 diff --git a/OpenAuth.App/FlowInstance/FlowInstanceApp.cs b/OpenAuth.App/FlowInstance/FlowInstanceApp.cs index 912d84b2..85c5b826 100644 --- a/OpenAuth.App/FlowInstance/FlowInstanceApp.cs +++ b/OpenAuth.App/FlowInstance/FlowInstanceApp.cs @@ -2,7 +2,7 @@ * @Author: yubaolee | ahfu~ <954478625@qq.com> * @Date: 2024-12-13 16:55:17 * @Description: 工作流实例表操作 - * @LastEditTime: 2025-02-26 10:39:03 + * @LastEditTime: 2025-03-08 13:59:47 * Copyright (c) 2024 by yubaolee | ahfu~ , All Rights Reserved. */ @@ -332,6 +332,40 @@ namespace OpenAuth.App return true; } + /// + /// 撤销当前节点的审批 + /// + public void UndoVerification(UndoVerificationReq request) + { + var flowInstance = Get(request.FlowInstanceId); + var user = _auth.GetCurrentUser().User; + + // 获取运行实例 + var wfruntime = new FlowRuntime(flowInstance); + + SugarClient.Ado.BeginTran(); + try + { + wfruntime.UndoVerification(); + + // 更新流程实例状态 + flowInstance.IsFinish = FlowInstanceStatus.Running; + flowInstance.SchemeContent = JsonHelper.Instance.Serialize(wfruntime.ToSchemeObj()); + + SugarClient.Updateable(flowInstance).ExecuteCommand(); + + // 记录撤销操作 + // wfruntime.SaveOperationHis($"【撤销审批】{user.Name}撤销了对【{wfruntime.currentNode.name}】的审批。备注:{request.Description}"); + + SugarClient.Ado.CommitTran(); + } + catch (Exception ex) + { + SugarClient.Ado.RollbackTran(); + throw new Exception("撤销审批失败:" + ex.Message); + } + } + /// /// 会签 /// @@ -590,7 +624,16 @@ namespace OpenAuth.App resp.NextNodeDesignateType = runtime.nextNode.setInfo.NodeDesignate; resp.CanWriteFormItemIds = runtime.currentNode.setInfo.CanWriteFormItemIds; } - + + var user = _auth.GetCurrentUser(); + var query = SugarClient.Queryable() + .OrderByDescending(u => u.CreateDate) + .First(u => u.InstanceId == id); + if (query != null) + { + //最后一个审批人是当前用户,可以撤销 + resp.CanUndoVerify = query.CreateUserId == user.User.Id; + } return resp; } diff --git a/OpenAuth.App/FlowInstance/Response/FlowVerificationResp.cs b/OpenAuth.App/FlowInstance/Response/FlowVerificationResp.cs index 00a0527d..e45fe698 100644 --- a/OpenAuth.App/FlowInstance/Response/FlowVerificationResp.cs +++ b/OpenAuth.App/FlowInstance/Response/FlowVerificationResp.cs @@ -37,5 +37,17 @@ namespace OpenAuth.App.Response /// 当前节点的可写表单Id /// public string[] CanWriteFormItemIds { get; set; } + + /// + /// 是否可以撤销审核 + ///流程最后一个已审批节点的审批人是当前登录人 + /// + public bool CanUndoVerify { get; set; } + + /// + /// 是否可以审核 + ///待审批的节点需要当前登录人审批 + /// + public bool CanVerify{ get; set; } } } diff --git a/OpenAuth.WebApi/Controllers/FlowInstancesController.cs b/OpenAuth.WebApi/Controllers/FlowInstancesController.cs index ca79097f..b8e07a62 100644 --- a/OpenAuth.WebApi/Controllers/FlowInstancesController.cs +++ b/OpenAuth.WebApi/Controllers/FlowInstancesController.cs @@ -167,6 +167,27 @@ namespace OpenAuth.WebApi.Controllers return response; } + /// + /// 撤销最后一个节点审批 + /// + /// + [HttpPost] + public Response UndoVerification([FromBody] UndoVerificationReq request) + { + var result = new Response(); + try + { + _app.UndoVerification(request); + } + catch (Exception ex) + { + result.Code = 500; + result.Message = ex.InnerException?.Message ?? ex.Message; + } + + return result; + } + /// /// 加载列表 /// @@ -194,6 +215,9 @@ namespace OpenAuth.WebApi.Controllers return result; } + + + public FlowInstancesController(FlowInstanceApp app) { _app = app; diff --git a/docs/core/flowinstancestatus.md b/docs/core/flowinstancestatus.md index 72c9e0b9..6c83b111 100644 --- a/docs/core/flowinstancestatus.md +++ b/docs/core/flowinstancestatus.md @@ -4,7 +4,7 @@ #### IsFinish:流程的当前状态 -- -1 草稿/召回:流程发起人主动撤销流程;【新增】 +- -1 草稿/召回:流程发起人主动召回流程; - 0 正在运行; @@ -15,6 +15,8 @@ - 4 驳回:流程结束,可能发起的流程内容有问题,要求被驳回重新提交; +#### ActivityId: 当前活动节点,即待审批的节点 + #### ActivityType:当前节点的类型 - -1 无法运行, @@ -121,3 +123,11 @@ - 3:开始节点,即type为:‘start’; - 4:流程运行结束,即type为’end’; + +与流程实例密切相关的还有两个表:流程实例的操作记录FlowInstanceOperationHistory及流转记录FlowInstanceTransitionHistory。它们有不同的作用: + +### 操作记录FlowInstanceOperationHistory +该表记录了流程实例的所有操作记录,包括流程的创建、撤回、驳回、同意、不同意等操作。 + +### 流转记录FlowInstanceTransitionHistory +记录某个流程实例所有已审批的从一个活动节点到下一个活动节点的操作人、操作时间。 \ No newline at end of file