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 WIDESEA_Core.DBManager; using WIDESEA_Core.EFDbContext; using WIDESEA_Core.Extensions; using WIDESEA_Core.Utilities; using WIDESEA_Entity.DomainModels; namespace WIDESEA_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 Dictionary<string, string[]> _formFields = 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> ///<param name="formFields">审批界é¢è¦æ˜¾ç¤ºå—段</param> /// <returns></returns> public WorkFlowContainer Use<T>(string name = null, Expression<Func<T, object>> filterFields = null, Expression<Func<T, object>> formFields = 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(); } if (formFields != null) { _formFields[type.Name] = formFields.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 (VOLContext contenxt = new VOLContext()) { 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 Type GetType(string tableName) { return _types.Where(c => c.Name == tableName).FirstOrDefault(); } public static string[] GetFilterFields(string tableName) { _filterFields.TryGetValue(tableName, out string[] fields); return fields; } public static string[] GetFormFields(string tableName) { _formFields.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(), AuditBack = item.AuditBack, AuditRefuse = item.AuditRefuse, AuditMethod = item.AuditMethod, SendMail = item.SendMail, WorkFlow_Id = item.WorkFlow_Id, WorkStepFlow_Id = item.WorkStepFlow_Id, StepType = item.StepType, StepValue = item.StepValue }); } 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); } } } }