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

601 lines
14 KiB

using learun.util;
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
namespace learun.workflow
{
/// <summary>
/// 版 本 EasyCode EC管理后台
/// Copyright (c) 2019-present EC管理有限公司
/// 创建人:tobin
/// 日 期:2019.11.22
/// 描 述:工作流引擎
/// </summary>
public class NWFEngine : NWFIEngine
{
#region 构造函数
/// <summary>
///
/// </summary>
/// <param name="nWFEngineConfig"></param>
public NWFEngine(NWFEngineConfig nWFEngineConfig)
{
// 初始化模板数据
config = nWFEngineConfig;
wfScheme = config.ParamConfig.Scheme.ToObject<NWFScheme>();
nodesMap = new Dictionary<string, NWFNodeInfo>();
foreach (var node in wfScheme.nodes)
{
if (!nodesMap.ContainsKey(node.id))
{
nodesMap.Add(node.id, node);
}
if (node.type == "startround")
{
startNode = node;
}
}
}
#endregion 构造函数
#region 模板数据信息
private NWFEngineConfig config;
private NWFScheme wfScheme = null;
private Dictionary<string, NWFNodeInfo> nodesMap = null;
private NWFNodeInfo startNode = null;
#endregion 模板数据信息
#region 私有方法
/// <summary>
/// 计算条件
/// </summary>
/// <param name="node">节点信息</param>
/// <returns></returns>
private async Task<bool> CalcCondition(NWFNodeInfo node)
{
bool res = true;
if (node.conditions.Count > 0)
{
#region 字段条件判断
foreach (var condition in node.conditions)
{
if (!string.IsNullOrEmpty(condition.dbId) && !string.IsNullOrEmpty(condition.table) && !string.IsNullOrEmpty(condition.field1) && !string.IsNullOrEmpty(condition.field2))
{
string sql = "select " + condition.field2 + " from " + condition.table + " where " + condition.field1 + " =@processId ";
DataTable dataTable = await config.DbFindTable(condition.dbId, sql, new { processId = config.ParamConfig.ProcessId });
if (dataTable.Rows.Count > 0)
{
string value = dataTable.Rows[0][0].ToString();
if (string.IsNullOrEmpty(value))
{
return false;
}
switch (condition.compareType)//比较类型1.等于2.不等于3.大于4.大于等于5.小于6.小于等于7.包含8.不包含9.包含于10.不包含于
{
case 1:// 等于
if (value != condition.value)
{
res = false;
}
break;
case 2:// 不等于
if (value == condition.value)
{
res = false;
}
break;
case 3:// 大于
if (Convert.ToDecimal(value) <= Convert.ToDecimal(condition.value))
{
res = false;
}
break;
case 4:// 大于等于
if (Convert.ToDecimal(value) < Convert.ToDecimal(condition.value))
{
res = false;
}
break;
case 5:// 小于
if (Convert.ToDecimal(value) >= Convert.ToDecimal(condition.value))
{
res = false;
}
break;
case 6:// 小于等于
if (Convert.ToDecimal(value) > Convert.ToDecimal(condition.value))
{
res = false;
}
break;
case 7:// 包含
if (!value.Contains(condition.value))
{
res = false;
}
break;
case 8:// 不包含
if (value.Contains(condition.value))
{
res = false;
}
break;
case 9:// 包含于
if (!condition.value.Contains(value))
{
res = false;
}
break;
case 10:// 不包含于
if (condition.value.Contains(value))
{
res = false;
}
break;
}
}
else
{
res = false;
}
}
if (!res)
{
break;
}
}
#endregion 字段条件判断
}
else if (!string.IsNullOrEmpty(node.conditionSql))
{
res = false;
// 流程进程ID
string conditionSql = node.conditionSql.Replace("{processId}", "@processId");
// 流程创建人用户
conditionSql = conditionSql.Replace("{userId}", "@userId");
conditionSql = conditionSql.Replace("{userAccount}", "@userAccount");
conditionSql = conditionSql.Replace("{companyId}", "@companyId");
conditionSql = conditionSql.Replace("{departmentId}", "@departmentId");
var param = new
{
processId = config.ParamConfig.ProcessId,
userId = config.ParamConfig.CreateUser.Id,
userAccount = config.ParamConfig.CreateUser.Account,
companyId = config.ParamConfig.CreateUser.CompanyId,
departmentId = config.ParamConfig.CreateUser.DepartmentId,
};
DataTable dataTable = await config.DbFindTable(node.dbConditionId, conditionSql, param);
if (dataTable.Rows.Count > 0)
{
res = true;
}
}
else
{
res = true;
}
return res;
}
/// <summary>
/// 计算会签
/// </summary>
/// <param name="wfNodeInfo">节点信息</param>
/// <param name="preNodeId">上一节点Id</param>
/// <param name="isAgree">同意</param>
/// <returns>0 不做处理 1 通过 -1 不通过</returns>
private async Task<int> CalcConfluence(NWFNodeInfo wfNodeInfo, string preNodeId, bool isAgree)
{
int res = 0;
int agreeNum = await config.GetAgreeNum(config.ParamConfig.ProcessId, wfNodeInfo.id);
int disAgreeNum = await config.GetDisAgreeNum(config.ParamConfig.ProcessId, wfNodeInfo.id);
List<string> preNodeList = GetPreNodes(wfNodeInfo.id);
switch (wfNodeInfo.confluenceType)//会签策略1-所有步骤通过,2-一个步骤通过即可,3-按百分比计算
{
case 1://所有步骤通过
if (isAgree)
{
if (preNodeList.Count == agreeNum + 1)
{
res = 1;
}
}
else
{
res = -1;
}
break;
case 2:
if (isAgree)
{
res = 1;
}
else if (preNodeList.Count == disAgreeNum + 1)
{
res = -1;
}
break;
case 3:
if (isAgree)
{
if ((agreeNum + 1) * 100 / preNodeList.Count >= Convert.ToDecimal(wfNodeInfo.confluenceRate))
{
res = 1;
}
}
else
{
if ((preNodeList.Count - disAgreeNum - 1) * 100 / preNodeList.Count < Convert.ToDecimal(wfNodeInfo.confluenceRate))
{
res = -1;
}
}
break;
}
return res;
}
#endregion 私有方法
#region 流程模板操作方法
/// <summary>
/// 获取流程模板
/// </summary>
/// <returns></returns>
public string GetScheme()
{
return config.ParamConfig.Scheme;
}
/// <summary>
/// 获取流程模板
/// </summary>
/// <returns></returns>
public NWFScheme GetSchemeObj()
{
return wfScheme;
}
/// <summary>
/// 获取开始节点
/// </summary>
/// <returns>节点信息</returns>
public NWFNodeInfo GetStartNode()
{
return startNode;
}
/// <summary>
/// 获取节点
/// </summary>
/// <param name="nodeId">流程处理节点ID</param>
/// <returns>节点信息</returns>
public NWFNodeInfo GetNode(string nodeId)
{
if (nodesMap.ContainsKey(nodeId))
{
return nodesMap[nodeId];
}
else
{
return null;
}
}
/// <summary>
/// 获取两节点间的线条
/// </summary>
/// <param name="fromNodeId">开始节点</param>
/// <param name="toNodeId">结束节点</param>
/// <param name="list">线条列表</param>
/// <param name="nodes"></param>
public bool GetLines(string fromNodeId, string toNodeId, List<NWFLineInfo> list, Dictionary<string, string> nodes = null)
{
bool res = false;
if (nodes == null)
{
nodes = new Dictionary<string, string>();
}
foreach (var line in wfScheme.lines)
{
if (line.from == fromNodeId)
{
if (line.to == toNodeId)
{
list.Add(line);
return true;
}
else
{
if (line.to == fromNodeId || nodesMap[line.to] == null || nodesMap[line.to].type == "endround")
{
}
else if (!nodes.ContainsKey(line.to))
{
nodes.Add(line.to, "1");
res = GetLines(line.to, toNodeId, list, nodes);
}
}
if (res)
{
list.Add(line);
return true;
}
}
}
return res;
}
/// <summary>
/// 获取下一节点
/// </summary>
/// <param name="nodeId">当前节点Id</param>
/// <param name="code">节点操作码 agree 同意 disagree 不同意 lrtimeout 超时</param>
/// <param name="lineList"></param>
/// <returns>节点信息列表</returns>
public List<NWFNodeInfo> GetNextNodes(string nodeId, string code, List<NWFLineInfo> lineList)
{
List<NWFNodeInfo> nextNodes = new List<NWFNodeInfo>();
// 找到与当前节点相连的线条
foreach (var line in wfScheme.lines)
{
if (line.from == nodeId)
{
bool isOk = false;
if (string.IsNullOrEmpty(line.strategy) || line.strategy == "1")
{
isOk = true;
}
else
{
var codeList = line.agreeList.Split(',');
foreach (string _code in codeList)
{
if (_code == code)
{
isOk = true;
break;
}
}
}
if (isOk)
{
if (nodesMap.ContainsKey(line.to))
{
nextNodes.Add(nodesMap[line.to]);
switch (line.operationType)
{// 绑定的操作类型
case "sql": // sql 语句
if (!string.IsNullOrEmpty(line.dbId) && !string.IsNullOrEmpty(line.strSql))
{
lineList.Add(line);
}
break;
case "interface": // interface 接口
if (!string.IsNullOrEmpty(line.strInterface))
{
lineList.Add(line);
}
break;
case "ioc": // 依赖注入
if (!string.IsNullOrEmpty(line.iocName))
{
lineList.Add(line);
}
break;
}
}
}
}
}
return nextNodes;
}
/// <summary>
/// 获取上一节点列表
/// </summary>
/// <param name="nodeId">当前节点Id</param>
/// <returns></returns>
public List<string> GetPreNodes(string nodeId)
{
List<string> list = new List<string>();
// 找到与当前节点相连的线条
foreach (var line in wfScheme.lines)
{
if (line.to == nodeId)
{
list.Add(line.from);
}
}
return list;
}
/// <summary>
/// 判断两节点是否连接
/// </summary>
/// <param name="formNodeId">开始节点</param>
/// <param name="toNodeId">结束节点</param>
/// <returns></returns>
public bool IsToNode(string formNodeId, string toNodeId)
{
bool res = false;
foreach (var line in wfScheme.lines)
{
if (line.from == formNodeId)
{
if (line.to == toNodeId)
{
res = true;
break;
}
else
{
if (line.to == formNodeId || nodesMap[line.to] == null || nodesMap[line.to].type == "endround")
{
break;
}
else
{
if (IsToNode(line.to, toNodeId))
{
res = true;
break;
}
}
}
}
}
return res;
}
#endregion 流程模板操作方法
#region 流程运行操作方法
/// <summary>
/// 获取配置参数信息
/// </summary>
/// <returns></returns>
public NWFEngineParamConfig GetConfig()
{
return config.ParamConfig;
}
/// <summary>
/// 获取接下来的任务节点信息
/// </summary>
/// <param name="beginNode">起始节点</param>
/// <param name="code">节点操作码 agree 同意 disagree 不同意 lrtimeout 超时</param>
/// <param name="isGetAuditors">是否获取下一节点审核人</param>
/// <param name="lineList">经过的线段需要执行操作的</param>
/// <returns></returns>
public async Task<List<NWFNodeInfo>> GetNextTaskNode(NWFNodeInfo beginNode, string code, bool isGetAuditors, List<NWFLineInfo> lineList)
{
List<NWFNodeInfo> list = new List<NWFNodeInfo>();
List<NWFNodeInfo> nextNodeList = GetNextNodes(beginNode.id, code, lineList);
Dictionary<string, string> auditers = null;
if (!string.IsNullOrEmpty(config.ParamConfig.Auditers))
{
auditers = config.ParamConfig.Auditers.ToObject<Dictionary<string, string>>();
}
foreach (var node in nextNodeList)
{
if (auditers != null && auditers.ContainsKey(node.id))
{
node.auditors = new List<NWFAuditor>();
node.auditors.Add(new NWFAuditor()
{
type = 3,
auditorId = auditers[node.id]
});
}
switch (node.type)
{
case "conditionnode": // 条件节点
if (!isGetAuditors)
{
if (await CalcCondition(node))
{
list.AddRange(await GetNextTaskNode(node, "agree", isGetAuditors, lineList));
}
else
{
list.AddRange(await GetNextTaskNode(node, "disagree", isGetAuditors, lineList));
}
}
else
{
list.AddRange(await GetNextTaskNode(node, "agree", isGetAuditors, lineList));
list.AddRange(await GetNextTaskNode(node, "disagree", isGetAuditors, lineList));
}
break;
case "confluencenode":// 会签节点
if (!isGetAuditors)
{
int confluenceRes;
if (code == "agree")
{
confluenceRes = await CalcConfluence(node, beginNode.id, true);
}
else
{
confluenceRes = await CalcConfluence(node, beginNode.id, false);
}
if (confluenceRes == 1)// 会签审核通过
{
list.AddRange(await GetNextTaskNode(node, "agree", false, lineList));
}
else if (confluenceRes == -1)// 会签审核不通过
{
list.AddRange(await GetNextTaskNode(node, "disagree", false, lineList));
}
node.confluenceRes = confluenceRes;
list.Add(node);
}
break;
case "auditornode":// 传阅节点
list.Add(node);
break;
case "childwfnode":// 子流程节点
list.Add(node);
if (node.childType == "2")
{ // 异步的情况下直接往下走
list.AddRange(await GetNextTaskNode(node, "agree", isGetAuditors, lineList));
}
break;
case "startround":// 开始节点 需要重新审核
list.Add(node);
config.ParamConfig.State = 1;
break;
case "endround":// 结束节点
config.ParamConfig.State = 2;
break;
default: // 默认一般审核界定啊
list.Add(node);
break;
}
}
return list;
}
#endregion 流程运行操作方法
}
}