Initial_commit_SecMPS_v2
This commit is contained in:
13
api_sqlsugar/VolPro.Core/WorkFlow/AuditBack.cs
Normal file
13
api_sqlsugar/VolPro.Core/WorkFlow/AuditBack.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace VolPro.Core.WorkFlow
|
||||
{
|
||||
public enum AuditBack
|
||||
{
|
||||
流程结束 = 0,
|
||||
返回上一节点 = 1,
|
||||
流程重新开始 = 2
|
||||
}
|
||||
}
|
||||
13
api_sqlsugar/VolPro.Core/WorkFlow/AuditRefuse.cs
Normal file
13
api_sqlsugar/VolPro.Core/WorkFlow/AuditRefuse.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace VolPro.Core.WorkFlow
|
||||
{
|
||||
public enum AuditRefuse
|
||||
{
|
||||
流程结束 = 0,
|
||||
返回上一节点 = 1,
|
||||
流程重新开始 = 2
|
||||
}
|
||||
}
|
||||
33
api_sqlsugar/VolPro.Core/WorkFlow/AuditStatus.cs
Normal file
33
api_sqlsugar/VolPro.Core/WorkFlow/AuditStatus.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace VolPro.Core.WorkFlow
|
||||
{
|
||||
public enum AuditStatus
|
||||
{
|
||||
待审核 = 0,
|
||||
审核通过 = 1,
|
||||
审核中 = 2,
|
||||
审核未通过 = 3,
|
||||
驳回 = 4,
|
||||
终止 = 5,
|
||||
反审 = 9,
|
||||
//预留审批流程草稿、待提交功能
|
||||
草稿 = 90,
|
||||
待提交 = 100,
|
||||
撤销 = 200
|
||||
}
|
||||
|
||||
public enum AuditType
|
||||
{
|
||||
用户审批 = 1,
|
||||
角色审批 = 2,
|
||||
部门审批 = 3,
|
||||
提交人上级部门审批 = 4,
|
||||
提交人上级角色审批 = 5,
|
||||
提交人自己 = 6,
|
||||
//根据提交人的部门,找到部门下所有用户的角色
|
||||
提交人部门对应角色 = 7
|
||||
}
|
||||
}
|
||||
14
api_sqlsugar/VolPro.Core/WorkFlow/FieldFilter.cs
Normal file
14
api_sqlsugar/VolPro.Core/WorkFlow/FieldFilter.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace VolPro.Core.WorkFlow
|
||||
{
|
||||
public class FieldFilter
|
||||
{
|
||||
public string Field { get; set; }
|
||||
public string Value { get; set; }
|
||||
|
||||
public string FilterType { get; set; }
|
||||
}
|
||||
}
|
||||
16
api_sqlsugar/VolPro.Core/WorkFlow/StepType.cs
Normal file
16
api_sqlsugar/VolPro.Core/WorkFlow/StepType.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace VolPro.Core.WorkFlow
|
||||
{
|
||||
public enum StepType
|
||||
{
|
||||
start,
|
||||
end,
|
||||
node,
|
||||
custom,
|
||||
//抄送
|
||||
cc
|
||||
}
|
||||
}
|
||||
442
api_sqlsugar/VolPro.Core/WorkFlow/WorkFlowContainer.cs
Normal file
442
api_sqlsugar/VolPro.Core/WorkFlow/WorkFlowContainer.cs
Normal file
@@ -0,0 +1,442 @@
|
||||
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 VolPro.Core.Configuration;
|
||||
using VolPro.Core.DBManager;
|
||||
using VolPro.Core.DbSqlSugar;
|
||||
using VolPro.Core.EFDbContext;
|
||||
using VolPro.Core.Extensions;
|
||||
using VolPro.Core.ManageUser;
|
||||
using VolPro.Core.Tenancy;
|
||||
using VolPro.Core.Utilities;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace VolPro.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<WorkFlowFormDetails> _formDetailFields = new List<WorkFlowFormDetails> { };
|
||||
private static List<Type> _types = new List<Type>();
|
||||
private static List<WorkFlowFormOptions> _flowFormOptions = new List<WorkFlowFormOptions>();
|
||||
private static Dictionary<string, string[]> _editFields = new Dictionary<string, string[]>();
|
||||
|
||||
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>
|
||||
///<param name="editFields">可以编辑的字段</param>
|
||||
/// <returns></returns>
|
||||
public WorkFlowContainer Use<T>(string name = null,
|
||||
Expression<Func<T, object>> filterFields = null,
|
||||
Expression<Func<T, object>> formFields = null,
|
||||
AuditStatus defaultAduitStatus = AuditStatus.待审核,
|
||||
Expression<Func<T, object>> editFields = null)
|
||||
{
|
||||
return _instance.Use<T, T>(name, filterFields, formFields, null, defaultAduitStatus, editFields);
|
||||
}
|
||||
|
||||
public WorkFlowContainer Use<T, Detail>(string name = null,
|
||||
Expression<Func<T, object>> filterFields = null,
|
||||
Expression<Func<T, object>> formFields = null,
|
||||
Expression<Func<Detail, object>> formDetailFields = null,
|
||||
AuditStatus defaultAduitStatus = AuditStatus.待审核,
|
||||
Expression<Func<T, object>> editFields = 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();
|
||||
}
|
||||
//可以编辑的字段
|
||||
if (editFields != null)
|
||||
{
|
||||
_editFields[type.Name] = editFields.GetExpressionToArray();
|
||||
}
|
||||
if (formDetailFields != null)
|
||||
{
|
||||
var dic = new WorkFlowFormDetails()
|
||||
{
|
||||
MainTable = type.Name,
|
||||
Type = typeof(Detail),
|
||||
FormFields = formDetailFields.GetExpressionToArray()
|
||||
};
|
||||
_formDetailFields.Add(dic);
|
||||
}
|
||||
_types.Add(type);
|
||||
_flowFormOptions.Add(new WorkFlowFormOptions()
|
||||
{
|
||||
TableName = type.Name,
|
||||
Type = type,
|
||||
DefaultAuditStatus = defaultAduitStatus
|
||||
});
|
||||
return _instance;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
List<Sys_WorkFlow> list = null;
|
||||
List<string> tables = _container.Select(s => s.Key).ToList();
|
||||
list = DbManger.SysDbContext.Set<Sys_WorkFlow>()
|
||||
.Includes(x => x.Sys_WorkFlowStep)
|
||||
.Where(c => tables.Contains(c.WorkTable)).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();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取明细表配置
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static List<WorkFlowFormDetails> GetDetail(Type mainType)
|
||||
{
|
||||
return _formDetailFields.Where(c => c.MainTable == mainType.Name).ToList();
|
||||
}
|
||||
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 string[] GetEditFields(string tableName)
|
||||
{
|
||||
_editFields.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>(string workFlowTableName = null)
|
||||
{
|
||||
return Exists(workFlowTableName ?? typeof(T).GetEntityTableName(false));
|
||||
}
|
||||
|
||||
public static bool Exists(string table)
|
||||
{
|
||||
return _container.ContainsKey(table);
|
||||
}
|
||||
|
||||
private WorkFlowContainer InitOptions(Type type, List<Sys_WorkFlow> list)
|
||||
{
|
||||
string tableName = type.GetEntityTableName(false);
|
||||
|
||||
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)
|
||||
{
|
||||
if (CheckTenancy())
|
||||
{
|
||||
return _workFlowTableOptions.Where(func).Where(x => x.DbServiceId == UserContext.CurrentServiceId);
|
||||
}
|
||||
return _workFlowTableOptions.Where(func);
|
||||
}
|
||||
public static WorkFlowTableOptions GetFlowOptions<T>(T entity, string tableName = null) where T : class
|
||||
{
|
||||
tableName = tableName ?? typeof(T).GetEntityTableName(false);
|
||||
if (!Exists(tableName) || !_workFlowTableOptions.Any(c => c.WorkTable == tableName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//2024.02.05增加租户区分
|
||||
if (CheckTenancy() && !_workFlowTableOptions.Any(c => c.WorkTable == tableName && c.DbServiceId == UserContext.CurrentServiceId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string key = typeof(T).GetKeyProperty().GetValue(entity).ToString();
|
||||
|
||||
var flowTable = DBServerProvider.DbContext.Set<Sys_WorkFlowTable>().Includes(c => c.Sys_WorkFlowTableStep)
|
||||
//2024.02.05增加租户区分
|
||||
.WhereIF(CheckTenancy(), c => c.DbServiceId == UserContext.CurrentServiceId)
|
||||
.Where(c => c.WorkTableKey == key && c.WorkTable == tableName && (c.AuditStatus != (int)AuditStatus.草稿 && c.AuditStatus != (int)AuditStatus.待提交))
|
||||
.OrderByDescending(x => x.CreateDate)
|
||||
.FirstOrDefault();
|
||||
|
||||
var entities = new List<T>() { entity };
|
||||
|
||||
//还未进入流程,找到满足流程的配置
|
||||
if (flowTable == null)
|
||||
{
|
||||
var serviceId = UserContext.CurrentServiceId;
|
||||
//优先判断满足条件的
|
||||
var filter = _workFlowTableOptions.Where(x => (CheckTenancy() ? x.DbServiceId == serviceId : true)
|
||||
&& x.WorkTable == tableName
|
||||
&& x.FilterList.Any(c => c.StepAttrType == StepType.start.ToString()
|
||||
&& c.FieldFilters.CheckFilter<T>(entities, c.Expression)))
|
||||
// && c.Expression != null && entities.Any(((Func<T, bool>)c.Expression))))
|
||||
.OrderByDescending(x => x.Weight)
|
||||
.FirstOrDefault();
|
||||
if (filter != null)
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
//没有找到满足条件的用无条件的流程
|
||||
|
||||
return _workFlowTableOptions.Where(x => (CheckTenancy() ? x.DbServiceId == serviceId : true)
|
||||
&& 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(false) == 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,
|
||||
Weight = workFlow.Weight,
|
||||
DbServiceId = workFlow.DbServiceId,
|
||||
TitleTemplate = workFlow.TitleTemplate,
|
||||
//2023.11.12增加默认状态
|
||||
DefaultAuditStatus = _flowFormOptions.Where(x => x.TableName == workFlow.WorkTable).Select(s => s.DefaultAuditStatus).FirstOrDefault(),
|
||||
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,
|
||||
ParentIds = new string[] { },
|
||||
SendMail = item.SendMail,
|
||||
WorkFlow_Id = item.WorkFlow_Id,
|
||||
WorkStepFlow_Id = item.WorkStepFlow_Id,
|
||||
StepType = item.StepType,
|
||||
StepValue = item.StepValue,
|
||||
FieldFilters = filters,
|
||||
StepEditForm = item.StepEditForm,
|
||||
AllowUpload = item.AllowUpload,
|
||||
AttachQty = item.AttachQty,
|
||||
AttachType = item.AttachType
|
||||
});
|
||||
}
|
||||
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>(string workTableName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(workTableName) && _container.TryGetValue(workTableName, out string name))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
Type type = typeof(T);
|
||||
if (_container.TryGetValue(type.Name, out 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);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CheckTenancy()
|
||||
{
|
||||
return (AppSetting.UseDynamicShareDB || AppSetting.TenancyField != null);
|
||||
}
|
||||
}
|
||||
public class WorkFlowFormOptions
|
||||
{
|
||||
public string TableName { get; set; }
|
||||
public Type Type { get; set; }
|
||||
public AuditStatus DefaultAuditStatus { get; set; }
|
||||
}
|
||||
public class WorkFlowFormDetails
|
||||
{
|
||||
public string MainTable { get; set; }
|
||||
public Type Type { get; set; }
|
||||
|
||||
public string[] FormFields { get; set; }
|
||||
}
|
||||
}
|
||||
118
api_sqlsugar/VolPro.Core/WorkFlow/WorkFlowFilter.cs
Normal file
118
api_sqlsugar/VolPro.Core/WorkFlow/WorkFlowFilter.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using VolPro.Core.Enums;
|
||||
using VolPro.Core.Extensions;
|
||||
|
||||
namespace VolPro.Core.WorkFlow
|
||||
{
|
||||
public static class WorkFlowFilter
|
||||
{
|
||||
public static bool CheckFilter<T>(this List<FieldFilter> filters, List<T> entities, object where) where T : class
|
||||
{
|
||||
try
|
||||
{
|
||||
if (where != null)
|
||||
{
|
||||
return entities.Any(((Func<T, bool>)where));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"流程表达式解析异常:" + ex.Message + ex.InnerException);
|
||||
if (filters != null)
|
||||
{
|
||||
//Nullable object must have a value.字段为null时
|
||||
Func<T, bool> expression = filters.Create<T>().Compile();
|
||||
return entities.AsQueryable().Any(expression);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static Expression<Func<T, bool>> Create<T>(this 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(false)}】不存在字段【{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.Like;
|
||||
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, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
expression = expression.And(filter.Field.CreateExpression<T>(filter.Value, type, true));
|
||||
}
|
||||
}
|
||||
if (orFilter != null)
|
||||
{
|
||||
expression = expression.And(orFilter);
|
||||
}
|
||||
return expression;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
285
api_sqlsugar/VolPro.Core/WorkFlow/WorkFlowGeneric.cs
Normal file
285
api_sqlsugar/VolPro.Core/WorkFlow/WorkFlowGeneric.cs
Normal file
@@ -0,0 +1,285 @@
|
||||
using Azure;
|
||||
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using VolPro.Core.DBManager;
|
||||
using VolPro.Core.DbSqlSugar;
|
||||
using VolPro.Core.Extensions;
|
||||
using VolPro.Core.Infrastructure;
|
||||
using VolPro.Core.ManageUser;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace VolPro.Core.WorkFlow
|
||||
{
|
||||
public static class WorkFlowGeneric
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取表当前审批流程数据
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="table"></param>
|
||||
/// <returns></returns>
|
||||
public static Sys_WorkFlowTable GetTableWorkflow<T>(this T entity, string table = null) where T : class, new()
|
||||
{
|
||||
table = table ?? typeof(T).GetEntityTableName();
|
||||
string key = typeof(T).GetKeyProperty().GetValue(entity).ToString();
|
||||
var data = DBServerProvider.DbContext.Set<Sys_WorkFlowTable>().Includes(x => x.Sys_WorkFlowTableStep)
|
||||
.Where(x => x.WorkTable == table && x.WorkTableKey == key)
|
||||
.WhereIF(WorkFlowContainer.CheckTenancy(), x => x.DbServiceId == UserContext.CurrentServiceId)
|
||||
.FirstOrDefault();
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取表当前正在审批的节点
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="table"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Sys_WorkFlowTableStep> GetTableCurrentFlowStep<T>(this T entity, string table=null) where T : class, new()
|
||||
{
|
||||
var data = entity.GetTableWorkflow(table);
|
||||
if (data == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var current = data.Sys_WorkFlowTableStep.Where(x => x.StepId == data.CurrentStepId).ToList();
|
||||
return current;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取表当前上一个审批节点
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="table"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Sys_WorkFlowTableStep> GetTablePreFlowStep<T>(this T entity, string table=null) where T : class, new()
|
||||
{
|
||||
var data = entity.GetTableWorkflow(table);
|
||||
if (data == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var current = data.Sys_WorkFlowTableStep.Where(x => x.StepId == data.CurrentStepId).FirstOrDefault();
|
||||
if (current == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return data.GetPreStep<Sys_WorkFlowTable>(current);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取表当前下一个审批节点
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="table"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Sys_WorkFlowTableStep> GetTableNextFlowStep<T>(this T entity, string table = null) where T : class, new()
|
||||
{
|
||||
var data = entity.GetTableWorkflow(table);
|
||||
if (data == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var current = data.Sys_WorkFlowTableStep.Where(x => x.StepId == data.CurrentStepId).FirstOrDefault();
|
||||
if (current == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return data.GetNextStep<Sys_WorkFlowTable>(current);
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取下一个节点
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="workflow"></param>
|
||||
/// <param name="current"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Sys_WorkFlowTableStep> GetNextStep<T>(this Sys_WorkFlowTable workflow, Sys_WorkFlowTableStep current) where T : Sys_WorkFlowTable
|
||||
{
|
||||
var list = workflow.Sys_WorkFlowTableStep.Where(x => x.StepId == current.NextStepId).ToList();
|
||||
//下一个节点抄送
|
||||
if (list.Exists(x => x.StepAttrType == StepType.cc.ToString()))
|
||||
{
|
||||
list = workflow.Sys_WorkFlowTableStep.Where(x => list.Any(c => c.NextStepId == x.StepId)).ToList();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取上一个节点
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="workflow"></param>
|
||||
/// <param name="current"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Sys_WorkFlowTableStep> GetPreStep<T>(this Sys_WorkFlowTable workflow, Sys_WorkFlowTableStep current) where T : Sys_WorkFlowTable
|
||||
{
|
||||
var list = workflow.Sys_WorkFlowTableStep.Where(x => x.NextStepId == current.StepId).ToList();
|
||||
//上一个节点抄送
|
||||
if (list.Exists(x => x.StepAttrType == StepType.cc.ToString()))
|
||||
{
|
||||
list = workflow.Sys_WorkFlowTableStep.Where(x => list.Any(c => c.StepId == x.NextStepId)).ToList();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
public static string GetNextStepId<T>(this Sys_WorkFlowTable workflow, Sys_WorkFlowTableStep current) where T : Sys_WorkFlowTable
|
||||
{
|
||||
return workflow.GetNextStep<Sys_WorkFlowTable>(current).Select(x => x.StepId).FirstOrDefault();
|
||||
}
|
||||
public static void CreateTitleTemplate<Entity>(Entity entity, Sys_WorkFlowTable flowTable, Sys_WorkFlow workflow)
|
||||
{
|
||||
if (string.IsNullOrEmpty(workflow.TitleTemplate))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var placeholders = new List<string>();
|
||||
var matches = Regex.Matches(workflow.TitleTemplate, @"\{#(\w+)\}");
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
string placeholder = match.Groups[0].Value;
|
||||
string key = match.Groups[1].Value;
|
||||
|
||||
placeholders.Add(key);
|
||||
}
|
||||
var tableOptions = DBServerProvider.DbContext.Set<Sys_TableColumn>()
|
||||
.Where(c => c.TableName == workflow.WorkTable && placeholders.Contains(c.ColumnName))
|
||||
.Select(s => new
|
||||
{
|
||||
s.ColumnName,
|
||||
s.ColumnCnName,
|
||||
s.DropNo,
|
||||
isDate = s.IsImage == 4,
|
||||
s.ColumnType,
|
||||
s.EditRowNo,
|
||||
s.EditType,
|
||||
s.IsNull
|
||||
}).ToList();
|
||||
|
||||
List<Sys_Dictionary> dictionaries = new List<Sys_Dictionary>();
|
||||
|
||||
var dicNos = tableOptions.Select(s => s.DropNo).ToList();
|
||||
if (dicNos.Count > 0)
|
||||
{
|
||||
dictionaries = DictionaryManager.GetDictionaries(dicNos, true).ToList();
|
||||
}
|
||||
|
||||
var properties = typeof(Entity).GetProperties().Where(x => placeholders.Contains(x.Name));
|
||||
|
||||
string titleTemplate = workflow.TitleTemplate;
|
||||
foreach (var property in properties)
|
||||
{
|
||||
string field = property.Name;
|
||||
string placeholder = $"{{#{field}}}";
|
||||
string value = property.GetValue(entity)?.ToString();
|
||||
|
||||
var option = tableOptions.Where(x => x.ColumnName == field).FirstOrDefault();
|
||||
if (option != null && !string.IsNullOrEmpty(value))
|
||||
{
|
||||
if (option.isDate)
|
||||
{
|
||||
value = value.GetDateTime().Value.ToString("yyyy-MM-dd");
|
||||
}
|
||||
else if (option.ColumnType == "DateTime")
|
||||
{
|
||||
value = value.GetDateTime().Value.ToString("yyyy-MM-dd HH:mm:sss");
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(option.DropNo))
|
||||
{
|
||||
string val = null;
|
||||
if (option.EditType == "selectList" || option.EditType == "checkbox" || option.EditType == "treeSelect")
|
||||
{
|
||||
string[] arr = value.Split(",");
|
||||
arr = dictionaries.Where(c => c.DicNo == option.DropNo).FirstOrDefault()
|
||||
?.Sys_DictionaryList
|
||||
?.Where(c => arr.Contains(c.DicValue))?.Select(s => s.DicName)
|
||||
.ToArray();
|
||||
val = string.Join(",", arr);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = dictionaries.Where(c => c.DicNo == option.DropNo).FirstOrDefault()
|
||||
?.Sys_DictionaryList
|
||||
?.Where(c => c.DicValue == value)?.Select(s => s.DicName)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
if (!string.IsNullOrEmpty(val))
|
||||
{
|
||||
value = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
titleTemplate = titleTemplate.Replace(placeholder, value ?? "");
|
||||
}
|
||||
flowTable.TitleTemplate = titleTemplate;
|
||||
}
|
||||
|
||||
public static List<string> AuditFields = new List<string>() { "auditid", "auditstatus", "auditor", "auditdate", "auditreason" };
|
||||
|
||||
public static List<string> UpdateAuditInfo<T>(T entity, int auditStatus, string auditReason)
|
||||
{
|
||||
List<string> auditFields = new List<string>();
|
||||
var userInfo = UserContext.Current.UserInfo;
|
||||
var properties = typeof(T).GetProperties();
|
||||
foreach (var item in properties)
|
||||
{
|
||||
bool isAudit = true;
|
||||
switch (item.Name.ToLower())
|
||||
{
|
||||
case "auditid":
|
||||
item.SetValue(entity, userInfo.User_Id.ChangeType(item.PropertyType));
|
||||
break;
|
||||
case "auditstatus":
|
||||
item.SetValue(entity, auditStatus);
|
||||
break;
|
||||
case "auditor":
|
||||
item.SetValue(entity, userInfo.UserTrueName);
|
||||
break;
|
||||
case "auditdate":
|
||||
item.SetValue(entity, DateTime.Now);
|
||||
break;
|
||||
case "auditreason":
|
||||
item.SetValue(entity, auditReason);
|
||||
break;
|
||||
default:
|
||||
isAudit = false;
|
||||
break;
|
||||
}
|
||||
if (isAudit)
|
||||
{
|
||||
auditFields.Add(item.Name);
|
||||
}
|
||||
}
|
||||
return auditFields;
|
||||
}
|
||||
/// <summary>
|
||||
/// 判断数据是否在审批中
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="auditProperty"></param>
|
||||
/// <returns></returns>
|
||||
public static bool CheckAudting<T>(List<T> list, PropertyInfo auditProperty)
|
||||
{
|
||||
foreach (var entity in list)
|
||||
{
|
||||
|
||||
int value = auditProperty.GetValue(entity).GetInt();
|
||||
if (value != (int)AuditStatus.审核中 && value != (int)AuditStatus.待审核)
|
||||
{
|
||||
return false;
|
||||
// return Response.Error($"只能操作审批中的数据".Translator());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
1891
api_sqlsugar/VolPro.Core/WorkFlow/WorkFlowManager.cs
Normal file
1891
api_sqlsugar/VolPro.Core/WorkFlow/WorkFlowManager.cs
Normal file
File diff suppressed because it is too large
Load Diff
26
api_sqlsugar/VolPro.Core/WorkFlow/WorkFlowTableOptions.cs
Normal file
26
api_sqlsugar/VolPro.Core/WorkFlow/WorkFlowTableOptions.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace VolPro.Core.WorkFlow
|
||||
{
|
||||
public class WorkFlowTableOptions:Sys_WorkFlow
|
||||
{
|
||||
public AuditStatus DefaultAuditStatus { get; set; }
|
||||
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