You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

842 lines
31 KiB
C#

using DS.Module.Core;
using DS.Module.Core.Data;
using DS.Module.Core.Extensions;
using DS.WMS.Core.Flow.Dtos;
using DS.WMS.Core.Flow.Entity;
using DS.WMS.Core.Flow.Interface;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Sys.Entity;
using Mapster;
using Newtonsoft.Json;
using SqlSugar;
namespace DS.WMS.Core.Flow.Method;
/// <summary>
/// 工作流服务
/// </summary>
public class FlowInstanceService : ServiceBase, IFlowInstanceService
{
static readonly ApiFox api;
static FlowInstanceService()
{
api = new ApiFox();
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="serviceProvider"></param>
public FlowInstanceService(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
/// <summary>
4 months ago
/// 当工作流类型为会签时,返回首个执行人
/// </summary>
/// <param name="instance">运行实例</param>
/// <returns></returns>
4 months ago
public static string GetNextMarkers(FlowInstance instance)
{
string[] markers = GetMarkers(instance);
if (instance.ActivityType == 0 && markers.Length > 0)
4 months ago
return markers[0];
4 months ago
return string.Empty;
}
/// <summary>
/// 获取当前工作流的所有执行人
/// </summary>
/// <param name="instance">运行实例</param>
/// <returns></returns>
4 months ago
public static string[] GetMarkers(FlowInstance instance)
{
4 months ago
if (instance.IsCompleted)
return [];
return instance.MakerList.Split(',', StringSplitOptions.RemoveEmptyEntries);
}
public DataResult<List<FlowInstanceRes>> GetListByPage(PageRequest request)
{
//序列化查询条件
var whereList = request.GetConditionalModels(Db);
var data = Db.Queryable<FlowInstance>().Where(a => a.MakerList == "1" || a.MakerList.Contains(User.UserId))
.LeftJoin<SysPermission>((a, b) => a.PermissionId == b.Id)
.Select((a, b) => new FlowInstanceRes
{
CreateTime = a.CreateTime,
}, true)
.Where(whereList).ToQueryPage(request.PageCondition);
return data;
}
/// <summary>
/// 确定是否为最后审批人
/// </summary>
/// <param name="taskType">任务类型</param>
/// <param name="bsId">业务ID</param>
/// <param name="bsType">业务类型</param>
/// <returns></returns>
public DataResult<bool> IsLastMarker(TaskBaseTypeEnum taskType, long bsId, BusinessType? bsType)
{
var flow = Db.Queryable<FlowInstance>().Where(x => x.AuditType == taskType && x.BusinessId == bsId && x.BusinessType == bsType && x.FlowStatus == FlowStatusEnum.Running)
.Select(x => new { x.Id, x.MakerList }).First();
bool isLastMarker = default;
if (flow != null && flow.MakerList == User.UserId)
isLastMarker = true;
return DataResult<bool>.Success(isLastMarker);
}
public DataResult EditFlowInstance(FlowInstanceReq req)
{
if (req.Id == 0)
{
return DataResult.Failed("非法请求!", MultiLanguageConst.IllegalRequest);
}
else
{
var info = Db.Queryable<FlowInstance>().Where(x => x.Id == req.Id).First();
if (!(info.FlowStatus == FlowStatusEnum.Draft || info.FlowStatus == FlowStatusEnum.Ready))
10 months ago
{
return DataResult.Failed("只能修改【就绪】和【撤销】状态的流程", MultiLanguageConst.FlowEditOnlyReadyAndCancel);
10 months ago
}
info = req.Adapt(info);
Db.Updateable(info).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand();
return DataResult.Successed("更新成功!", MultiLanguageConst.DataUpdateSuccess);
}
}
protected virtual FlowInstance? BuildInstance(CreateFlowInstanceReq req)
{
if (string.IsNullOrEmpty(req.TemplateId.ToString()))
return null;
10 months ago
FlowTemplate template = Db.Queryable<FlowTemplate>().First(x => x.Id == req.TemplateId);
return template == null ? null : new FlowInstance
{
CustomName = template.Name,
TemplateId = template.Id,
BusinessId = req.BusinessId,
BusinessType = req.BusinessType,
PermissionId = template.PermissionId,
ColumnView = template.ColumnView,
Content = template.Content,
MarkerNotifyURL = template.MakerNotifyURL,
CallbackURL = template.CallbackURL,
AuditType = template.AuditType
};
}
/// <summary>
/// 创建工作流实例
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public DataResult CreateFlowInstance(CreateFlowInstanceReq req)
{
var instance = BuildInstance(req);
if (instance == null)
return DataResult.Failed("该流程模板已不存在,请重新设计流程!", MultiLanguageConst.FlowTemplateNotExist);
var userName = Db.Queryable<SysUser>().Where(x => x.Id == long.Parse(User.UserId)).Select(x => x.UserName).First();
//创建运行实例
var runtime = CreateRuntimeService(instance);
if (runtime.ShouldSkip)
{
instance.FlowStatus = FlowStatusEnum.Approve;
instance.Note = "已设置为自动跳过工作流执行";
Db.Insertable(instance).ExecuteCommand();
var history1 = new FlowInstanceHistory
{
InstanceId = instance.Id,
Content = "【创建】"
+ userName
+ "创建了一个流程进程【"
+ instance.CustomName + "】",
UserName = userName
};
var history2 = new FlowInstanceHistory
{
InstanceId = instance.Id,
Content = "【审核】"
+ userName
+ "流程条件触发自动审核【"
+ instance.CustomName + "】",
UserName = userName
};
FlowInstanceHistory[] histories = [history1, history2];
Db.Insertable(histories).ExecuteCommand();
if (!string.IsNullOrEmpty(instance.CallbackURL))
Task.Factory.StartNew(() => RunCallbackAsync(instance));
var result = DataResult.Successed("创建工作流实例成功!", instance, MultiLanguageConst.FlowInstanceCreateSuccess);
return result;
}
if (runtime.CurrentNode is { AssigneeType: "user", Users.Count: > 0 })
{
if (!runtime.CurrentNode.Users.Contains(User.UserId))
{
return DataResult.Failed("该工作流指定用户非本人,没有发起审批的权限", MultiLanguageConst.FlowInstanceAssignUser);
}
}
if (runtime.CurrentNode is { AssigneeType: "role", Roles.Count: > 0 })
{
var userRoles = Db.Queryable<SysRoleUser>().Where(x => x.UserId == long.Parse(User.UserId))
.Select(n => n.RoleId.ToString()).ToList();
var intersectRoles = runtime.CurrentNode.Roles.Intersect(userRoles).ToList();
if (intersectRoles.Count == 0)
{
return DataResult.Failed("该工作流指定角色非本人,没有发起审批的权限", MultiLanguageConst.FlowInstanceAssignRole);
}
}
#region 根据运行实例改变当前节点状态
instance.ActivityId = runtime.CurrentNodeId;
instance.ActivityType = runtime.GetNodeType(runtime.StartNodeId);
instance.ActivityName = runtime.CurrentNode.Name;
instance.PreviousId = "";
instance.MakerList = GetCurrentMakers(runtime);
instance.FlowStatus = FlowStatusEnum.Ready;
#endregion 根据运行实例改变当前节点状态
Db.Insertable(instance).ExecuteCommand();
//流程==4为结束执行回调URL
if (runtime.GetNextNodeType() == 4 && !instance.CallbackURL.IsNullOrEmpty())
{
Task.Factory.StartNew(() => RunCallbackAsync(instance));
}
10 months ago
var history = new FlowInstanceHistory
{
InstanceId = instance.Id,
10 months ago
Content = "【创建】"
+ userName
10 months ago
+ "创建了一个流程进程【"
+ instance.CustomName + "】",
UserName = userName
};
Db.Insertable(history).ExecuteCommand();
return DataResult.Successed("创建工作流实例成功!", instance, MultiLanguageConst.FlowInstanceCreateSuccess);
}
/// <summary>
/// 撤销
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public DataResult WithdrawFlowInstance(CancelFlowInstanceReq req)
{
var instance = Db.Queryable<FlowInstance>().First(x => x.Id == req.Id);
if (instance == null)
{
return DataResult.Failed("该工作流不存在!", MultiLanguageConst.FlowInstanceNotExist);
}
if (instance.FlowStatus == FlowStatusEnum.Approve)
{
return DataResult.Failed("该工作流已完成!", MultiLanguageConst.FlowInstanceFinished);
}
instance.ActivityId = "";
//创建运行实例
var wfruntime = CreateRuntimeService(instance);
wfruntime.Cancel();
#region 根据运行实例改变当前节点状态
string startNodeId = wfruntime.StartNodeId; //起始节点
instance.PreviousId = instance.ActivityId;
instance.ActivityId = startNodeId;
instance.ActivityType = wfruntime.GetNodeType(startNodeId);
instance.ActivityName = wfruntime.ChildNodes.First(x => x.Id == startNodeId).Name;
instance.MakerList = wfruntime.GetNextNodeType() != 4 ? GetCurrentMakers(wfruntime) : "1";
instance.FlowStatus = FlowStatusEnum.Draft;
#endregion 根据运行实例改变当前节点状态
var serializerSettings = new JsonSerializerSettings
{
// 设置为驼峰命名
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
};
instance.Content = JsonConvert.SerializeObject(wfruntime.ToFlowRoot(), Formatting.None, serializerSettings);
Db.Updateable(instance).ExecuteCommand();
var userInfo = Db.Queryable<SysUser>().First(x => x.Id == long.Parse(User.UserId));
10 months ago
var history = new FlowInstanceHistory
{
InstanceId = instance.Id,
Content = $"【撤销】由{userInfo.UserName}撤销,备注:{req.Note}",
Result = -1,
UserName = userInfo.UserName
};
Db.Insertable(history).ExecuteCommand();
return DataResult.Successed("撤销成功!", MultiLanguageConst.FlowInstanceCancelSuccess);
}
10 months ago
/// <summary>
/// 获取流程操作历史
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public DataResult<List<FlowInstanceHistoryRes>> GetFlowInstanceHistoryList(string id)
{
var data = Db.Queryable<FlowInstanceHistory>()
10 months ago
.Where(a => a.InstanceId == long.Parse(id))
.Select<FlowInstanceHistoryRes>()
.ToList();
return DataResult<List<FlowInstanceHistoryRes>>.Success(data);
}
/// <summary>
/// 获取流程操作历史
/// </summary>
/// <param name="bsId">业务ID</param>
/// <param name="bsType">bsType</param>
/// <returns></returns>
public DataResult<List<FlowInstanceHistoryRes>> GetFlowInstanceHistoryList(long bsId, BusinessType? bsType)
{
var data = Db.Queryable<FlowInstanceHistory>()
.Where(x => SqlFunc.Subqueryable<FlowInstance>().Where(y => x.InstanceId == y.Id && y.BusinessId == bsId)
.WhereIF(bsType.HasValue, y => y.BusinessType == bsType.Value)
.Any())
.Select<FlowInstanceHistoryRes>()
.ToList();
return DataResult<List<FlowInstanceHistoryRes>>.Success(data);
}
/// <summary>
/// 启动
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public DataResult StartFlowInstance(string id)
{
var instance = Db.Queryable<FlowInstance>().First(x => x.Id == long.Parse(id));
if (instance == null)
{
return DataResult.Failed("该工作流不存在!", MultiLanguageConst.FlowInstanceNotExist);
}
if (instance.FlowStatus == FlowStatusEnum.Approve)
{
return DataResult.Failed("该工作流已完成!", MultiLanguageConst.FlowInstanceFinished);
}
//创建运行实例
var wfruntime = CreateRuntimeService(instance);
#region 根据运行实例改变当前节点状态
instance.ActivityId = wfruntime.NextNodeId;
instance.ActivityType = wfruntime.GetNextNodeType();
instance.ActivityName = wfruntime.NextNode.Name;
instance.PreviousId = wfruntime.CurrentNodeId;
instance.MakerList = wfruntime.GetNextNodeType() != 4 ? GetNextMakers(wfruntime) : "1";
instance.FlowStatus = (wfruntime.GetNextNodeType() == 4 ? FlowStatusEnum.Approve : FlowStatusEnum.Running);
#endregion 根据运行实例改变当前节点状态
Db.Updateable(instance).ExecuteCommand();
//流程==4为结束执行回调URL
if (wfruntime.GetNextNodeType() == 4 && !instance.CallbackURL.IsNullOrEmpty())
{
Task.Factory.StartNew(() => RunCallbackAsync(instance));
}
var userInfo = Db.Queryable<SysUser>().First(x => x.Id == long.Parse(User.UserId));
10 months ago
var history = new FlowInstanceHistory
{
InstanceId = instance.Id,
Content = $"【启动】由{userInfo.UserName}启动该流程。",
UserName = userInfo.UserName
};
Db.Insertable(history).ExecuteCommand();
return DataResult.Successed("更新成功!", instance, MultiLanguageConst.FlowInstanceUpdateSuccess);
}
/// <summary>
/// 审核工作流实例
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public DataResult AuditFlowInstance(FlowInstanceAuditReq req)
{
var instance = GetFlowInstance(req.Id);
if (instance == null)
{
return DataResult.Failed("该工作流不存在!", MultiLanguageConst.FlowInstanceNotExist);
}
else if (instance.FlowStatus == FlowStatusEnum.Approve)
{
return DataResult.Failed("该工作流已完成!", MultiLanguageConst.FlowInstanceFinished);
}
6 months ago
return AuditFlowCore(req.Status, req.AuditNote, instance);
}
/// <summary>
/// 工作流实例审核实现
/// </summary>
/// <param name="status"></param>
/// <param name="auditNote"></param>
/// <param name="instance"></param>
/// <returns></returns>
6 months ago
protected virtual DataResult AuditFlowCore(int status, string auditNote, FlowInstance instance)
{
ArgumentNullException.ThrowIfNull(instance, nameof(instance));
if (!instance.MakerList.Contains(User.UserId))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.AuditUnauthorization));
var tag = new FlowTag
{
UserName = User.UserName,
UserId = User.UserId,
6 months ago
Description = auditNote,
Taged = status
};
var runtime = CreateRuntimeService(instance);
6 months ago
if (runtime.CurrentNodeId != instance.ActivityId)
return DataResult.Failed("该工作流审批节点与当前节点不一致!", MultiLanguageConst.FlowInstanceNodeIdConflict);
#region 会签
if (instance.ActivityType == 0) //当前节点是会签节点
{
//会签时的【当前节点】一直是会签开始节点
runtime.MakeTagNode(runtime.CurrentNodeId, tag); //标记审核节点状态
var res = runtime.NodeConfluence(runtime.CurrentNodeId, tag);
if (res == ((int)TagState.No).ToString()) //驳回
{
instance.FlowStatus = FlowStatusEnum.Reject;
if (runtime.NextNodeType == 4)
{
instance.PreviousId = instance.ActivityId;
instance.ActivityId = runtime.NextNodeId;
instance.ActivityType = runtime.NextNodeType;
instance.ActivityName = runtime.NextNode.Name;
instance.MakerList = runtime.NextNodeType == 4 ? string.Empty : GetNextMakers(runtime);
}
}
else if (!string.IsNullOrEmpty(res)) //通过
{
if (runtime.NextNodeType == 5)
{
instance.MakerList = runtime.GetOtherUsers(tag);
}
else
{
instance.PreviousId = instance.ActivityId;
instance.ActivityId = runtime.NextNodeId;
instance.ActivityType = runtime.NextNodeType;
instance.ActivityName = runtime.NextNode.Name;
instance.FlowStatus = runtime.NextNodeType == 4 ? FlowStatusEnum.Approve : FlowStatusEnum.Running;
instance.MakerList = runtime.NextNodeType == 4 ? string.Empty : GetNextMakers(runtime);
}
}
else //继续审批
{
//会签过程中,需要更新用户
instance.MakerList = GetForkNodeMakers(runtime, runtime.CurrentNodeId);
}
var marker = GetNextMarkers(instance);
//获取会签下一执行人,进行通知
if (!string.IsNullOrEmpty(marker) && !instance.MarkerNotifyURL.IsNullOrEmpty())
{
Task.Factory.StartNew(() => NotifyMarkerChangedAsync(status, instance, long.Parse(marker)));
}
}
#endregion 会签
6 months ago
#region 或签
else
{
runtime.MakeTagNode(runtime.CurrentNodeId, tag);
if (tag.Taged == (int)TagState.Ok)
{
instance.PreviousId = instance.ActivityId;
instance.ActivityId = runtime.NextNodeId;
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;
}
else
{
instance.FlowStatus = FlowStatusEnum.Reject; //表示该节点不同意
runtime.NextNodeId = string.Empty;
runtime.NextNodeType = 4;
}
}
#endregion 或签
int nextNodeType = runtime.GetNextNodeType();
4 months ago
//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();
//流程=4为结束执行回调URL
if (runtime.NextNodeType != 5 && (nextNodeType == 4 || nextNodeType == -1) && !instance.CallbackURL.IsNullOrEmpty())
Task.Factory.StartNew(() => RunCallbackAsync(instance));
var userId = long.Parse(User.UserId);
var userInfo = Db.Queryable<SysUser>().Where(x => x.Id == userId).Select(x => new { x.Id, x.UserName }).First();
10 months ago
var history = new FlowInstanceHistory
{
InstanceId = instance.Id,
Content = "【" + runtime.CurrentNode.Name
10 months ago
+ "】【" + DateTime.Now.ToString("yyyy-MM-dd HH:mm")
+ "】" + (tag.Taged == 1 ? "同意" : "不同意") + ",备注:"
+ tag.Description,
UserName = userInfo?.UserName,
Result = status,
Note = auditNote
};
Db.Insertable(history).ExecuteCommand();
return DataResult.Successed("审批成功!", MultiLanguageConst.FlowInstanceAuditSuccess);
}
/// <summary>
/// 运行执行人变更回调
/// </summary>
4 months ago
/// <param name="status">审批结果</param>
/// <param name="instance">运行实例</param>
/// <param name="nextUserId">下一执行人ID</param>
/// <returns></returns>
protected virtual async Task NotifyMarkerChangedAsync(int status, FlowInstance instance, params long[] nextUserId)
{
ArgumentNullException.ThrowIfNull(instance, nameof(instance));
//请求参数设置
var callback = new MarkerChangedCallback
{
InstanceId = instance.Id,
BusinessId = instance.BusinessId,
BusinessType = instance.BusinessType,
AuditType = instance.AuditType,
4 months ago
Status = status == 1 ? FlowStatusEnum.Approve : FlowStatusEnum.Reject,
NextUserId = nextUserId
};
if (api.DefaultHeaders.Contains("Authorization"))
api.DefaultHeaders.Remove("Authorization");
api.DefaultHeaders.Add("Authorization", "Bearer " + User.GetToken());
await api.PostAsync<DataResult>(instance.MarkerNotifyURL, callback);
}
/// <summary>
/// 对指定的回调URL发起异步请求
/// </summary>
/// <param name="instance">运行实例</param>
protected virtual async Task RunCallbackAsync(FlowInstance instance)
{
ArgumentNullException.ThrowIfNull(instance, nameof(instance));
if (instance.CallbackURL.IsNullOrEmpty())
return;
//请求参数设置
var callback = new FlowCallback
{
InstanceId = instance.Id,
BusinessId = instance.BusinessId,
BusinessType = instance.BusinessType,
AuditType = instance.AuditType,
FlowStatus = instance.FlowStatus,
RejectReason = instance.Note
};
if (api.DefaultHeaders.Contains("Authorization"))
api.DefaultHeaders.Remove("Authorization");
api.DefaultHeaders.Add("Authorization", "Bearer " + User.GetToken());
var result = await api.PostAsync<DataResult>(instance.CallbackURL, callback);
if (result.Succeeded)
{
//更新回调执行标识
await Db.Updateable<FlowInstance>().SetColumns(it => it.IsCallbackExecuted == true)
.Where(it => it.Id == instance.Id).ExecuteCommandAsync();
}
}
/// <summary>
/// 运行回调更新
/// </summary>
/// <param name="bsId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="callbackURL">回调URL</param>
/// <returns></returns>
public async Task<DataResult> RunCallbackAsync(long bsId, BusinessType? businessType = null, string? callbackURL = null)
{
var instance = await Db.Queryable<FlowInstance>().Where(x => x.BusinessId == bsId && x.BusinessType == businessType)
.InnerJoin<FlowTemplateTenant>((f, ft) => f.TemplateId == ft.Id).Select((f, ft) => new FlowInstance
{
BusinessId = f.BusinessId,
BusinessType = f.BusinessType,
CallbackURL = ft.CallbackURL,
MarkerNotifyURL = ft.MarkerNotifyURL,
FlowStatus = f.FlowStatus,
Id = f.Id,
AuditType = ft.AuditType
}).FirstAsync();
if (instance == null)
return DataResult.FailedWithDesc(MultiLanguageConst.EmptyData);
if (!string.IsNullOrEmpty(callbackURL))
instance.CallbackURL = callbackURL;
await RunCallbackAsync(instance);
return DataResult.Success;
}
/// <summary>
/// 获取运行实例信息
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public FlowInstance GetFlowInstance(long id)
{
return Db.Queryable<FlowInstance>().Where(x => x.Id == id)
.InnerJoin<FlowTemplateTenant>((f, ft) => f.TemplateId == ft.Id).Select((f, ft) => new FlowInstance
{
ActivityId = f.ActivityId,
ActivityName = f.ActivityName,
ActivityType = f.ActivityType,
BusinessId = f.BusinessId,
BusinessType = f.BusinessType,
CallbackURL = ft.CallbackURL,
MarkerNotifyURL = ft.MarkerNotifyURL,
ColumnView = f.ColumnView,
Content = f.Content,
FlowStatus = f.FlowStatus,
Id = f.Id,
MakerList = f.MakerList,
PreviousId = f.PreviousId,
PermissionId = f.PermissionId,
AuditType = ft.AuditType
}).First();
}
protected virtual FlowRuntime CreateRuntimeService(FlowInstance instance)
{
return new FlowRuntime(instance, Db, null);
}
public DataResult<FlowInstanceRes> GetFlowInstanceInfo(string id)
{
var data = Db.Queryable<FlowInstance>()
// .LeftJoin<SysPermission>((a, b) => a.PermissionId == b.Id)
.Where(a => a.Id == long.Parse(id))
.Select<FlowInstanceRes>()
.First();
return DataResult<FlowInstanceRes>.Success(data);
}
/// <summary>
/// 寻找下一步的执行人
/// 一般用于本节点审核完成后,修改流程实例的当前执行人,可以做到通知等功能
/// </summary>
/// <returns></returns>
protected string GetCurrentMakers(FlowRuntime wfruntime, CreateFlowInstanceReq request = null)
{
string makerList = "";
if (wfruntime.NextNodeId == "-1")
throw new ApplicationException("无法寻找到下一个节点");
if (wfruntime.CurrentNodeType == 0) //如果是会签节点
{
makerList = GetForkNodeMakers(wfruntime, wfruntime.NextNodeId);
}
else if (wfruntime.CurrentNode.AssigneeType == "role")
{
var users = Db.Queryable<SysRoleUser>().Where(x =>
wfruntime.CurrentNode.Roles.Contains(x.RoleId.ToString()))
.Select(x => x.UserId).Distinct().ToList();
makerList = string.Join(',', users);
}
else if (wfruntime.CurrentNode.AssigneeType == "user")
{
makerList = string.Join(",", wfruntime.CurrentNode.Users);
}
else if (wfruntime.CurrentNode.AssigneeType == FlowChild.Dynamic)
{
makerList = GetDynamicMarkers(wfruntime.CurrentNode, wfruntime);
}
else
{
makerList = GetNodeMarkers(wfruntime.CurrentNode);
if (string.IsNullOrEmpty(makerList))
{
throw (new Exception("无法寻找到节点的审核者,请查看流程设计是否有问题!"));
}
}
return makerList;
}
/// <summary>
/// 寻找下一步的执行人
/// 一般用于本节点审核完成后,修改流程实例的当前执行人,可以做到通知等功能
/// </summary>
/// <returns></returns>
protected string GetNextMakers(FlowRuntime wfruntime, CreateFlowInstanceReq request = null)
{
string makerList = "";
if (wfruntime.NextNodeId == "-1")
throw new ApplicationException("无法寻找到下一个节点");
if (wfruntime.NextNode.AssigneeType == "role")
{
var users = Db.Queryable<SysRoleUser>().Where(x =>
wfruntime.NextNode.Roles.Contains(x.RoleId.ToString()))
.Select(x => x.UserId).Distinct().ToList();
makerList = string.Join(",", users);
}
else if (wfruntime.NextNode.AssigneeType == "user")
{
makerList = string.Join(",", wfruntime.NextNode.Users);
}
else if (wfruntime.NextNode.AssigneeType == FlowChild.Dynamic)
{
makerList = GetDynamicMarkers(wfruntime.NextNode, wfruntime);
}
else
{
makerList = GetNodeMarkers(wfruntime.NextNode);
if (string.IsNullOrEmpty(makerList))
{
throw new Exception("无法寻找到节点的审核者,请查看流程设计是否有问题!");
}
}
return makerList;
}
/// <summary>
/// 获取会签开始节点的所有可执行者
/// </summary>
/// <param name="forkNodeId">会签开始节点</param>
/// <returns></returns>
protected virtual string GetForkNodeMakers(FlowRuntime wfruntime, string forkNodeId)
{
string makerList = "";
var nextNode = wfruntime.NextNode;
var nextConditionNodeId = wfruntime.GetNextConditionNodeId(nextNode);
var nextConditionNode = wfruntime.ChildNodes.First(x => x.Id == nextConditionNodeId);
if (nextConditionNode.AssigneeType == "role")
{
var users = Db.Queryable<SysRoleUser>().Where(x =>
nextConditionNode.Roles.Contains(x.RoleId.ToString()))
.Select(x => x.UserId).Distinct().ToList();
makerList = string.Join(",", users);
}
else if (nextConditionNode.AssigneeType == "user")
{
makerList = string.Join(",", nextConditionNode.Users);
}
else if (nextConditionNode.AssigneeType == FlowChild.Dynamic)
{
makerList = GetDynamicMarkers(nextConditionNode, wfruntime);
}
return makerList;
}
/// <summary>
/// 寻找该节点执行人
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
protected string GetNodeMarkers(FlowChild node, string flowinstanceCreateUserId = "")
{
string makerList = "";
if (node.Type == FlowChild.START && (!string.IsNullOrEmpty(flowinstanceCreateUserId))) //如果是开始节点,通常情况下是驳回到开始了
{
makerList = flowinstanceCreateUserId;
}
else if (node.AssigneeType != null)
{
if (node.AssigneeType == "role")
{
var users = Db.Queryable<SysRoleUser>().Where(x =>
node.Roles.Contains(x.RoleId.ToString()))
.Select(x => x.UserId).Distinct().ToList();
makerList = string.Join(",", users);
}
else if (node.AssigneeType == "user")
{
makerList = node.Users.ToString();
}
}
else //如果没有设置节点信息,默认所有人都可以审核
{
makerList = "1";
}
return makerList;
}
//获取动态节点的执行人
internal string GetDynamicMarkers(FlowChild flowNode, FlowRuntime runtime)
{
if (flowNode == null || string.IsNullOrEmpty(flowNode.MarkerSQLText) || runtime == null)
return string.Empty;
List<string> markers = [];
using (var reader = TenantDb.Ado.GetDataReader(flowNode.MarkerSQLText, new SugarParameter($"@{nameof(BaseModel<long>.Id)}", runtime.BusinessId)))
{
while (reader.Read())
markers.Add(reader.GetString(0));
}
string markerList = string.Join(",", markers);
if (string.IsNullOrEmpty(markerList))
throw new ApplicationException("未能根据动态节点设置的查询语句获取工作流执行人,请检查模板配置");
Db.Updateable<FlowInstance>()
.SetColumns(x => x.MakerList == markerList).Where(x => x.Id == runtime.InstanceId)
.ExecuteCommand();
return markerList;
}
}