1
This commit is contained in:
13
iMES.Core/WorkFlow/AuditBack.cs
Normal file
13
iMES.Core/WorkFlow/AuditBack.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace iMES.Core.WorkFlow
|
||||
{
|
||||
public enum AuditBack
|
||||
{
|
||||
流程结束 = 0,
|
||||
返回上一节点 = 1,
|
||||
流程重新开始 = 2
|
||||
}
|
||||
}
|
||||
13
iMES.Core/WorkFlow/AuditRefuse.cs
Normal file
13
iMES.Core/WorkFlow/AuditRefuse.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace iMES.Core.WorkFlow
|
||||
{
|
||||
public enum AuditRefuse
|
||||
{
|
||||
流程结束 = 0,
|
||||
返回上一节点 = 1,
|
||||
流程重新开始 = 2
|
||||
}
|
||||
}
|
||||
22
iMES.Core/WorkFlow/AuditStatus.cs
Normal file
22
iMES.Core/WorkFlow/AuditStatus.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace iMES.Core.WorkFlow
|
||||
{
|
||||
public enum AuditStatus
|
||||
{
|
||||
待审核 = 0,
|
||||
审核通过 = 1,
|
||||
审核中 = 2,
|
||||
审核未通过 = 3,
|
||||
驳回 = 4
|
||||
}
|
||||
|
||||
public enum AuditType
|
||||
{
|
||||
用户审批 = 1,
|
||||
角色审批 = 2,
|
||||
部门审批 = 3
|
||||
}
|
||||
}
|
||||
14
iMES.Core/WorkFlow/FieldFilter.cs
Normal file
14
iMES.Core/WorkFlow/FieldFilter.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace iMES.Core.WorkFlow
|
||||
{
|
||||
public class FieldFilter
|
||||
{
|
||||
public string Field { get; set; }
|
||||
public string Value { get; set; }
|
||||
|
||||
public string FilterType { get; set; }
|
||||
}
|
||||
}
|
||||
13
iMES.Core/WorkFlow/StepType.cs
Normal file
13
iMES.Core/WorkFlow/StepType.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace iMES.Core.WorkFlow
|
||||
{
|
||||
public enum StepType
|
||||
{
|
||||
start,
|
||||
end,
|
||||
node
|
||||
}
|
||||
}
|
||||
310
iMES.Core/WorkFlow/WorkFlowContainer.cs
Normal file
310
iMES.Core/WorkFlow/WorkFlowContainer.cs
Normal file
@@ -0,0 +1,310 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using iMES.Core.DBManager;
|
||||
using iMES.Core.EFDbContext;
|
||||
using iMES.Core.Extensions;
|
||||
using iMES.Core.Utilities;
|
||||
using iMES.Entity.DomainModels;
|
||||
|
||||
namespace iMES.Core.WorkFlow
|
||||
{
|
||||
public class WorkFlowContainer
|
||||
{
|
||||
private static WorkFlowContainer _instance;
|
||||
private static Dictionary<string, string> _container = new Dictionary<string, string>();
|
||||
private static Dictionary<string, string[]> _filterFields = new Dictionary<string, string[]>();
|
||||
|
||||
private static List<Type> _types = new List<Type>();
|
||||
|
||||
public static WorkFlowContainer Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance != null)
|
||||
{
|
||||
return _instance;
|
||||
|
||||
}
|
||||
_instance = new WorkFlowContainer();
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="name">流程实例名称</param>
|
||||
/// <param name="filterFields">流程配置可筛选条件字段</param>
|
||||
/// <returns></returns>
|
||||
public WorkFlowContainer Use<T>(string name = null, Expression<Func<T, object>> filterFields = null)
|
||||
{
|
||||
Type type = typeof(T);
|
||||
if (_types.Contains(type))
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
|
||||
_container[type.Name] = name ?? typeof(T).GetEntityTableCnName();
|
||||
if (filterFields != null)
|
||||
{
|
||||
_filterFields[type.Name] = filterFields.GetExpressionToArray();
|
||||
}
|
||||
_types.Add(type);
|
||||
return _instance;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
List<Sys_WorkFlow> list = null;
|
||||
List<string> tables = _container.Select(s => s.Key).ToList();
|
||||
using (SysDbContext contenxt = new SysDbContext())
|
||||
{
|
||||
list = contenxt.Set<Sys_WorkFlow>().Where(c => tables.Contains(c.WorkTable)).Include(x => x.Sys_WorkFlowStep).ToList();
|
||||
}
|
||||
foreach (var item in list.GroupBy(x => x.WorkTable))
|
||||
{
|
||||
Type type = _types.Where(x => x.Name == item.Key).FirstOrDefault();
|
||||
InitOptions(type, item.ToList());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"初始化流程调用数据库异常,异常信息{ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static string[] GetFilterFields(string tableName)
|
||||
{
|
||||
_filterFields.TryGetValue(tableName, out string[] fields);
|
||||
return fields;
|
||||
}
|
||||
|
||||
public static object GetDic()
|
||||
{
|
||||
return _container.Select(s => new { key = s.Key, value = s.Value }).ToList();
|
||||
}
|
||||
|
||||
public static bool Exists<T>()
|
||||
{
|
||||
return Exists(typeof(T).GetEntityTableName());
|
||||
}
|
||||
|
||||
public static bool Exists(string table)
|
||||
{
|
||||
return _container.ContainsKey(table);
|
||||
}
|
||||
|
||||
private WorkFlowContainer InitOptions(Type type, List<Sys_WorkFlow> list)
|
||||
{
|
||||
string tableName = type.GetEntityTableName();
|
||||
|
||||
foreach (var workFlow in list)
|
||||
{
|
||||
try
|
||||
{
|
||||
var obj = typeof(WorkFlowContainer).GetMethod("Add").MakeGenericMethod(new Type[] { type });
|
||||
obj.Invoke(this, new object[] { workFlow, workFlow.Sys_WorkFlowStep, true });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"初始化流程配置信息异常,表:【{tableName}】,异常信息{e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
Console.WriteLine($"初始化流程表:【{tableName}】成功");
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
public static IEnumerable<WorkFlowTableOptions> GetFlowOptions(Func<WorkFlowTableOptions, bool> func)
|
||||
{
|
||||
return _workFlowTableOptions.Where(func);
|
||||
}
|
||||
|
||||
public static WorkFlowTableOptions GetFlowOptions<T>(T entity)
|
||||
{
|
||||
string tableName = typeof(T).GetEntityTableName();
|
||||
if (!Exists(tableName) || !_workFlowTableOptions.Any(c => c.WorkTable == tableName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
string key = typeof(T).GetKeyProperty().GetValue(entity).ToString();
|
||||
|
||||
var flowTable = DBServerProvider.DbContext.Set<Sys_WorkFlowTable>().Include(c => c.Sys_WorkFlowTableStep)
|
||||
.Where(c => c.WorkTableKey == key&&c.WorkTable==tableName)
|
||||
.OrderByDescending(x => x.CreateDate)
|
||||
.FirstOrDefault();
|
||||
|
||||
var entities = new List<T>() { entity };
|
||||
|
||||
//还未进入流程,找到满足流程的配置
|
||||
if (flowTable == null)
|
||||
{
|
||||
//优先判断满足条件的
|
||||
var filter = _workFlowTableOptions.Where(x => x.WorkTable == tableName
|
||||
&& x.FilterList.Any(c => c.StepAttrType == StepType.start.ToString()
|
||||
&& c.Expression != null && entities.Any(((Func<T, bool>)c.Expression))))
|
||||
.OrderByDescending(x => x.Weight)
|
||||
.FirstOrDefault();
|
||||
if (filter != null)
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
//没有找到满足条件的用无条件的流程
|
||||
|
||||
return _workFlowTableOptions.Where(x => x.WorkTable == tableName
|
||||
&& x.FilterList.Any(c => c.StepAttrType == StepType.start.ToString()
|
||||
&& c.Expression == null))
|
||||
.OrderByDescending(x => x.Weight)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static readonly List<WorkFlowTableOptions> _workFlowTableOptions = new List<WorkFlowTableOptions>();
|
||||
private static object _wk_object = new object();
|
||||
|
||||
|
||||
public WebResponseContent AddTable(Sys_WorkFlow workFlow, List<Sys_WorkFlowStep> flowSteps, bool showError = true)
|
||||
{
|
||||
WebResponseContent webResponse = new WebResponseContent();
|
||||
Type type = _types.Where(x => x.GetEntityTableName() == workFlow.WorkTable).FirstOrDefault();
|
||||
if (type == null)
|
||||
{
|
||||
return webResponse.Error($"{workFlow.WorkTableName}未注册");
|
||||
}
|
||||
|
||||
Del(workFlow.WorkFlow_Id);
|
||||
|
||||
var obj = typeof(WorkFlowContainer).GetMethod("Add").MakeGenericMethod(new Type[] { type });
|
||||
webResponse = obj.Invoke(this, new object[] { workFlow, flowSteps, true }) as WebResponseContent;
|
||||
if (webResponse.Status && string.IsNullOrEmpty(webResponse.Message))
|
||||
{
|
||||
webResponse.Message = "流程创建成功";
|
||||
}
|
||||
return webResponse;
|
||||
}
|
||||
|
||||
public static WebResponseContent Add<T>(Sys_WorkFlow workFlow, List<Sys_WorkFlowStep> flowSteps, bool showError = true) where T : class
|
||||
{
|
||||
WebResponseContent webResponse = new WebResponseContent();
|
||||
lock (_wk_object)
|
||||
{
|
||||
WorkFlowTableOptions options = new WorkFlowTableOptions()
|
||||
{
|
||||
WorkFlow_Id = workFlow.WorkFlow_Id,
|
||||
WorkTable = workFlow.WorkTable,
|
||||
WorkName = workFlow.WorkName,
|
||||
FilterList = new List<FilterOptions>()
|
||||
};
|
||||
bool success = true;
|
||||
//结束节点不生成条件
|
||||
foreach (var item in flowSteps.Where(c => c.StepAttrType != StepType.end.ToString()))
|
||||
{
|
||||
var filters = item.Filters.DeserializeObject<List<FieldFilter>>();
|
||||
try
|
||||
{
|
||||
Expression<Func<T, bool>> expression = WorkFlowFilter.Create<T>(filters);
|
||||
options.FilterList.Add(new FilterOptions()
|
||||
{
|
||||
StepId = item.StepId,
|
||||
ParentId = item.ParentId,
|
||||
NextStepIds = item.NextStepIds,
|
||||
StepAttrType = item.StepAttrType,
|
||||
Expression = expression?.Compile()
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
string message = $"流程:【{workFlow.WorkName}】,节点:【{item.StepName}】条件异常,请检查【值】与【字段的类型】是否匹配,节点配置:{item.Filters}";
|
||||
|
||||
Console.WriteLine(message + ex.Message);
|
||||
if (showError)
|
||||
{
|
||||
// throw new Exception(message);
|
||||
return webResponse.Error(message);
|
||||
}
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
if (options.Sys_WorkFlowStep == null)
|
||||
{
|
||||
options.Sys_WorkFlowStep = flowSteps;
|
||||
}
|
||||
|
||||
var data = _workFlowTableOptions.Where(x => x.WorkFlow_Id == workFlow.WorkFlow_Id).FirstOrDefault();
|
||||
if (data != null)
|
||||
{
|
||||
data.WorkTable = options.WorkTable;
|
||||
data.WorkName = options.WorkName;
|
||||
data.FilterList = options.FilterList;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (options.FilterList != null)
|
||||
{
|
||||
foreach (var item in options.FilterList)
|
||||
{
|
||||
if (item.ParentId != null)
|
||||
{
|
||||
item.ParentIds = item.ParentId.Split(",");
|
||||
}
|
||||
else
|
||||
{
|
||||
item.ParentIds = new string[] { };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_workFlowTableOptions.Add(options);
|
||||
}
|
||||
}
|
||||
return webResponse.OK();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetName<T>()
|
||||
{
|
||||
Type type = typeof(T);
|
||||
if (_container.TryGetValue(type.Name, out string name))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
return type.GetEntityTableCnName();
|
||||
}
|
||||
public static void Del(Guid workFlowId)
|
||||
{
|
||||
int index = _workFlowTableOptions.FindIndex(x => x.WorkFlow_Id == workFlowId);
|
||||
if (index != -1)
|
||||
{
|
||||
_workFlowTableOptions.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DelRange(Guid[] workFlowId)
|
||||
{
|
||||
foreach (var id in workFlowId)
|
||||
{
|
||||
Del(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
98
iMES.Core/WorkFlow/WorkFlowFilter.cs
Normal file
98
iMES.Core/WorkFlow/WorkFlowFilter.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using iMES.Core.Enums;
|
||||
using iMES.Core.Extensions;
|
||||
|
||||
namespace iMES.Core.WorkFlow
|
||||
{
|
||||
public static class WorkFlowFilter
|
||||
{
|
||||
|
||||
public static Expression<Func<T, bool>> Create<T>(List<FieldFilter> filters) where T : class
|
||||
{
|
||||
if (filters == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
filters = filters.Where(x => !string.IsNullOrEmpty(x.Field)).ToList();
|
||||
if (!filters.Any(x => !string.IsNullOrEmpty(x.Value)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<string> fields = typeof(T).GetProperties().Select(s => s.Name).ToList();
|
||||
Expression<Func<T, bool>> orFilter = null;
|
||||
Expression<Func<T, bool>> expression = x => true;
|
||||
foreach (var filter in filters)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filter.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!fields.Contains(filter.Field))
|
||||
{
|
||||
string msg = $"表【{typeof(T).GetEntityTableName()}】不存在字段【{filter.Field}】";
|
||||
Console.WriteLine(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
filter.Value = filter.Value.Trim();
|
||||
LinqExpressionType type = LinqExpressionType.Equal;
|
||||
switch (filter.FilterType)
|
||||
{
|
||||
case "!=":
|
||||
type = LinqExpressionType.NotEqual;
|
||||
break;
|
||||
case ">":
|
||||
type = LinqExpressionType.GreaterThan;
|
||||
break;
|
||||
case ">=":
|
||||
type = LinqExpressionType.ThanOrEqual;
|
||||
break;
|
||||
case "小于":
|
||||
case "<":
|
||||
type = LinqExpressionType.LessThan;
|
||||
break;
|
||||
case "<=":
|
||||
type = LinqExpressionType.LessThanOrEqual;
|
||||
break;
|
||||
case "in":
|
||||
type = LinqExpressionType.In;
|
||||
break;
|
||||
case "like":
|
||||
type = LinqExpressionType.Contains;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (type == LinqExpressionType.In)
|
||||
{
|
||||
var values = filter.Value.Split(",").Where(x => !string.IsNullOrEmpty(x)).ToList();
|
||||
if (values.Count > 0)
|
||||
{
|
||||
expression = expression.And(filter.Field.CreateExpression<T>(values, type));
|
||||
}
|
||||
}
|
||||
else if (filter.FilterType == "or")
|
||||
{
|
||||
if (orFilter == null)
|
||||
{
|
||||
orFilter = x => false;
|
||||
}
|
||||
orFilter = orFilter.Or(filter.Field.CreateExpression<T>(filter.Value, LinqExpressionType.Equal));
|
||||
}
|
||||
else
|
||||
{
|
||||
expression = expression.And(filter.Field.CreateExpression<T>(filter.Value, type));
|
||||
}
|
||||
}
|
||||
if (orFilter != null)
|
||||
{
|
||||
expression = expression.And(orFilter);
|
||||
}
|
||||
return expression;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
530
iMES.Core/WorkFlow/WorkFlowManager.cs
Normal file
530
iMES.Core/WorkFlow/WorkFlowManager.cs
Normal file
@@ -0,0 +1,530 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using iMES.Core.DBManager;
|
||||
using iMES.Core.EFDbContext;
|
||||
using iMES.Core.Extensions;
|
||||
using iMES.Core.ManageUser;
|
||||
using iMES.Core.Services;
|
||||
using iMES.Core.Utilities;
|
||||
using iMES.Entity.DomainModels;
|
||||
|
||||
namespace iMES.Core.WorkFlow
|
||||
{
|
||||
public static class WorkFlowManager
|
||||
{
|
||||
public static bool Exists<T>()
|
||||
{
|
||||
return WorkFlowContainer.Exists<T>();
|
||||
}
|
||||
|
||||
public static bool Exists<T>(T entity)
|
||||
{
|
||||
return WorkFlowContainer.Exists<T>() && GetAuditFlowTable<T>(typeof(T).GetKeyProperty().GetValue(entity).ToString()) != null;
|
||||
}
|
||||
public static bool Exists(string table)
|
||||
{
|
||||
return WorkFlowContainer.Exists(table);
|
||||
}
|
||||
|
||||
public static int GetAuditStatus<T>(string value)
|
||||
{
|
||||
return GetAuditFlowTable<T>(value)?.AuditStatus ?? 0;
|
||||
}
|
||||
|
||||
public static Sys_WorkFlowTable GetAuditFlowTable<T>(string workTableKey)
|
||||
{
|
||||
var table = DBServerProvider.DbContext.Set<Sys_WorkFlowTable>()
|
||||
.Where(x => x.WorkTable == typeof(T).GetEntityTableName() && x.WorkTableKey == workTableKey)
|
||||
// .Select(s => new { s.CurrentStepId,s.AuditStatus})
|
||||
.FirstOrDefault();
|
||||
return table;
|
||||
}
|
||||
|
||||
private static void Rewrite<T>(T entity, Sys_WorkFlow workFlow, bool changeTableStatus) where T : class
|
||||
{
|
||||
var autditProperty = typeof(T).GetProperties().Where(x => x.Name.ToLower() == "auditstatus").FirstOrDefault();
|
||||
if (autditProperty == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string value = typeof(T).GetKeyProperty().GetValue(entity).ToString();
|
||||
|
||||
var dbContext = DBServerProvider.DbContext;
|
||||
|
||||
|
||||
var workTable = dbContext.Set<Sys_WorkFlowTable>().Where(x => x.WorkTableKey == value && x.WorkFlow_Id == workFlow.WorkFlow_Id)
|
||||
.AsNoTracking()
|
||||
.Include(x => x.Sys_WorkFlowTableStep).FirstOrDefault();
|
||||
if (workTable == null || workFlow.Sys_WorkFlowStep == null || workFlow.Sys_WorkFlowStep.Count == 0)
|
||||
{
|
||||
Console.WriteLine($"未查到流程数据,id:{ workFlow.WorkFlow_Id}");
|
||||
return;
|
||||
}
|
||||
// workTable.CurrentOrderId = 1;
|
||||
|
||||
//这里还未处理回退到上一个节点
|
||||
|
||||
//重新设置第一个节点(有可能是返回上一个节点)
|
||||
string startStepId = workTable.Sys_WorkFlowTableStep.Where(x => x.StepAttrType == StepType.start.ToString())
|
||||
.Select(s => s.StepId).FirstOrDefault();
|
||||
|
||||
workTable.CurrentStepId = workTable.Sys_WorkFlowTableStep.Where(x => x.ParentId == startStepId).Select(s => s.StepId).FirstOrDefault();
|
||||
|
||||
workTable.AuditStatus = (int)AuditStatus.待审核;
|
||||
workTable.Sys_WorkFlowTableStep.ForEach(item =>
|
||||
{
|
||||
item.Enable = 0;
|
||||
item.AuditId = null;
|
||||
item.Auditor = null;
|
||||
item.AuditDate = null;
|
||||
item.Remark = null;
|
||||
});
|
||||
|
||||
if (changeTableStatus)
|
||||
{
|
||||
dbContext.Entry(entity).State = EntityState.Detached;
|
||||
autditProperty.SetValue(entity, 0);
|
||||
dbContext.Entry(entity).Property(autditProperty.Name).IsModified = true;
|
||||
}
|
||||
|
||||
dbContext.Entry(workTable).State = EntityState.Detached;
|
||||
dbContext.Update(workTable);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 新建时写入流程
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="rewrite">是否重新生成流程</param>
|
||||
/// <param name="changeTableStatus">是否修改原表的审批状态</param>
|
||||
public static void AddProcese<T>(T entity, bool rewrite = false, bool changeTableStatus = true) where T : class
|
||||
{
|
||||
WorkFlowTableOptions workFlow = WorkFlowContainer.GetFlowOptions(entity);
|
||||
//没有对应的流程信息
|
||||
if (workFlow == null || workFlow.FilterList.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
workFlow.WorkTableName = WorkFlowContainer.GetName<T>();
|
||||
string workTable = typeof(T).GetEntityTableName();
|
||||
|
||||
////重新生成流程
|
||||
if (rewrite)
|
||||
{
|
||||
Rewrite(entity, workFlow, changeTableStatus);
|
||||
return;
|
||||
}
|
||||
|
||||
var userInfo = UserContext.Current.UserInfo;
|
||||
Guid workFlowTable_Id = Guid.NewGuid();
|
||||
Sys_WorkFlowTable workFlowTable = new Sys_WorkFlowTable()
|
||||
{
|
||||
WorkFlowTable_Id = workFlowTable_Id,
|
||||
AuditStatus = (int)AuditStatus.待审核,
|
||||
Enable = 1,
|
||||
WorkFlow_Id = workFlow.WorkFlow_Id,
|
||||
WorkName = workFlow.WorkName,
|
||||
WorkTable = workTable,
|
||||
WorkTableKey = typeof(T).GetKeyProperty().GetValue(entity).ToString(),
|
||||
WorkTableName = workFlow.WorkTableName,
|
||||
CreateID = userInfo.User_Id,
|
||||
CreateDate = DateTime.Now,
|
||||
Creator = userInfo.UserTrueName
|
||||
};
|
||||
//生成流程的下一步
|
||||
var steps = workFlow.FilterList.Where(x => x.StepAttrType == StepType.start.ToString()).Select(s => new Sys_WorkFlowTableStep()
|
||||
{
|
||||
Sys_WorkFlowTableStep_Id = Guid.NewGuid(),
|
||||
WorkFlowTable_Id = workFlowTable_Id,
|
||||
WorkFlow_Id = workFlow.WorkFlow_Id,
|
||||
StepId = s.StepId,
|
||||
StepName = s.StepName ?? "流程开始",
|
||||
StepAttrType = s.StepAttrType,
|
||||
NextStepId = null,
|
||||
ParentId = null,
|
||||
StepType = s.StepType,
|
||||
StepValue = s.StepValue,
|
||||
OrderId = 0,
|
||||
Enable = 1,
|
||||
CreateDate = DateTime.Now,
|
||||
Creator = userInfo.UserTrueName,
|
||||
CreateID = userInfo.User_Id
|
||||
}).ToList();
|
||||
|
||||
var entities = new List<T>() { entity };
|
||||
for (int i = 0; i < steps.Count; i++)
|
||||
{
|
||||
var item = steps[i];
|
||||
//查找下一个满足条件的节点数据
|
||||
FilterOptions filter = workFlow.FilterList.Where(c => c.ParentIds.Contains(item.StepId)
|
||||
&& c.Expression != null
|
||||
&& entities.Any(((Func<T, bool>)c.Expression))
|
||||
).FirstOrDefault();
|
||||
//未找到满足条件的找无条件的节点
|
||||
if (filter == null)
|
||||
{
|
||||
filter = workFlow.FilterList.Where(c => c.ParentIds.Contains(item.StepId) && c.Expression == null).FirstOrDefault();
|
||||
}
|
||||
if (filter != null)
|
||||
{
|
||||
var setp = workFlow.Sys_WorkFlowStep.Where(x => x.StepId == filter.StepId).Select(s => new Sys_WorkFlowTableStep()
|
||||
{
|
||||
Sys_WorkFlowTableStep_Id = Guid.NewGuid(),
|
||||
WorkFlowTable_Id = workFlowTable_Id,
|
||||
WorkFlow_Id = s.WorkFlow_Id,
|
||||
|
||||
StepId = s.StepId,
|
||||
StepName = s.StepName,
|
||||
StepAttrType = s.StepAttrType,
|
||||
NextStepId = null,
|
||||
ParentId = item.StepId,
|
||||
StepType = s.StepType,
|
||||
StepValue = s.StepValue,
|
||||
OrderId = i + 1,
|
||||
Enable = 1,
|
||||
CreateDate = DateTime.Now,
|
||||
}).FirstOrDefault();
|
||||
|
||||
//显示后续部门与角色审批人待完
|
||||
|
||||
//设置下个审核节点
|
||||
item.NextStepId = setp.StepId;
|
||||
if (!steps.Any(x => x.StepId == setp.StepId))
|
||||
{
|
||||
steps.Add(setp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//找不到满足条件的节点,直接结束流程
|
||||
var end = workFlow.Sys_WorkFlowStep.Where(c => c.StepAttrType == StepType.end.ToString()).ToList();
|
||||
|
||||
if (end.Count > 0)
|
||||
{
|
||||
item.NextStepId = end[0].StepId;
|
||||
steps.Add(end.Select(s => new Sys_WorkFlowTableStep()
|
||||
{
|
||||
Sys_WorkFlowTableStep_Id = Guid.NewGuid(),
|
||||
WorkFlowTable_Id = workFlowTable_Id,
|
||||
WorkFlow_Id = s.WorkFlow_Id,
|
||||
StepId = s.StepId,
|
||||
StepName = s.StepName,
|
||||
StepAttrType = s.StepAttrType,
|
||||
NextStepId = null,
|
||||
ParentId = item.StepId,
|
||||
StepType = s.StepType,
|
||||
StepValue = s.StepValue,
|
||||
OrderId = i + 1,
|
||||
Enable = 1,
|
||||
CreateDate = DateTime.Now,
|
||||
}).FirstOrDefault());
|
||||
i = steps.Count + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var setp in steps)
|
||||
{
|
||||
if (setp.StepType == (int)AuditType.用户审批)
|
||||
{
|
||||
setp.AuditId = setp.StepValue.GetInt();
|
||||
}
|
||||
}
|
||||
|
||||
//没有满足流程的数据不走流程
|
||||
int count = steps.Where(x => x.StepAttrType != StepType.start.ToString() && x.StepAttrType != StepType.end.ToString()).Count();
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//设置进入流程后的第一个审核节点,(开始节点的下一个节点)
|
||||
var nodeInfo = steps.Where(x => x.ParentId == steps[0].StepId).Select(s => new { s.StepId, s.StepName }).FirstOrDefault();
|
||||
workFlowTable.CurrentStepId = nodeInfo.StepId;
|
||||
workFlowTable.StepName = nodeInfo.StepName;
|
||||
|
||||
workFlowTable.Sys_WorkFlowTableStep = steps;
|
||||
|
||||
//写入日志
|
||||
var log = new Sys_WorkFlowTableAuditLog()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
WorkFlowTable_Id = workFlowTable.WorkFlowTable_Id,
|
||||
CreateDate = DateTime.Now,
|
||||
AuditStatus = (int)AuditStatus.待审核,
|
||||
Remark = $"[{userInfo.UserTrueName}]提交了数据"
|
||||
};
|
||||
var dbContext = DBServerProvider.DbContext;
|
||||
dbContext.Set<Sys_WorkFlowTable>().Add(workFlowTable);
|
||||
dbContext.Set<Sys_WorkFlowTableAuditLog>().Add(log);
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 审核
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="status"></param>
|
||||
/// <param name="remark"></param>
|
||||
/// <param name="autditProperty"></param>
|
||||
/// <param name="workFlowExecuting"></param>
|
||||
/// <param name="workFlowExecuted"></param>
|
||||
/// <returns></returns>
|
||||
public static WebResponseContent Audit<T>(T entity, AuditStatus status, string remark,
|
||||
PropertyInfo autditProperty,
|
||||
Func<T, AuditStatus, bool, WebResponseContent> workFlowExecuting,
|
||||
Func<T, AuditStatus, List<int>, bool, WebResponseContent> workFlowExecuted,
|
||||
bool init = false,
|
||||
Action<T, List<int>> initInvoke = null
|
||||
) where T : class
|
||||
{
|
||||
WebResponseContent webResponse = new WebResponseContent(true);
|
||||
if (init)
|
||||
{
|
||||
if (!WorkFlowContainer.Exists<T>())
|
||||
{
|
||||
return webResponse;
|
||||
}
|
||||
}
|
||||
var dbContext = DBServerProvider.DbContext;
|
||||
dbContext.QueryTracking = true; ;
|
||||
var query = dbContext.Set<T>();
|
||||
|
||||
var keyProperty = typeof(T).GetKeyProperty();
|
||||
string key = keyProperty.GetValue(entity).ToString();
|
||||
string workTable = typeof(T).GetEntityTableName();
|
||||
|
||||
Sys_WorkFlowTable workFlow = dbContext.Set<Sys_WorkFlowTable>()
|
||||
.Where(x => x.WorkTable == workTable && x.WorkTableKey == key)
|
||||
.Include(x => x.Sys_WorkFlowTableStep)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (workFlow == null)
|
||||
{
|
||||
return webResponse.Error("未查到流程信息,请检查数据是否被删除");
|
||||
}
|
||||
|
||||
|
||||
workFlow.AuditStatus = (int)status;
|
||||
|
||||
var currentStep = workFlow.Sys_WorkFlowTableStep.Where(x => x.StepId == workFlow.CurrentStepId).FirstOrDefault();
|
||||
|
||||
if (currentStep == null)
|
||||
{
|
||||
return webResponse.Error($"未查到流程陈点[workFlow.CurrentStepId]信息,请检查数据是否被删除");
|
||||
}
|
||||
var user = UserContext.Current.UserInfo;
|
||||
//生成审核记录
|
||||
var log = new Sys_WorkFlowTableAuditLog()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
StepId = currentStep.StepId,
|
||||
WorkFlowTable_Id = currentStep.WorkFlowTable_Id,
|
||||
WorkFlowTableStep_Id = currentStep.Sys_WorkFlowTableStep_Id,
|
||||
AuditDate = DateTime.Now,
|
||||
AuditId = user.User_Id,
|
||||
Auditor = user.UserTrueName,
|
||||
AuditResult = remark,
|
||||
Remark = remark,
|
||||
AuditStatus = (int)status,
|
||||
CreateDate = DateTime.Now,
|
||||
StepName = currentStep.StepName
|
||||
};
|
||||
|
||||
if (autditProperty == null)
|
||||
{
|
||||
autditProperty = typeof(T).GetProperties().Where(s => s.Name.ToLower() == "auditstatus").FirstOrDefault();
|
||||
}
|
||||
bool isLast = false;
|
||||
Sys_WorkFlowTableStep nextStep = null;
|
||||
|
||||
//更新明细记录
|
||||
workFlow.Sys_WorkFlowTableStep.ForEach(x =>
|
||||
{
|
||||
if (workFlow.CurrentStepId == x.StepId)
|
||||
{
|
||||
x.AuditId = user.User_Id;
|
||||
x.Auditor = user.UserTrueName;
|
||||
x.AuditDate = DateTime.Now;
|
||||
//如果审核拒绝或驳回并退回上一步,待完
|
||||
x.AuditStatus = (int)status;
|
||||
x.Remark = remark;
|
||||
}
|
||||
});
|
||||
//获取下一步审核id
|
||||
var nextStepId = currentStep.NextStepId;
|
||||
|
||||
nextStep = workFlow.Sys_WorkFlowTableStep.Where(x => x.StepId == nextStepId).FirstOrDefault();
|
||||
//没有找到下一步审批,审核完成
|
||||
if ((nextStep == null || nextStep.StepAttrType == StepType.end.ToString()))
|
||||
{
|
||||
if (status == AuditStatus.审核通过)
|
||||
{
|
||||
workFlow.CurrentStepId = "审核完成";
|
||||
}
|
||||
else
|
||||
{
|
||||
workFlow.CurrentStepId = "流程结束";
|
||||
}
|
||||
var filterOptions = WorkFlowContainer.GetFlowOptions(x => x.WorkTable == workTable)
|
||||
.FirstOrDefault()
|
||||
?.FilterList
|
||||
?.Where(x => x.StepId == currentStep.StepId)
|
||||
?.FirstOrDefault();
|
||||
|
||||
workFlow.AuditStatus = (int)status;
|
||||
|
||||
if (filterOptions != null)
|
||||
{
|
||||
//发送邮件(appsettings.json配置文件里添加邮件信息)
|
||||
SendMail(workFlow, filterOptions, nextStep, dbContext);
|
||||
//如果审核拒绝或驳回并退回上一步,待完
|
||||
//重新配置流程待完
|
||||
if (status == AuditStatus.审核未通过)
|
||||
{
|
||||
if (filterOptions.AuditRefuse == (int)AuditRefuse.返回上一节点)
|
||||
{
|
||||
|
||||
}
|
||||
else if (filterOptions.AuditRefuse == (int)AuditRefuse.流程重新开始)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
else if (status == AuditStatus.驳回)
|
||||
{
|
||||
if (filterOptions.AuditBack == (int)AuditBack.返回上一节点)
|
||||
{
|
||||
|
||||
}
|
||||
else if (filterOptions.AuditBack == (int)AuditBack.流程重新开始)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
autditProperty.SetValue(entity, (int)status);
|
||||
dbContext.Set<Sys_WorkFlowTable>().Update(workFlow);
|
||||
query.Update(entity);
|
||||
dbContext.Set<Sys_WorkFlowTableAuditLog>().Add(log);
|
||||
dbContext.SaveChanges();
|
||||
return webResponse;
|
||||
}
|
||||
//指向下一个人审批
|
||||
if (nextStep != null && status == AuditStatus.审核通过)
|
||||
{
|
||||
workFlow.CurrentStepId = nextStep.StepId;
|
||||
//原表显示审核中状态
|
||||
autditProperty.SetValue(entity, (int)AuditStatus.审核中);
|
||||
workFlow.AuditStatus = (int)AuditStatus.审核中;
|
||||
}
|
||||
else
|
||||
{
|
||||
autditProperty.SetValue(entity, (int)status);
|
||||
}
|
||||
|
||||
|
||||
//下一个节点=null或节下一个节点为结束节点,流程结束
|
||||
if (nextStep == null || workFlow.Sys_WorkFlowTableStep.Exists(c => c.StepId == nextStep.StepId && c.StepAttrType == StepType.end.ToString()))
|
||||
{
|
||||
isLast = true;
|
||||
}
|
||||
|
||||
if (workFlowExecuting != null)
|
||||
{
|
||||
webResponse = workFlowExecuting.Invoke(entity, status, isLast);
|
||||
if (!webResponse.Status)
|
||||
{
|
||||
return webResponse;
|
||||
}
|
||||
}
|
||||
|
||||
query.Update(entity);
|
||||
|
||||
|
||||
dbContext.Set<Sys_WorkFlowTable>().Update(workFlow);
|
||||
dbContext.Set<Sys_WorkFlowTableAuditLog>().Add(log);
|
||||
|
||||
dbContext.SaveChanges();
|
||||
dbContext.Entry(workFlow).State = EntityState.Detached;
|
||||
if (workFlowExecuted != null)
|
||||
{
|
||||
webResponse = workFlowExecuted.Invoke(entity, status, GetAuditUserIds(nextStep?.StepType ?? 0, nextStep?.StepValue), isLast);
|
||||
}
|
||||
return webResponse;
|
||||
}
|
||||
|
||||
private static void SendMail(Sys_WorkFlowTable workFlow, FilterOptions filterOptions, Sys_WorkFlowTableStep nextStep, SysDbContext dbContext)
|
||||
{
|
||||
if (filterOptions.SendMail != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//审核发送邮件通知待完
|
||||
var userIds = GetAuditUserIds(nextStep.StepType ?? 0, nextStep.StepValue);
|
||||
if (userIds.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var emails = dbContext.Set<Sys_User>()
|
||||
.Where(x => userIds.Contains(x.User_Id) && x.Email != null & x.Email != "").Select(s => s.Email)
|
||||
.ToList();
|
||||
Task.Run(() =>
|
||||
{
|
||||
string msg = "";
|
||||
try
|
||||
{
|
||||
string title = $"有新的任务待审批:流程【{workFlow.WorkName}】,任务【{nextStep.StepName}】";
|
||||
MailHelper.Send(title, title, string.Join(";", emails));
|
||||
msg = $"审批流程发送邮件,流程名称:{workFlow.WorkName},流程id:{workFlow.WorkFlow_Id},步骤:{nextStep.StepName},步骤Id:{nextStep.StepId},收件人:{ string.Join(";", emails)}";
|
||||
Logger.AddAsync(msg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
msg += "邮件发送异常:";
|
||||
Logger.AddAsync(msg, ex.Message + ex.StackTrace);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取审批人的id
|
||||
/// </summary>
|
||||
/// <param name="stepType"></param>
|
||||
/// <returns></returns>
|
||||
private static List<int> GetAuditUserIds(int stepType, string nextId = null)
|
||||
{
|
||||
List<int> userIds = new List<int>();
|
||||
if (stepType == 0 || string.IsNullOrEmpty(nextId))
|
||||
{
|
||||
return userIds;
|
||||
}
|
||||
if (stepType == (int)AuditType.角色审批)
|
||||
{
|
||||
int roleId = nextId.GetInt();
|
||||
userIds = DBServerProvider.DbContext.Set<Sys_User>().Where(s => s.Role_Id == roleId).Take(50).Select(s => s.User_Id).ToList();
|
||||
}
|
||||
else if (stepType == (int)AuditType.部门审批)
|
||||
{
|
||||
Guid departmentId = nextId.GetGuid() ?? Guid.Empty;
|
||||
userIds = DBServerProvider.DbContext.Set<Sys_UserDepartment>().Where(s => s.DepartmentId == departmentId && s.Enable == 1).Take(50).Select(s => s.UserId).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
userIds.Add(nextId.GetInt());
|
||||
}
|
||||
return userIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
iMES.Core/WorkFlow/WorkFlowTableOptions.cs
Normal file
25
iMES.Core/WorkFlow/WorkFlowTableOptions.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using iMES.Entity.DomainModels;
|
||||
|
||||
namespace iMES.Core.WorkFlow
|
||||
{
|
||||
public class WorkFlowTableOptions:Sys_WorkFlow
|
||||
{
|
||||
public List<FilterOptions> FilterList { get; set; }
|
||||
}
|
||||
|
||||
public class FilterOptions : Sys_WorkFlowStep
|
||||
{
|
||||
public List<FieldFilter> FieldFilters { get; set; }
|
||||
|
||||
public object Expression { get; set; }
|
||||
|
||||
public string[] ParentIds { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user