|
|
using Infrastructure;
|
|
|
using Infrastructure.Extensions;
|
|
|
using Newtonsoft.Json;
|
|
|
using OpenAuth.App.Config;
|
|
|
using OpenAuth.Repository.Domain;
|
|
|
using SqlSugar;
|
|
|
using StackExchange.Redis;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Diagnostics;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
namespace OpenAuth.App
|
|
|
{
|
|
|
public class WFEngine : IWFEngine
|
|
|
{
|
|
|
ISqlSugarClient client;
|
|
|
//private RepositoryFactory dbFactory { get; set; }
|
|
|
/// <summary>
|
|
|
/// 流程配置信息
|
|
|
/// </summary>
|
|
|
private WFEngineConfig _config { get; set; }
|
|
|
/// <summary>
|
|
|
/// 流程模板
|
|
|
/// </summary>
|
|
|
private WorkFlow.WFScheme _wfScheme { get; set; }
|
|
|
/// <summary>
|
|
|
/// 流程单元对应字典
|
|
|
/// </summary>
|
|
|
private Dictionary<string, WFUnit> _dicUnit { get; set; }
|
|
|
/// <summary>
|
|
|
/// 开始节点
|
|
|
/// </summary>
|
|
|
private WFUnit _startNode { get; set; }
|
|
|
/// <summary>
|
|
|
/// 线条集合
|
|
|
/// </summary>
|
|
|
private List<WFUnit> _lines { get; set; }
|
|
|
#region 构造函数
|
|
|
/// <summary>
|
|
|
/// 构造方法
|
|
|
/// </summary>
|
|
|
/// <param name="config">流程参数</param>
|
|
|
public WFEngine(WFEngineConfig config, ISqlSugarClient sqlSugarClient)
|
|
|
{
|
|
|
// 初始化模板数据
|
|
|
_config = config;
|
|
|
_wfScheme = ToObject<WorkFlow.WFScheme>(_config.Params.Scheme);
|
|
|
//_wfScheme = Newtonsoft.Json.JsonConvert.DeserializeObject<WorkFlow.WFScheme>(_config.Params.Scheme);
|
|
|
//_wfScheme = ExtensionsJson.ToObject<WorkFlow.WFScheme>(_config.Params.Scheme);
|
|
|
|
|
|
_dicUnit = new Dictionary<string, WFUnit>();
|
|
|
_lines = new List<WFUnit>();
|
|
|
|
|
|
foreach (var unit in _wfScheme.WfData)
|
|
|
{
|
|
|
if (!_dicUnit.ContainsKey(unit.Id))
|
|
|
{
|
|
|
_dicUnit.Add(unit.Id, unit);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
if (unit.Type == NodeTypeEnum.startEvent.GetDescription())
|
|
|
{
|
|
|
_startNode = unit;
|
|
|
}
|
|
|
else if (unit.Type == NodeTypeEnum.myline.GetDescription())
|
|
|
{
|
|
|
_lines.Add(unit);
|
|
|
}
|
|
|
}
|
|
|
client = sqlSugarClient;
|
|
|
//dbFactory = new RepositoryFactory();
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
public T ToObject<T>(string Json)
|
|
|
{
|
|
|
return (T)((Json == null) ? ((object)default(T)) : ((object)JsonConvert.DeserializeObject<T>(Json)));
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 流程运行参数
|
|
|
/// </summary>
|
|
|
public WFEngineConfig Config => _config;
|
|
|
/// <summary>
|
|
|
/// 开始节点
|
|
|
/// </summary>
|
|
|
public WFUnit StartNode => _startNode;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 流程发起用户
|
|
|
/// </summary>
|
|
|
public WFUserInfo CreateUser => _config.Params.CreateUser;
|
|
|
/// <summary>
|
|
|
/// 流程发起用户
|
|
|
/// </summary>
|
|
|
public WFUserInfo CurrentUser => _config.Params.CurrentUser;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 流程配置信息
|
|
|
/// </summary>
|
|
|
public WorkFlow.WFScheme WFScheme => _wfScheme;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取流程单元信息
|
|
|
/// </summary>
|
|
|
/// <param name="id">id</param>
|
|
|
/// <returns>流程单元信息</returns>
|
|
|
public WFUnit GetNode(string id)
|
|
|
{
|
|
|
if (_dicUnit.ContainsKey(id))
|
|
|
{
|
|
|
return _dicUnit[id];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取下一节点集合
|
|
|
/// </summary>
|
|
|
/// <param name="startId">开始节点</param>
|
|
|
/// <param name="code">执行动作编码</param>
|
|
|
/// <returns></returns>
|
|
|
public List<WFUnit> GetNextUnits(string startId, string code = "")
|
|
|
{
|
|
|
List<WFUnit> nextUnits = new List<WFUnit>();
|
|
|
|
|
|
// 找到与当前节点相连的线条
|
|
|
foreach (var line in _lines)
|
|
|
{
|
|
|
if (line.From == startId)
|
|
|
{
|
|
|
// 获取连接到开始节点的线条
|
|
|
bool isOk = false;
|
|
|
if (string.IsNullOrEmpty(line.LineConditions))
|
|
|
{
|
|
|
isOk = true;
|
|
|
}
|
|
|
else if (!string.IsNullOrEmpty(code))
|
|
|
{
|
|
|
var codeList = line.LineConditions.Split(',');
|
|
|
foreach (string _code in codeList)
|
|
|
{
|
|
|
if (_code == code)
|
|
|
{
|
|
|
isOk = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{ //没有执行码就是全部执行
|
|
|
isOk = true;
|
|
|
}
|
|
|
|
|
|
|
|
|
// 获取到流入节点
|
|
|
if (isOk)
|
|
|
{
|
|
|
if (_dicUnit.ContainsKey(line.To) && nextUnits.Find(t => t.Id == line.To) == null)
|
|
|
{
|
|
|
nextUnits.Add(_dicUnit[line.To]);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return nextUnits;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 获取下一节点集合
|
|
|
/// </summary>
|
|
|
/// <param name="startId">开始节点</param>
|
|
|
/// <param name="codeList">条件编码</param>
|
|
|
/// <returns></returns>
|
|
|
public List<WFUnit> GetNextUnits(string startId, List<string> codeList)
|
|
|
{
|
|
|
List<WFUnit> nextUnits = new List<WFUnit>();
|
|
|
|
|
|
// 找到与当前节点相连的线条
|
|
|
foreach (var line in _lines)
|
|
|
{
|
|
|
if (line.From == startId)
|
|
|
{
|
|
|
// 获取连接到开始节点的线条
|
|
|
bool isOk = false;
|
|
|
if (codeList.Count > 0 && !string.IsNullOrEmpty(line.LineConditions))
|
|
|
{
|
|
|
var codeList2 = line.LineConditions.Split(',');
|
|
|
foreach (string _code in codeList2)
|
|
|
{
|
|
|
if (codeList.FindIndex(t => t == _code) != -1)
|
|
|
{
|
|
|
isOk = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 获取到流入节点
|
|
|
if (isOk)
|
|
|
{
|
|
|
if (_dicUnit.ContainsKey(line.To) && nextUnits.Find(t => t.Id == line.To) == null)
|
|
|
{
|
|
|
nextUnits.Add(_dicUnit[line.To]);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return nextUnits;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取下一节点集合(流转条件为空的情况)
|
|
|
/// </summary>
|
|
|
/// <param name="startId">开始节点</param>
|
|
|
/// <returns></returns>
|
|
|
public List<WFUnit> GetNextUnitsNoSet(string startId)
|
|
|
{
|
|
|
List<WFUnit> nextUnits = new List<WFUnit>();
|
|
|
|
|
|
// 找到与当前节点相连的线条
|
|
|
foreach (var line in _lines)
|
|
|
{
|
|
|
if (line.From == startId)
|
|
|
{
|
|
|
// 获取到流入节点
|
|
|
if (string.IsNullOrEmpty(line.LineConditions))
|
|
|
{
|
|
|
if (_dicUnit.ContainsKey(line.To) && nextUnits.Find(t => t.Id == line.To) == null)
|
|
|
{
|
|
|
nextUnits.Add(_dicUnit[line.To]);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return nextUnits;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 获取上一单元ID列表
|
|
|
/// </summary>
|
|
|
/// <param name="myUnitId">当前节点Id</param>
|
|
|
/// <returns></returns>
|
|
|
public List<string> GetPreUnitIds(string myUnitId)
|
|
|
{
|
|
|
List<string> list = new List<string>();
|
|
|
// 找到与当前节点相连的线条
|
|
|
foreach (var line in _lines)
|
|
|
{
|
|
|
if (line.To == myUnitId && list.Find(t => t == line.From) == null)
|
|
|
{
|
|
|
list.Add(line.From);
|
|
|
}
|
|
|
}
|
|
|
return list;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 获取任务
|
|
|
/// </summary>
|
|
|
/// <param name="startId">开始节点</param>
|
|
|
/// <param name="code">执行动作编码</param>
|
|
|
/// <param name="toUnitId">下一个指定节点</param>
|
|
|
/// <returns></returns>
|
|
|
public async Task<List<WorkFlow.WFTask>> GetTask(string startId, string code = "", string toUnitId = "")
|
|
|
{
|
|
|
bool isIsReject = code == "disagree";
|
|
|
var nextUnits = GetNextUnits(startId, code);
|
|
|
|
|
|
if (!string.IsNullOrEmpty(toUnitId))
|
|
|
{
|
|
|
nextUnits = nextUnits.FindAll(t => t.Type == "bpmn:ScriptTask");// 只保留脚本节点
|
|
|
nextUnits.Add(GetNode(toUnitId));
|
|
|
}
|
|
|
|
|
|
// 如果无法获取下一个审核任务且是驳回操作,就返回到之前流转过来的任务(除去通过驳回流转过来的)(需要过滤掉脚本节点)
|
|
|
if (nextUnits.FindAll(t => t.Type != "bpmn:ScriptTask").Count == 0 && isIsReject)
|
|
|
{
|
|
|
// 获取当前节点的
|
|
|
var prevUnitId = await Config.GetPrevUnitId(Config.Params.ProcessId, startId);
|
|
|
if (!string.IsNullOrEmpty(prevUnitId))
|
|
|
{
|
|
|
nextUnits.Add(GetNode(prevUnitId));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var list = await GetTask(nextUnits, isIsReject, startId);
|
|
|
foreach (var item in list)
|
|
|
{
|
|
|
item.PrevUnitId = startId;
|
|
|
}
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取任务
|
|
|
/// </summary>
|
|
|
/// <param name="nextUnits">下一个节点集合</param>
|
|
|
/// <param name="isReject">是否驳回</param>
|
|
|
/// <param name="startId">开始节点</param>
|
|
|
/// <returns></returns>
|
|
|
public async Task<List<WorkFlow.WFTask>> GetTask(List<WFUnit> nextUnits, bool isReject, string startId)
|
|
|
{
|
|
|
WFUnit startUnit = _dicUnit[startId];
|
|
|
|
|
|
if (startUnit.Type == NodeTypeEnum.startEvent.GetDescription() && string.IsNullOrEmpty(startUnit.Name))
|
|
|
{
|
|
|
startUnit.Name = "开始节点";
|
|
|
}
|
|
|
|
|
|
List<WorkFlow.WFTask> taskList = new List<WorkFlow.WFTask>();
|
|
|
foreach (var unit in nextUnits)
|
|
|
{
|
|
|
switch (unit.Type)
|
|
|
{
|
|
|
//case "startEvent":// 开始节点
|
|
|
case "bpmn:StartEvent":// 开始节点
|
|
|
taskList.Add(GetStartTask(unit, isReject, startId, startUnit.Name));
|
|
|
break;
|
|
|
//case "gatewayAnd":
|
|
|
case "bpmn:ParallelGateway":
|
|
|
// 并行网关会等待所有分支汇入才往下执行,所有出口分支都会被执行
|
|
|
// 判断是否所有分支都被执行了
|
|
|
// 1.或去此节点所有上节点
|
|
|
// 2.生成一个等待任务
|
|
|
// 3.获取所有该节点当前等待任务
|
|
|
// 4.判断是否完成获取下一节点
|
|
|
var preIdList = GetPreUnitIds(unit.Id);
|
|
|
if (preIdList.Count <= 1)
|
|
|
{
|
|
|
taskList.AddRange(await GetTask(unit.Id));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var awaitTaskList = await Config.GetAwaitTaskList(Config.Params.ProcessId, unit.Id);
|
|
|
var awaitTaskList2 = awaitTaskList.FindAll(t => t.PrevUnitId != startId); // 排除当前等待任务的所有等待任务
|
|
|
if (awaitTaskList2.Count + 1 >= preIdList.Count)
|
|
|
{
|
|
|
// 如果所有支路都被执行了就生成一个取消所有等待任务的命令
|
|
|
taskList.Add(GetDeleteAwaitTask(unit, isReject, startId, startUnit.Name));
|
|
|
taskList.AddRange(await GetTask(unit.Id));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
taskList.Add(GetAwaitTask(unit, isReject, startId, startUnit.Name));
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
//case "gatewayXor":
|
|
|
case "bpmn:ExclusiveGateway":
|
|
|
// 排他网关不会等待所有分支汇入才往下执行,只要有分支汇入就会往下执行,出口分支只会执行一条(条件为true,如果多条出口分支条件为true也执行一条)
|
|
|
// 1.获取当前节点的true条件,如果成立条件为0,就执行人默认没有条件的线条
|
|
|
// 2.获取下一个节点
|
|
|
var conditionCodes = await GetConditionIds(unit.Conditions);
|
|
|
var nextUnits2 = GetNextUnits(unit.Id, conditionCodes);
|
|
|
if (nextUnits2.Count == 0)
|
|
|
{
|
|
|
nextUnits2 = GetNextUnitsNoSet(unit.Id);
|
|
|
}
|
|
|
if (nextUnits2.Count == 0)
|
|
|
{
|
|
|
throw new Exception(string.Format("无法获取下一节点【{0}】", unit.Id));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var nextUnits3 = new List<WFUnit>();
|
|
|
nextUnits3.Add(nextUnits2[0]);
|
|
|
taskList.AddRange(await GetTask(nextUnits3, isReject, unit.Id));
|
|
|
}
|
|
|
break;
|
|
|
//case "gatewayInclusive":
|
|
|
case "bpmn:InclusiveGateway":
|
|
|
// 包容网关会等待所有分支汇入才往下执行,出口分支能执行多条(条件为true)
|
|
|
bool isNext = false;
|
|
|
var preIdList2 = GetPreUnitIds(unit.Id);
|
|
|
if (preIdList2.Count <= 1)
|
|
|
{
|
|
|
isNext = true;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
|
|
|
var awaitTaskList = await Config.GetAwaitTaskList(Config.Params.ProcessId, unit.Id);
|
|
|
var awaitTaskList2 = awaitTaskList.FindAll(t => t.PrevUnitId != startId); // 排除当前等待任务的所有等待任务
|
|
|
if (awaitTaskList2.Count + 1 >= preIdList2.Count)
|
|
|
{
|
|
|
// 如果所有支路都被执行了就生成一个取消所有等待任务的命令
|
|
|
taskList.Add(GetDeleteAwaitTask(unit, isReject, startId, startUnit.Name));
|
|
|
isNext = true;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
taskList.Add(GetAwaitTask(unit, isReject, startId, startUnit.Name));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (isNext)
|
|
|
{
|
|
|
var conditionCodes2 = await GetConditionIds(unit.Conditions);
|
|
|
var nextUnits3 = GetNextUnits(unit.Id, conditionCodes2);
|
|
|
nextUnits3.AddRange(GetNextUnitsNoSet(unit.Id));
|
|
|
taskList.AddRange(await GetTask(nextUnits3, isReject, unit.Id));
|
|
|
}
|
|
|
break;
|
|
|
//case "userTask":// 审批节点
|
|
|
case "bpmn:Task":// 审批节点
|
|
|
// 1.获取节点上一次的请求人
|
|
|
var preAuditUsers = await Config.GetPrevTaskUserList(Config.Params.ProcessId, unit.Id);
|
|
|
if (preAuditUsers.FindIndex(t => t.State == 1) != -1)
|
|
|
{
|
|
|
// 如果此节点被激活不需要审核
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
|
|
|
var auditUsers = new List<WFUserInfo>();
|
|
|
if (preAuditUsers.Count == 0)
|
|
|
{
|
|
|
// 表示此节点未被处理过
|
|
|
// 获取审核人
|
|
|
if (Config.Params.NextUsers != null && Config.Params.NextUsers.ContainsKey(unit.Id))
|
|
|
{
|
|
|
var auditUserList = new List<WFAuditor>();
|
|
|
var strAuditUser = Config.Params.NextUsers[unit.Id];
|
|
|
var strAuditUserList = strAuditUser.Split(",");
|
|
|
foreach (var id in strAuditUserList)
|
|
|
{
|
|
|
auditUserList.Add(new WFAuditor()
|
|
|
{
|
|
|
Type = "3",
|
|
|
Id = id
|
|
|
});
|
|
|
}
|
|
|
|
|
|
auditUsers = await Config.GetUserList(auditUserList, CreateUser, Config.Params.ProcessId, _startNode);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auditUsers = await Config.GetUserList(unit.AuditUsers, CreateUser, Config.Params.ProcessId, _startNode);
|
|
|
}
|
|
|
|
|
|
// 添加传阅任务,节点第一次执行的时候触发
|
|
|
var lookUsers = await Config.GetUserList(unit.LookUsers, CreateUser, Config.Params.ProcessId, _startNode);
|
|
|
taskList.AddRange(GetLookUserTaskList(unit, lookUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 添加一条任务用于更新之前任务状态(将之前的任务设置成不是最近的一次任务)
|
|
|
taskList.Add(GetUpdateTask(unit));
|
|
|
}
|
|
|
|
|
|
// 表示找不到审核人
|
|
|
if (preAuditUsers.Count == 0 && auditUsers.Count == 0)
|
|
|
{
|
|
|
switch (unit.NoAuditor)
|
|
|
{
|
|
|
case "1":
|
|
|
taskList.AddRange(GetUserTaskList(unit, await Config.GetSystemUserList(), isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
|
|
|
break;
|
|
|
case "2":
|
|
|
// 流转到下一个节点
|
|
|
taskList.Add(GetSkipTask(unit, isReject, startId, startUnit.Name));
|
|
|
taskList.AddRange(await GetTask(unit.Id));
|
|
|
break;
|
|
|
case "3":
|
|
|
throw new Exception(string.Format("【{0}{1}】找不到审核人,无法提交", unit.Name, unit.Id));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 1.需要先判断是否是会签
|
|
|
if (unit.IsCountersign)
|
|
|
{
|
|
|
// 之前有人处理过
|
|
|
if (preAuditUsers.Count > 0)
|
|
|
{
|
|
|
// 驳回处理,重新开启审核
|
|
|
if (isReject)
|
|
|
{
|
|
|
taskList.AddRange(GetCountersignTask(unit, preAuditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString(), unit.CountersignType));
|
|
|
}
|
|
|
else
|
|
|
// 1.判断之前的会签策略是否通过
|
|
|
if (await Config.IsCountersignAgree(Config.Params.ProcessId, unit.Id))
|
|
|
{
|
|
|
// 判断自动同意规则,会签状态下只有3有效
|
|
|
if (unit.AutoAgree.IndexOf("3") != -1)
|
|
|
{
|
|
|
taskList.AddRange(await GetTask(unit.Id));// 自动审核,流转到下一节点
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
taskList.AddRange(GetCountersignTask(unit, preAuditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString(), unit.CountersignType));
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
taskList.AddRange(GetCountersignTask(unit, preAuditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString(), unit.CountersignType, unit.CountersignAgian));
|
|
|
}
|
|
|
}
|
|
|
// 第一次处理
|
|
|
else
|
|
|
{
|
|
|
taskList.AddRange(GetCountersignTask(unit, auditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString(), unit.CountersignType));
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 之前有人处理过
|
|
|
if (preAuditUsers.Count > 0)
|
|
|
{
|
|
|
if (IsAtuoAgree(preAuditUsers, unit.AutoAgree.Split(','), isReject))
|
|
|
{
|
|
|
taskList.AddRange(await GetTask(unit.Id, "agree"));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 判断是否有完成任务的人
|
|
|
if (preAuditUsers.FindIndex(t => t.State == 3) != -1)
|
|
|
{
|
|
|
taskList.AddRange(GetUserTaskList(unit, preAuditUsers.FindAll(t => t.State == 3), isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
taskList.AddRange(GetUserTaskList(unit, preAuditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (IsAtuoAgree(auditUsers, unit.AutoAgree.Split(','), isReject))
|
|
|
{
|
|
|
taskList.Add(GetAutoSkipTask(unit, isReject, startId, startUnit.Name));// 作为日志记录
|
|
|
taskList.AddRange(await GetTask(unit.Id, "agree"));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
taskList.AddRange(GetUserTaskList(unit, auditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case "bpmn:ScriptTask":// 脚本节点
|
|
|
taskList.Add(GetScriptTaskList(unit, isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
|
|
|
taskList.AddRange(await GetTask(unit.Id));
|
|
|
break;
|
|
|
//case "subprocess":// 暂时不支持
|
|
|
case "bpmn:SubProcess":
|
|
|
taskList.Add(GetSubprocessTask(unit, startId, startUnit.Name));
|
|
|
break;
|
|
|
//case "endEvent":// 结束节点
|
|
|
case "bpmn:EndEvent":// 结束节点
|
|
|
taskList.Add(GetEndTask(unit, startId, startUnit.Name));
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return taskList;
|
|
|
}
|
|
|
|
|
|
|
|
|
#region 私有方法
|
|
|
/// <summary>
|
|
|
/// 获取开始任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <param name="IsReject"></param>
|
|
|
/// <param name="preUnitId"></param>
|
|
|
/// <param name="preUnitName"></param>
|
|
|
/// <returns></returns>
|
|
|
private WorkFlow.WFTask GetStartTask(WFUnit unit, bool IsReject, string preUnitId, string preUnitName)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Name = "重新创建",
|
|
|
Token = Guid.NewGuid().ToString(),
|
|
|
Type = 4,
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
IsReject = IsReject,
|
|
|
MessageType = unit.MessageType,
|
|
|
User = _config.Params.CreateUser
|
|
|
};
|
|
|
return task;
|
|
|
}
|
|
|
|
|
|
private WorkFlow.WFTask GetEndTask(WFUnit unit, string preUnitId, string preUnitName)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Name = "流程结束",
|
|
|
Token = Guid.NewGuid().ToString(),
|
|
|
Type = 100,
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
};
|
|
|
return task;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 获取一个等待任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <param name="IsReject"></param>
|
|
|
/// <param name="preUnitId"></param>
|
|
|
/// <param name="preUnitName"></param>
|
|
|
/// <returns></returns>
|
|
|
private WorkFlow.WFTask GetAwaitTask(WFUnit unit, bool IsReject, string preUnitId, string preUnitName)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Name = "等待其它支路完成",
|
|
|
Type = 21,
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
IsReject = IsReject
|
|
|
};
|
|
|
|
|
|
return task;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取一个更新任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <returns></returns>
|
|
|
private WorkFlow.WFTask GetUpdateTask(WFUnit unit)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Type = 26,
|
|
|
};
|
|
|
|
|
|
return task;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取一个找不到审核人直接跳过任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <param name="IsReject"></param>
|
|
|
/// <param name="preUnitId"></param>
|
|
|
/// <param name="preUnitName"></param>
|
|
|
/// <returns></returns>
|
|
|
private WorkFlow.WFTask GetSkipTask(WFUnit unit, bool IsReject, string preUnitId, string preUnitName)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Name = "当前任务找不到审核人直接跳过",
|
|
|
Type = 23,
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
IsReject = IsReject
|
|
|
};
|
|
|
|
|
|
return task;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取一个找不到审核人直接跳过任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <param name="IsReject"></param>
|
|
|
/// <param name="preUnitId"></param>
|
|
|
/// <param name="preUnitName"></param>
|
|
|
/// <returns></returns>
|
|
|
private WorkFlow.WFTask GetAutoSkipTask(WFUnit unit, bool IsReject, string preUnitId, string preUnitName)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Name = "自动审核规则跳过",
|
|
|
Type = 24,
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
IsReject = IsReject
|
|
|
};
|
|
|
|
|
|
return task;
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取一个取消等待任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <param name="IsReject"></param>
|
|
|
/// <param name="preUnitId"></param>
|
|
|
/// <param name="preUnitName"></param>
|
|
|
/// <returns></returns>
|
|
|
private WorkFlow.WFTask GetDeleteAwaitTask(WFUnit unit, bool IsReject, string preUnitId, string preUnitName)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Name = "取消等待任务",
|
|
|
Type = 22,
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
IsReject = IsReject
|
|
|
};
|
|
|
|
|
|
return task;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 获取审批任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <param name="userList"></param>
|
|
|
/// <param name="isReject"></param>
|
|
|
/// <param name="preUnitId"></param>
|
|
|
/// <param name="preUnitName"></param>
|
|
|
/// <param name="token"></param>
|
|
|
/// <returns></returns>
|
|
|
private List<WorkFlow.WFTask> GetUserTaskList(WFUnit unit, List<WFUserInfo> userList, bool isReject, string preUnitId, string preUnitName, string token)
|
|
|
{
|
|
|
List<WorkFlow.WFTask> list = new List<WorkFlow.WFTask>();
|
|
|
int type = 1;
|
|
|
if (unit!=null&&unit.IsSingleTask)
|
|
|
{
|
|
|
type = 7;
|
|
|
}
|
|
|
foreach (var user in userList)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Name = unit.Name,
|
|
|
Type = type,
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
IsReject = isReject,
|
|
|
Token = token,
|
|
|
MessageType = unit.MessageType,
|
|
|
|
|
|
// 超时设置
|
|
|
IsOvertimeMessage = unit.IsOvertimeMessage,
|
|
|
OvertimeMessageStart = unit.OvertimeMessageStart,
|
|
|
OvertimeMessageInterval = unit.OvertimeMessageInterval,
|
|
|
OvertimeGo = unit.OvertimeGo,
|
|
|
OvertimeMessageType = unit.OvertimeMessageType,
|
|
|
|
|
|
IsBatchAudit = unit.IsBatchAudit,
|
|
|
// 处理人
|
|
|
User = user
|
|
|
|
|
|
};
|
|
|
if (string.IsNullOrEmpty(task.Name))
|
|
|
{
|
|
|
task.Name = "审核处理";
|
|
|
}
|
|
|
|
|
|
list.Add(task);
|
|
|
}
|
|
|
|
|
|
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取传阅任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <param name="userList"></param>
|
|
|
/// <param name="isReject"></param>
|
|
|
/// <param name="preUnitId"></param>
|
|
|
/// <param name="preUnitName"></param>
|
|
|
/// <param name="token"></param>
|
|
|
/// <returns></returns>
|
|
|
private List<WorkFlow.WFTask> GetLookUserTaskList(WFUnit unit, List<WFUserInfo> userList, bool isReject, string preUnitId, string preUnitName, string token)
|
|
|
{
|
|
|
List<WorkFlow.WFTask> list = new List<WorkFlow.WFTask>();
|
|
|
foreach (var user in userList)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Name = unit.Name,
|
|
|
Type = 2,
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
IsReject = isReject,
|
|
|
Token = token,
|
|
|
MessageType = unit.MessageType,
|
|
|
|
|
|
// 处理人
|
|
|
User = user
|
|
|
|
|
|
};
|
|
|
if (string.IsNullOrEmpty(task.Name))
|
|
|
{
|
|
|
task.Name = "查看";
|
|
|
}
|
|
|
|
|
|
list.Add(task);
|
|
|
}
|
|
|
|
|
|
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取会签审批任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <param name="userList"></param>
|
|
|
/// <param name="isReject"></param>
|
|
|
/// <param name="preUnitId"></param>
|
|
|
/// <param name="preUnitName"></param>
|
|
|
/// <param name="token"></param>
|
|
|
/// <param name="countersignType">审核方式 1.并行 2.串行</param>
|
|
|
/// <param name="countersignAgian">再次审核 1.已同意不需要审核 2.已同意需要审核</param>
|
|
|
/// <returns></returns>
|
|
|
private List<WorkFlow.WFTask> GetCountersignTask(WFUnit unit, List<WFUserInfo> userList, bool isReject, string preUnitId, string preUnitName, string token, string countersignType, string countersignAgian = "2")
|
|
|
{
|
|
|
List<WorkFlow.WFTask> list = new List<WorkFlow.WFTask>();
|
|
|
int num = 1;
|
|
|
foreach (var user in userList)
|
|
|
{
|
|
|
if (countersignAgian == "1" && user.IsAgree)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
user.IsAwait = countersignType == "1" ? false : true;
|
|
|
user.Sort = num;
|
|
|
if (num == 1)
|
|
|
{
|
|
|
user.IsAwait = false;
|
|
|
}
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Name = unit.Name,
|
|
|
Type = 5,
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
IsReject = isReject,
|
|
|
Token = token,
|
|
|
MessageType = unit.MessageType,
|
|
|
|
|
|
// 超时设置
|
|
|
IsOvertimeMessage = unit.IsOvertimeMessage,
|
|
|
OvertimeMessageStart = unit.OvertimeMessageStart,
|
|
|
OvertimeMessageInterval = unit.OvertimeMessageInterval,
|
|
|
OvertimeGo = unit.OvertimeGo,
|
|
|
OvertimeMessageType = unit.OvertimeMessageType,
|
|
|
|
|
|
IsBatchAudit = unit.IsBatchAudit,
|
|
|
// 处理人
|
|
|
User = user,
|
|
|
|
|
|
|
|
|
};
|
|
|
if (string.IsNullOrEmpty(task.Name))
|
|
|
{
|
|
|
task.Name = "审核处理";
|
|
|
}
|
|
|
|
|
|
list.Add(task);
|
|
|
|
|
|
num++;
|
|
|
}
|
|
|
|
|
|
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取脚本执行任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <param name="isReject"></param>
|
|
|
/// <param name="preUnitId"></param>
|
|
|
/// <param name="preUnitName"></param>
|
|
|
/// <param name="token"></param>
|
|
|
/// <returns></returns>
|
|
|
private WorkFlow.WFTask GetScriptTaskList(WFUnit unit, bool isReject, string preUnitId, string preUnitName, string token)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
UnitId = unit.Id,
|
|
|
Name = unit.Name,
|
|
|
Type = 10,
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
IsReject = isReject,
|
|
|
Token = token,
|
|
|
|
|
|
ExecuteType = unit.ExecuteType,
|
|
|
SqlDb = unit.SqlDb,
|
|
|
SqlStr = unit.SqlStr,
|
|
|
SqlStrRevoke = unit.SqlStrRevoke,
|
|
|
ApiUrl = unit.ApiUrl,
|
|
|
ApiUrlRevoke = unit.ApiUrlRevoke,
|
|
|
Ioc = unit.Ioc,
|
|
|
IocRevoke = unit.IocRevoke,
|
|
|
|
|
|
|
|
|
};
|
|
|
if (string.IsNullOrEmpty(task.Name))
|
|
|
{
|
|
|
task.Name = "脚本执行";
|
|
|
}
|
|
|
|
|
|
|
|
|
return task;
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取成立的条件ID
|
|
|
/// </summary>
|
|
|
/// <param name="conditions">条件列表</param>
|
|
|
/// <returns></returns>
|
|
|
private async Task<List<string>> GetConditionIds(List<WFCondition> conditions)
|
|
|
{
|
|
|
List<string> list = new List<string>();
|
|
|
foreach (var condition in conditions)
|
|
|
{
|
|
|
//获取数据id
|
|
|
var process = await client.Queryable<WFProcess>().FirstAsync(a => a.Id == _config.Params.ProcessId);
|
|
|
WFInstanceInfo instanceInfo = null;
|
|
|
if (process != null)
|
|
|
{
|
|
|
// instanceInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<WFInstanceInfo>(process.InstanceInfo);
|
|
|
instanceInfo = process.InstanceInfo;
|
|
|
}
|
|
|
|
|
|
if (condition.Type == "1")// 字段比较
|
|
|
{
|
|
|
string sql = string.Format("select \"{0}\" from \"{1}\" where \"{2}\" = @processId ", condition.Cfield, condition.Table, condition.Rfield, condition.Rfield);
|
|
|
//var dt = await dbFactory.BaseRepository(condition.DbCode).FindTable(sql, new { processId = _config.Params.ProcessId });
|
|
|
var pars = client.Ado.GetParameters(new { processId = instanceInfo.pkeyValue });
|
|
|
var dt = await client.Ado.GetDataTableAsync(sql, pars);
|
|
|
if (dt.Rows.Count > 0)
|
|
|
{
|
|
|
var value = dt.Rows[0][condition.Cfield.ToLower()].ToString();
|
|
|
|
|
|
switch (condition.CompareType)
|
|
|
{
|
|
|
case "1":
|
|
|
if (value == condition.Value)
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
break;
|
|
|
case "2":
|
|
|
if (value != condition.Value)
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
break;
|
|
|
case "3":
|
|
|
if (Convert.ToDecimal(value) > Convert.ToDecimal(condition.Value))
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
break;
|
|
|
case "4":
|
|
|
if (Convert.ToDecimal(value) >= Convert.ToDecimal(condition.Value))
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
break;
|
|
|
case "5":
|
|
|
if (Convert.ToDecimal(value) < Convert.ToDecimal(condition.Value))
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
break;
|
|
|
case "6":
|
|
|
if (Convert.ToDecimal(value) <= Convert.ToDecimal(condition.Value))
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
break;
|
|
|
case "7":
|
|
|
if (value.IndexOf(condition.Value) != -1)
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
break;
|
|
|
case "8":
|
|
|
if (value.IndexOf(condition.Value) == -1)
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
break;
|
|
|
case "9":
|
|
|
if (condition.Value.IndexOf(value) != -1)
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
break;
|
|
|
case "10":
|
|
|
if (condition.Value.IndexOf(value) == -1)
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{// sql语句
|
|
|
//var dt = await dbFactory.BaseRepository(condition.DbCode).FindTable(condition.Sql, new { processId = _config.Params.ProcessId, userId = CreateUser.Id, userAccount = CreateUser.Account, companyId = CreateUser.CompanyId, departmentId = CreateUser.DepartmentId });
|
|
|
//var pars = client.Ado.GetParameters(new { processId = _config.Params.ProcessId, userId = CreateUser.Id, userAccount = CreateUser.Account, companyId = CreateUser.CompanyId, departmentId = CreateUser.DepartmentId });
|
|
|
var pars = client.Ado.GetParameters(new { processId = instanceInfo.pkeyValue, userId = CreateUser.Id, userAccount = CreateUser.Account, companyId = CreateUser.CompanyId, departmentId = CreateUser.DepartmentId });
|
|
|
var dt = await client.Ado.GetDataTableAsync(condition.Sql, pars);
|
|
|
|
|
|
if (dt.Rows.Count > 0)
|
|
|
{
|
|
|
list.Add(condition.Code);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return list;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 判断是否自动同意
|
|
|
/// </summary>
|
|
|
/// <param name="auditUsers">审核处理人</param>
|
|
|
/// <param name="atuoAgrees">自动同意策略1.处理人就是提交人 2.处理人和上一步的处理人相同 3.处理人审批过</param>
|
|
|
/// <param name="isReject">是否是驳回</param>
|
|
|
/// <returns></returns>
|
|
|
private bool IsAtuoAgree(List<WFUserInfo> auditUsers, string[] atuoAgrees, bool isReject)
|
|
|
{
|
|
|
if (isReject)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
bool res = false;
|
|
|
if (auditUsers.Count == 0 || atuoAgrees.Length == 0)
|
|
|
{
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
foreach (var item in atuoAgrees)
|
|
|
{
|
|
|
switch (item)
|
|
|
{
|
|
|
case "1":
|
|
|
if (auditUsers.FindIndex(t => t.Id == CreateUser.Id) != -1)
|
|
|
{
|
|
|
res = true;
|
|
|
}
|
|
|
break;
|
|
|
case "2":
|
|
|
if (auditUsers.FindIndex(t => t.Id == CurrentUser.Id) != -1)
|
|
|
{
|
|
|
res = true;
|
|
|
}
|
|
|
break;
|
|
|
case "3":
|
|
|
if (auditUsers.FindIndex(t => t.IsAgree) != -1 && !isReject)
|
|
|
{
|
|
|
res = true;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取子流程任务
|
|
|
/// </summary>
|
|
|
/// <param name="unit"></param>
|
|
|
/// <param name="preUnitId"></param>
|
|
|
/// <param name="preUnitName"></param>
|
|
|
/// <returns></returns>
|
|
|
private WorkFlow.WFTask GetSubprocessTask(WFUnit unit, string preUnitId, string preUnitName)
|
|
|
{
|
|
|
WorkFlow.WFTask task = new WorkFlow.WFTask()
|
|
|
{
|
|
|
Type = 3,
|
|
|
UnitId = unit.Id,
|
|
|
Name = "子流程",
|
|
|
Token = Guid.NewGuid().ToString(),
|
|
|
PrevUnitId = preUnitId,
|
|
|
PrevUnitName = preUnitName,
|
|
|
ChildSchemeInfoId = unit.WfschemeId,
|
|
|
User = _config.Params.CreateUser
|
|
|
};
|
|
|
return task;
|
|
|
}
|
|
|
#endregion
|
|
|
}
|
|
|
}
|