添加项目文件。

This commit is contained in:
zel
2025-03-05 19:42:01 +08:00
parent 659f1a2ad9
commit 47dcdeb55d
582 changed files with 242004 additions and 0 deletions

View File

@@ -0,0 +1,325 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using WaterCloud.Code;
using WaterCloud.DataBase;
using WaterCloud.Domain.SystemManage;
using WaterCloud.Domain.SystemOrganize;
namespace WaterCloud.Service
{
public class BaseService<T> : RepositoryBase<T> where T : class, new()
{
// 用户信息
public OperatorModel currentuser;
// 用于当前表操作
protected RepositoryBase<T> repository;
// 用于其他表操作
protected ISqlSugarClient _context;
public BaseService(ISqlSugarClient context) : base(context)
{
currentuser = OperatorProvider.Provider.GetCurrent();
_context = context;
repository = this;
if (currentuser == null)
{
currentuser = new OperatorModel();
}
else
{
var entityType = typeof(T);
if (entityType.IsDefined(typeof(TenantAttribute), false))
{
var tenantAttribute = entityType.GetCustomAttribute<TenantAttribute>(false)!;
repository.ChangeEntityDb(tenantAttribute.configId);
}
else if (_context.AsTenant().IsAnyConnection(currentuser.DbNumber))
{
repository.ChangeEntityDb(currentuser.DbNumber);
}
else
{
var dblist = DBInitialize.GetConnectionConfigs(false);
_context.AsTenant().AddConnection(dblist.FirstOrDefault(a => a.ConfigId.ToString() == currentuser.DbNumber));
repository.ChangeEntityDb(currentuser.DbNumber);
repository.Db.DefaultConfig();
}
}
}
/// <summary>
/// 获取当前登录用户的数据访问权限(单表)
/// </summary>
/// <param name=""parameterName>linq表达式参数的名称如u=>u.name中的"u"</param>
/// <param name=""moduleName>菜单名称</param>
/// <param name=""query>查询</param>
/// <returns></returns>
protected ISugarQueryable<T> GetDataPrivilege(string parametername, string moduleName = "", ISugarQueryable<T> query = null)
{
moduleName = string.IsNullOrEmpty(moduleName) ? ReflectionHelper.GetModuleName() : moduleName;
if (query == null)
{
query = repository.IQueryable();
}
if (!CheckDataPrivilege(moduleName))
{
return GetFieldsFilterDataNew(parametername, query, moduleName);
}
var rule = repository.Db.Queryable<DataPrivilegeRuleEntity>().WithCache().First(u => u.F_ModuleCode == moduleName && u.F_EnabledMark == true && u.F_DeleteMark == false);
if (rule.F_PrivilegeRules.Contains(Define.DATAPRIVILEGE_LOGINUSER) ||
rule.F_PrivilegeRules.Contains(Define.DATAPRIVILEGE_LOGINROLE) ||
rule.F_PrivilegeRules.Contains(Define.DATAPRIVILEGE_LOGINORG))
{
//即把{loginUser} =='xxxxxxx'换为 loginUser.User.Id =='xxxxxxx'从而把当前登录的用户名与当时设计规则时选定的用户id对比
rule.F_PrivilegeRules = rule.F_PrivilegeRules.Replace(Define.DATAPRIVILEGE_LOGINUSER, currentuser.UserId);
var roles = currentuser.RoleId;
//var roles = loginUser.Roles.Select(u => u.Id).ToList();//多角色
//roles.Sort();
rule.F_PrivilegeRules = rule.F_PrivilegeRules.Replace(Define.DATAPRIVILEGE_LOGINROLE,
roles);
var orgs = currentuser.OrganizeId;
//var orgs = loginUser.Orgs.Select(u => u.Id).ToList();//多部门
//orgs.Sort();
rule.F_PrivilegeRules = rule.F_PrivilegeRules.Replace(Define.DATAPRIVILEGE_LOGINORG,
orgs);
}
query = query.GenerateFilter(parametername,
JsonHelper.ToObject<List<FilterList>>(rule.F_PrivilegeRules));
return GetFieldsFilterDataNew(parametername, query, moduleName);
}
/// <summary>
/// 获取当前登录用户的数据访问权限(复杂查询)
/// </summary>
/// <param name=""parameterName>linq表达式参数的名称如u=>u.name中的"u"</param>
/// <param name=""moduleName>菜单名称</param>
/// <param name=""query>查询</param>
/// <returns></returns>
protected ISugarQueryable<TEntity> GetDataPrivilege<TEntity>(string parametername, string moduleName = "", ISugarQueryable<TEntity> query = null)
{
moduleName = string.IsNullOrEmpty(moduleName) ? ReflectionHelper.GetModuleName() : moduleName;
if (!CheckDataPrivilege(moduleName))
{
return GetFieldsFilterDataNew(parametername, query, moduleName);
}
var rule = repository.Db.Queryable<DataPrivilegeRuleEntity>().WithCache().First(u => u.F_ModuleCode == moduleName && u.F_EnabledMark == true && u.F_DeleteMark == false);
if (rule.F_PrivilegeRules.Contains(Define.DATAPRIVILEGE_LOGINUSER) ||
rule.F_PrivilegeRules.Contains(Define.DATAPRIVILEGE_LOGINROLE) ||
rule.F_PrivilegeRules.Contains(Define.DATAPRIVILEGE_LOGINORG))
{
//即把{loginUser} =='xxxxxxx'换为 loginUser.User.Id =='xxxxxxx'从而把当前登录的用户名与当时设计规则时选定的用户id对比
rule.F_PrivilegeRules = rule.F_PrivilegeRules.Replace(Define.DATAPRIVILEGE_LOGINUSER, currentuser.UserId);
var roles = currentuser.RoleId;
rule.F_PrivilegeRules = rule.F_PrivilegeRules.Replace(Define.DATAPRIVILEGE_LOGINROLE,
roles);
var orgs = currentuser.OrganizeId;
rule.F_PrivilegeRules = rule.F_PrivilegeRules.Replace(Define.DATAPRIVILEGE_LOGINORG,
orgs);
}
query = query.GenerateFilter(parametername,
JsonHelper.ToObject<List<FilterList>>(rule.F_PrivilegeRules));
return GetFieldsFilterDataNew(parametername, query, moduleName);
}
/// <summary>
/// 获取当前登录用户是否需要数据控制
/// </summary>
/// <param name=""moduleName>菜单名称</param>
/// <returns></returns>
protected bool CheckDataPrivilege(string moduleName = "")
{
moduleName = string.IsNullOrEmpty(moduleName) ? ReflectionHelper.GetModuleName() : moduleName;
if (currentuser.IsAdmin) return false; //超级管理员特权
var rule = repository.Db.Queryable<DataPrivilegeRuleEntity>().WithCache().First(u => u.F_ModuleCode == moduleName && u.F_EnabledMark == true && u.F_DeleteMark == false);
////系统菜单也不需要数据权限 跟字段重合取消这样处理
//var module = UnitWork.FindEntity<ModuleEntity>(u => u.F_EnCode == moduleName).GetAwaiter().GetResult();
if (rule == null)
{
return false; //没有设置数据规则,那么视为该资源允许被任何主体查看
}
//if (rule == null|| module.F_IsPublic==true)
//{
// return false; //没有设置数据规则,那么视为该资源允许被任何主体查看
//}
return true;
}
/// <summary>
/// soul数据反向模板化
/// </summary>
/// <param name=""dic>集合</param>
/// <param name=""pagination>分页</param>
/// <returns></returns>
protected SoulPage<TEntity> ChangeSoulData<TEntity>(Dictionary<string, Dictionary<string, string>> dic, SoulPage<TEntity> pagination)
{
List<FilterSo> filterSos = pagination.getFilterSos();
filterSos = FormatData(dic, filterSos);
pagination.filterSos = filterSos.ToJson();
return pagination;
}
protected List<FilterSo> FormatData(Dictionary<string, Dictionary<string, string>> dic, List<FilterSo> filterSos)
{
foreach (var item in filterSos)
{
if (item.mode == "condition" && dic.ContainsKey(item.field) && dic[item.field].Values.Contains(item.value))
{
item.value = dic[item.field].FirstOrDefault(a => a.Value == item.value).Key;
}
if (item.children != null && item.children.Count > 0)
{
item.children = FormatData(dic, item.children);
}
}
return filterSos;
}
/// <summary>
/// 字段权限处理
/// </summary>
///<param name=""list>数据列表</param>
/// <param name=""moduleName>菜单名称</param>
/// <returns></returns>
protected List<TEntity> GetFieldsFilterData<TEntity>(List<TEntity> list, string moduleName = "")
{
moduleName = string.IsNullOrEmpty(moduleName) ? ReflectionHelper.GetModuleName() : moduleName;
//管理员跳过
if (currentuser.IsAdmin)
{
return list;
}
//系统菜单跳过
var module = repository.Db.Queryable<ModuleEntity>().First(u => u.F_EnCode == moduleName);
//判断是否需要字段权限
if (module == null || module.F_IsFields == false)
{
return list;
}
//空list直接返回
if (list.Count == 0)
{
return list;
}
var rolelist = currentuser.RoleId.Split(',');
var rule = repository.Db.Queryable<RoleAuthorizeEntity>().Where(u => rolelist.Contains(u.F_ObjectId) && u.F_ItemType == 3).Select(a => a.F_ItemId).Distinct().ToList();
var fieldsList = repository.Db.Queryable<ModuleFieldsEntity>().Where(u => (rule.Contains(u.F_Id) || u.F_IsPublic == true) && u.F_EnabledMark == true && u.F_ModuleId == module.F_Id).Select(u => u.F_EnCode).ToList();
//反射获取主键
PropertyInfo pkProp = typeof(TEntity).GetProperties().Where(p => p.GetCustomAttributes(typeof(SugarColumn), false).Length > 0).First();
var idName = "F_Id";
if (pkProp != null)
{
idName = pkProp.Name;
}
fieldsList.Add(idName);
fieldsList = fieldsList.Distinct().ToList();
return DataTableHelper.ListFilter(list, fieldsList);
}
/// <summary>
/// 字段权限处理
/// </summary>
///<param name=""entity>数据</param>
/// <param name=""moduleName>菜单名称</param>
/// <returns></returns>
protected TEntity GetFieldsFilterData<TEntity>(TEntity entity, string moduleName = "")
{
moduleName = string.IsNullOrEmpty(moduleName) ? ReflectionHelper.GetModuleName() : moduleName;
//管理员跳过
if (currentuser.IsAdmin)
{
return entity;
}
//系统菜单跳过
var module = repository.Db.Queryable<ModuleEntity>().First(u => u.F_EnCode == moduleName);
//判断是否需要字段权限
if (module == null || module.F_IsFields == false)
{
return entity;
}
//空对象直接返回
if (entity == null)
{
return entity;
}
var rolelist = currentuser.RoleId.Split(',');
var rule = repository.Db.Queryable<RoleAuthorizeEntity>().Where(u => rolelist.Contains(u.F_ObjectId) && u.F_ItemType == 3).Select(a => a.F_ItemId).Distinct().ToList();
var fieldsList = repository.Db.Queryable<ModuleFieldsEntity>().Where(u => (rule.Contains(u.F_Id) || u.F_IsPublic == true) && u.F_EnabledMark == true && u.F_ModuleId == module.F_Id).Select(u => u.F_EnCode).ToList();
//反射获取主键
PropertyInfo pkProp = typeof(TEntity).GetProperties().Where(p => p.GetCustomAttributes(typeof(SugarColumn), false).Length > 0).First();
var idName = "F_Id";
if (pkProp != null)
{
idName = pkProp.Name;
}
fieldsList.Add(idName);
fieldsList = fieldsList.Distinct().ToList();
List<TEntity> list = new List<TEntity>();
list.Add(entity);
return DataTableHelper.ListFilter(list, fieldsList)[0];
}
/// <summary>
/// 字段权限处理
/// </summary>
///<param name=""query>数据列表</param>
/// <param name=""moduleName>菜单名称</param>
/// <returns></returns>
protected ISugarQueryable<TEntity> GetFieldsFilterDataNew<TEntity>(string parametername, ISugarQueryable<TEntity> query, string moduleName = "")
{
moduleName = string.IsNullOrEmpty(moduleName) ? ReflectionHelper.GetModuleName() : moduleName;
//管理员跳过
if (currentuser.IsAdmin)
{
return query;
}
//系统菜单跳过
var module = repository.Db.Queryable<ModuleEntity>().First(u => u.F_EnCode == moduleName);
//判断是否需要字段权限
if (module == null || module.F_IsFields == false)
{
return query;
}
var rolelist = currentuser.RoleId.Split(',');
var rule = repository.Db.Queryable<RoleAuthorizeEntity>().Where(u => rolelist.Contains(u.F_ObjectId) && u.F_ItemType == 3).Select(a => a.F_ItemId).Distinct().ToList();
var fieldsList = repository.Db.Queryable<ModuleFieldsEntity>().Where(u => (rule.Contains(u.F_Id) || u.F_IsPublic == true) && u.F_EnabledMark == true && u.F_ModuleId == module.F_Id).Select(u => u.F_EnCode).ToList();
//反射获取主键
PropertyInfo pkProp = typeof(TEntity).GetProperties().Where(p => p.GetCustomAttributes(typeof(SugarColumn), false).Length > 0).First();
var idName = "F_Id";
if (pkProp != null)
{
idName = pkProp.Name;
}
fieldsList.Add(idName);
fieldsList = fieldsList.Distinct().ToList();
//可以构建lambda
var parameter = Expression.Parameter(typeof(TEntity), parametername);
var bindings = fieldsList
.Select(name => name.Trim())
.Select(name => Expression.Bind(
typeof(TEntity).GetProperty(name),
Expression.Property(parameter, name)
));
var newT = Expression.MemberInit(Expression.New(typeof(TEntity)), bindings);
var lambda = Expression.Lambda<Func<TEntity, TEntity>>(newT, parameter);
query = query.Select(lambda);
//chloe扩展方法
//List<string> ignoreList = new List<string>();
// foreach (var item in typeof(TEntity).GetProperties())
// {
// if (!fieldsList.Contains(item.Name))
// {
// ignoreList.Add(item.Name);
// }
// }
// query = query.Ignore(ignoreList.ToArray());
return query;
}
}
}

View File

@@ -0,0 +1,74 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using WaterCloud.Code;
using WaterCloud.Code.Model;
using WaterCloud.DataBase;
using WaterCloud.Domain.SystemOrganize;
namespace WaterCloud.Service
{
/// <summary>
/// 初始数据库操作类
/// </summary>
public class DBInitialize
{
private static string cacheKey = GlobalContext.SystemConfig.ProjectPrefix + "_dblist";// 数据库键
/// <summary>
/// 获取注册数据库list
/// </summary>
/// <param name="readDb">重置数据库list</param>
/// <returns></returns>
public static List<ConnectionConfig> GetConnectionConfigs(bool readDb = false)
{
List<ConnectionConfig> list = CacheHelper.Get<List<ConnectionConfig>>(cacheKey);
if (list == null || !list.Any() || readDb)
{
list = new List<ConnectionConfig>();
var data = GlobalContext.SystemConfig;
var defaultConfig = DBContexHelper.Contex(data.DBConnectionString, data.DBProvider);
defaultConfig.ConfigId = "0";
list.Add(defaultConfig);
try
{
//租户数据库
if (data.SqlMode == Define.SQL_TENANT)
{
using (var context = new SqlSugarClient(defaultConfig))
{
var sqls = context.Queryable<SystemSetEntity>().ToList();
foreach (var item in sqls.Where(a => a.F_EnabledMark == true && a.F_EndTime > DateTime.Now.Date && a.F_DbNumber != "0"))
{
var config = DBContexHelper.Contex(item.F_DbString, item.F_DBProvider);
config.ConfigId = item.F_DbNumber;
list.Add(config);
}
}
}
if (data.SqlConfig == null)
data.SqlConfig = new List<DBConfig>();
//扩展数据库
foreach (var item in data.SqlConfig)
{
var config = DBContexHelper.Contex(item.DBConnectionString, item.DBProvider);
config.ConfigId = item.DBNumber;
if (list.Any(a => a.ConfigId == config.ConfigId))
{
throw new Exception($"数据库编号重复,请检查{config.ConfigId}");
}
list.Add(config);
}
}
catch (Exception ex)
{
LogHelper.WriteWithTime(ex);
}
CacheHelper.SetBySecond(cacheKey, list);
}
return list;
}
}
}

View File

@@ -0,0 +1,64 @@
using SqlSugar;
using System.Collections.Generic;
using System.Linq;
using WaterCloud.Code;
using WaterCloud.DataBase;
using WaterCloud.Domain.SystemSecurity;
namespace WaterCloud.Service
{
public class DatabaseTableService : IDenpendency
{
public RepositoryBase<LogEntity> repository;
private static string cacheKey = GlobalContext.SystemConfig.ProjectPrefix + "_dblist";// 数据库键
public DatabaseTableService(ISqlSugarClient context)
{
repository = new RepositoryBase<LogEntity>(context);
}
public List<DbTableInfo> GetTableList(string tableName, string dbNumber)
{
if (string.IsNullOrEmpty(dbNumber))
{
dbNumber = GlobalContext.SystemConfig.MainDbNumber;
}
repository.ChangeEntityDb(dbNumber);
var data = repository.Db.DbMaintenance.GetTableInfoList(false);
if (!string.IsNullOrEmpty(tableName))
data = data.Where(a => a.Name.Contains(tableName)).ToList();
return data;
}
public List<DbTableInfo> GetTablePageList(string tableName, string dbNumber, Pagination pagination)
{
if (string.IsNullOrEmpty(dbNumber))
{
dbNumber = GlobalContext.SystemConfig.MainDbNumber;
}
repository.ChangeEntityDb(dbNumber);
var data = repository.Db.DbMaintenance.GetTableInfoList(false);
if (!string.IsNullOrEmpty(tableName))
data = data.Where(a => a.Name.Contains(tableName)).ToList();
pagination.records = data.Count();
return data.Skip((pagination.page - 1) * pagination.rows).Take(pagination.rows).ToList();
}
public List<dynamic> GetDbNumberListJson()
{
var data = DBInitialize.GetConnectionConfigs();
return data.Select(a => a.ConfigId).ToList();
}
public List<DbColumnInfo> GetTableFieldList(string tableName, string dbNumber)
{
if (string.IsNullOrEmpty(dbNumber))
{
dbNumber = GlobalContext.SystemConfig.MainDbNumber;
}
repository.ChangeEntityDb(dbNumber);
var data = repository.Db.DbMaintenance.GetColumnInfosByTableName(tableName, false);
return data;
}
}
}

View File

@@ -0,0 +1,11 @@
using System.Threading.Tasks;
namespace WaterCloud.Service
{
public interface ICustomerForm
{
Task Add(string flowInstanceId, string frmData);
Task Edit(string flowInstanceId, string frmData);
}
}

View File

@@ -0,0 +1,5 @@
namespace WaterCloud.Service
{
public interface IDenpendency
{ }
}

View File

@@ -0,0 +1,431 @@
using Microsoft.Extensions.DependencyInjection;
using MySqlConnector;
using Quartz;
using Quartz.Impl;
using Quartz.Impl.AdoJobStore.Common;
using Quartz.Spi;
using RabbitMQ.Client;
using SqlSugar;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Linq;
using System.Reflection;
using WaterCloud.Code;
using WaterCloud.DataBase;
using WaterCloud.Domain.SystemOrganize;
using WaterCloud.Service.AutoJob;
using WaterCloud.Service.Event;
namespace WaterCloud.Service
{
/// <summary>
/// 服务设置
/// </summary>
public static class ServiceSetup
{
/// <summary>
/// SqlSugar设置
/// </summary>
/// <param name="services"></param>
public static IServiceCollection AddSqlSugar(this IServiceCollection services)
{
var configList = DBInitialize.GetConnectionConfigs(true);
SqlSugarScope sqlSugarScope = new SqlSugarScope(configList,
//全局上下文生效
db =>
{
foreach (var item in configList)
{
db.GetConnection(item.ConfigId).DefaultConfig();
}
});
//初始化数据库
foreach (var item in configList)
{
var db = sqlSugarScope.GetConnection(item.ConfigId);
if (GlobalContext.SystemConfig.IsInitDb)
{
InitDb(item, db);
}
if (GlobalContext.SystemConfig.IsSeedData)
{
InitSeedData(item, db);
}
}
//注入数据库连接
// 注册 SqlSugar
services.AddSingleton<ISqlSugarClient>(sqlSugarScope);
return services;
}
/// <summary>
/// sqlsugar配置
/// </summary>
/// <param name="db"></param>
public static void DefaultConfig(this ISqlSugarClient db)
{
db.Ado.CommandTimeOut = GlobalContext.SystemConfig.DBCommandTimeout;
db.CurrentConnectionConfig.ConfigureExternalServices = new ConfigureExternalServices()
{
DataInfoCacheService = new SqlSugarCache(), //配置我们创建的缓存类
EntityNameService = (type, entity) =>
{
var attributes = type.GetCustomAttributes(true);
if (attributes.Any(it => it is TableAttribute))
{
entity.DbTableName = (attributes.First(it => it is TableAttribute) as TableAttribute).Name;
}
},
EntityService = (property, column) =>
{
var attributes = property.GetCustomAttributes(true);//get all attributes
if (attributes.Any(it => it is KeyAttribute))// by attribute set primarykey
{
column.IsPrimarykey = true; //有哪些特性可以看 1.2 特性明细
}
if (attributes.Any(it => it is ColumnAttribute))
{
column.DbColumnName = (attributes.First(it => it is ColumnAttribute) as ColumnAttribute).Name;
}
if (attributes.Any(it => it is SugarColumn) && column.DataType == "longtext" && db.CurrentConnectionConfig.DbType == SqlSugar.DbType.SqlServer)
{
column.DataType = "nvarchar(4000)";
}
}
};
db.Aop.OnLogExecuted = (sql, pars) => //SQL执行完
{
if (sql.StartsWith("SELECT"))
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[SELECT]-" + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
}
if (sql.StartsWith("INSERT"))
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("[INSERT]-" + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
}
if (sql.StartsWith("UPDATE"))
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("[UPDATE]-" + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
}
if (sql.StartsWith("DELETE"))
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[DELETE]-" + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
}
Console.WriteLine($"执行库{db.CurrentConnectionConfig.ConfigId}");
Console.WriteLine("NeedTime-" + db.Ado.SqlExecutionTime.ToString());
//App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
Console.WriteLine("Content:" + UtilMethods.GetSqlString(db.CurrentConnectionConfig.DbType, sql, pars));
Console.WriteLine("---------------------------------");
Console.WriteLine("");
};
}
private static void InitSeedData(ConnectionConfig config, SqlSugarProvider db)
{
var entityTypes = GlobalContext.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false));
if (!entityTypes.Any()) return;//没有就退出
// 获取所有种子配置-初始化数据
var seedDataTypes = GlobalContext.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
&& u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))));
if (!seedDataTypes.Any()) return;
foreach (var seedType in seedDataTypes)//遍历种子类
{
//使用与指定参数匹配程度最高的构造函数来创建指定类型的实例。
var instance = Activator.CreateInstance(seedType);
//获取SeedData方法
var hasDataMethod = seedType.GetMethod("SeedData");
//判断是否有种子数据
var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>();
if (seedData == null) continue;//没有种子数据就下一个
var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();//获取实体类型
var tenantAtt = entityType.GetCustomAttribute<TenantAttribute>();//获取sqlsugar租户特性
if (tenantAtt != null && tenantAtt.configId.ToString() != config.ConfigId.ToString()) continue;//如果不是当前租户的就下一个
var seedDataTable = seedData.ToList().ToDataTable();//获取种子数据
seedDataTable.TableName = db.EntityMaintenance.GetEntityInfo(entityType).DbTableName;//获取表名
if (seedDataTable.Columns.Contains("F_Id"))//判断种子数据是否有主键
{
var storage = db.Storageable(seedDataTable).WhereColumns("F_Id").ToStorage();
//codefirst暂时全部新增,根据主键更新,用户表暂不更新
storage.AsInsertable.ExecuteCommand();
var ignoreUpdate = hasDataMethod.GetCustomAttribute<IgnoreSeedDataUpdateAttribute>();//读取忽略更新特性
if (ignoreUpdate == null)
storage.AsUpdateable.ExecuteCommand();//只有没有忽略更新的特性才执行更新
}
else // 没有主键或者不是预定义的主键(有重复的可能)
{
//全量插入
var storage = db.Storageable(seedDataTable).ToStorage();
storage.AsInsertable.ExecuteCommand();
}
}
}
/// <summary>
/// 初始化数据库表结构
/// </summary>
/// <param name="config">数据库配置</param>
private static void InitDb(ConnectionConfig config, SqlSugarProvider db)
{
try
{
db.DbMaintenance.CreateDatabase();//创建数据库
}
catch (Exception ex)
{
Console.WriteLine($"创建数据库失败,开始尝试操作表! ex:{ex.Message}");
}
var entityTypes = GlobalContext.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false));
if (!entityTypes.Any()) return;//没有就退出
foreach (var entityType in entityTypes)
{
var tenantAtt = entityType.GetCustomAttribute<TenantAttribute>();//获取Sqlsugar多租户特性
var ignoreInit = entityType.GetCustomAttribute<IgnoreInitTableAttribute>();//获取忽略初始化特性
if (ignoreInit != null) continue;//如果有忽略初始化特性
if (tenantAtt != null && tenantAtt.configId.ToString() != config.ConfigId.ToString()) continue;//如果特性存在并且租户ID不是当前数据库ID
var splitTable = entityType.GetCustomAttribute<SplitTableAttribute>();//获取自动分表特性
if (splitTable == null)//如果特性是空
{
db.CodeFirst.SetStringDefaultLength(50).InitTables(entityType);//普通创建
}
else
db.CodeFirst.SetStringDefaultLength(50).SplitTables().InitTables(entityType);//自动分表创建
}
}
/// <summary>
/// 判断类型是否实现某个泛型
/// </summary>
/// <param name="type">类型</param>
/// <param name="generic">泛型类型</param>
/// <returns>bool</returns>
public static bool HasImplementedRawGeneric(this System.Type type, System.Type generic)
{
// 检查接口类型
var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
if (isTheRawGenericType) return true;
// 检查类型
while (type != null && type != typeof(object))
{
isTheRawGenericType = IsTheRawGenericType(type);
if (isTheRawGenericType) return true;
type = type.BaseType;
}
return false;
// 判断逻辑
bool IsTheRawGenericType(System.Type type) => generic == (type.IsGenericType ? type.GetGenericTypeDefinition() : type);
}
/// <summary>
/// List转DataTable
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
public static DataTable ToDataTable<T>(this List<T> list)
{
DataTable result = new();
if (list.Count > 0)
{
// result.TableName = list[0].GetType().Name; // 表名赋值
PropertyInfo[] propertys = list[0].GetType().GetProperties();
foreach (PropertyInfo pi in propertys)
{
System.Type colType = pi.PropertyType;
if (colType.IsGenericType && colType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
colType = colType.GetGenericArguments()[0];
}
if (IsIgnoreColumn(pi))
continue;
if (IsJsonColumn(pi))//如果是json特性就是sting类型
colType = typeof(string);
result.Columns.Add(pi.Name, colType);
}
for (int i = 0; i < list.Count; i++)
{
ArrayList tempList = new();
foreach (PropertyInfo pi in propertys)
{
if (IsIgnoreColumn(pi))
continue;
object obj = pi.GetValue(list[i], null);
if (IsJsonColumn(pi))//如果是json特性就是转化为json格式
obj = obj?.ToJson();//如果json字符串是空就传null
tempList.Add(obj);
}
object[] array = tempList.ToArray();
result.LoadDataRow(array, true);
}
}
return result;
}
/// <summary>
/// 排除SqlSugar忽略的列
/// </summary>
/// <param name="pi"></param>
/// <returns></returns>
private static bool IsIgnoreColumn(PropertyInfo pi)
{
var sc = pi.GetCustomAttributes<SugarColumn>(false).FirstOrDefault(u => u.IsIgnore == true);
return sc != null;
}
private static bool IsJsonColumn(PropertyInfo pi)
{
var sc = pi.GetCustomAttributes<SugarColumn>(false).FirstOrDefault(u => u.IsJson == true);
return sc != null;
}
/// <summary>
/// Quartz设置
/// </summary>
/// <param name="services"></param>
public static IServiceCollection AddQuartz(this IServiceCollection services)
{
services.AddSingleton<JobExecute>();
//注册ISchedulerFactory的实例。
services.AddSingleton<IJobFactory, IOCJobFactory>();
if (GlobalContext.SystemConfig.IsCluster != true)
{
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
}
else
{
//开启集群模式,具体数据库从官方github下载
//https://github.com/quartznet/quartznet/blob/main/database/tables/
services.AddSingleton<ISchedulerFactory>(u =>
{
//当前是mysql的例子其他数据库做相应更改
DbProvider.RegisterDbMetadata("mysql-custom", new DbMetadata()
{
AssemblyName = typeof(MySqlConnection).Assembly.GetName().Name,
ConnectionType = typeof(MySqlConnection),
CommandType = typeof(MySqlCommand),
ParameterType = typeof(MySqlParameter),
ParameterDbType = typeof(System.Data.DbType),
ParameterDbTypePropertyName = "DbType",
ParameterNamePrefix = "@",
ExceptionType = typeof(MySqlException),
BindByName = true
});
var properties = new NameValueCollection
{
["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz", // 配置Quartz以使用JobStoreTx
//["quartz.jobStore.useProperties"] = "true", // 配置AdoJobStore以将字符串用作JobDataMap值
["quartz.jobStore.dataSource"] = "myDS", // 配置数据源名称
["quartz.jobStore.tablePrefix"] = "QRTZ_", // quartz所使用的表在当前数据库中的表前缀
["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.MySQLDelegate, Quartz", // 配置AdoJobStore使用的DriverDelegate
["quartz.dataSource.myDS.connectionString"] = GlobalContext.SystemConfig.DBConnectionString, // 配置数据库连接字符串,自己处理好连接字符串,我这里就直接这么写了
["quartz.dataSource.myDS.provider"] = "mysql-custom", // 配置数据库提供程序(这里是自定义的,定义的代码在上面)
["quartz.jobStore.lockHandler.type"] = "Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz",
["quartz.serializer.type"] = "json",
["quartz.jobStore.clustered"] = "true", // 指示Quartz.net的JobStore是应对 集群模式
["quartz.scheduler.instanceId"] = "AUTO"
};
return new StdSchedulerFactory(properties);
});
}
//是否开启后台任务
if (GlobalContext.SystemConfig.OpenQuartz == true)
{
services.AddHostedService<JobCenter>();
}
return services;
}
/// <summary>
/// 重置超管密码
/// </summary>
public static IServiceCollection ReviseSuperSysem(this IServiceCollection services)
{
var data = GlobalContext.SystemConfig;
try
{
if (data.ReviseSystem == true)
{
using (var context = new SqlSugarClient(DBContexHelper.Contex()))
{
context.Ado.BeginTran();
var systemSet = context.Queryable<SystemSetEntity>().First(a => a.F_DbNumber == data.MainDbNumber);
var user = context.Queryable<UserEntity>().First(a => a.F_CompanyId == systemSet.F_Id && a.F_IsAdmin == true);
var userinfo = context.Queryable<UserLogOnEntity>().Where(a => a.F_UserId == user.F_Id).First();
userinfo.F_UserSecretkey = Md5.md5(Utils.CreateNo(), 16).ToLower();
userinfo.F_UserPassword = Md5.md5(DESEncrypt.Encrypt(Md5.md5(systemSet.F_AdminPassword, 32).ToLower(), userinfo.F_UserSecretkey).ToLower(), 32).ToLower();
context.Updateable<UserEntity>(a => new UserEntity
{
F_Account = systemSet.F_AdminAccount
}).Where(a => a.F_Id == userinfo.F_Id).ExecuteCommand();
context.Updateable<UserLogOnEntity>(a => new UserLogOnEntity
{
F_UserPassword = userinfo.F_UserPassword,
F_UserSecretkey = userinfo.F_UserSecretkey
}).Where(a => a.F_Id == userinfo.F_Id).ExecuteCommand();
context.Ado.CommitTran();
CacheHelper.Remove(GlobalContext.SystemConfig.ProjectPrefix + "_operator_" + "info_" + user.F_Id);
}
}
}
catch (Exception ex)
{
LogHelper.Write(ex);
}
return services;
}
/// <summary>
/// 注册事件总线
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddEventBus(this IServiceCollection services)
{
// 注册 EventBus 服务
return services.AddEventBus(builder =>
{
if (GlobalContext.SystemConfig.RabbitMq.Enabled)
{
// 创建连接工厂
var factory = new ConnectionFactory
{
HostName= GlobalContext.SystemConfig.RabbitMq.HostName,
VirtualHost= GlobalContext.SystemConfig.RabbitMq.VirtualHost,
Port= GlobalContext.SystemConfig.RabbitMq.Port,
UserName = GlobalContext.SystemConfig.RabbitMq.UserName,
Password = GlobalContext.SystemConfig.RabbitMq.Password
};
// 创建默认内存通道事件源对象可自定义队列路由key比如这里是 eventbus
var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, GlobalContext.SystemConfig.ProjectPrefix
+ "_eventbus", 3000);
// 替换默认事件总线存储器
builder.ReplaceStorer(serviceProvider =>
{
return rbmqEventSourceStorer;
});
}
// 注册 ToDo 事件订阅者
builder.AddSubscriber<LogEventSubscriber>();
builder.AddSubscriber<MessageEventSubscriber>();
});
}
}
}