😎1、优化sqlsugar扩展相关及其他代码 2、升级依赖

This commit is contained in:
zuohuaijun 2025-05-18 17:27:22 +08:00
parent 23ab3f9c2c
commit a95b29757d
17 changed files with 292 additions and 287 deletions

View File

@ -26,11 +26,11 @@
<PackageReference Include="AngleSharp" Version="1.3.0" />
<PackageReference Include="AspectCore.Extensions.Reflection" Version="2.4.0" />
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.1" Aliases="BouncyCastleV2" />
<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.0" Aliases="BouncyCastleV2" />
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.0.3" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.62" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.62" />
<PackageReference Include="Furion.Pure" Version="4.9.7.62" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.68" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.68" />
<PackageReference Include="Furion.Pure" Version="4.9.7.68" />
<PackageReference Include="Hardware.Info" Version="101.0.1" />
<PackageReference Include="Hashids.net" Version="1.7.0" />
<PackageReference Include="IPTools.China" Version="1.6.0" />
@ -39,7 +39,7 @@
<PackageReference Include="Magicodes.IE.Excel" Version="2.7.5.2" />
<PackageReference Include="Magicodes.IE.Pdf" Version="2.7.5.2" />
<PackageReference Include="Magicodes.IE.Word" Version="2.7.5.2" />
<PackageReference Include="MailKit" Version="4.12.0" />
<PackageReference Include="MailKit" Version="4.12.1" />
<PackageReference Include="MiniExcel" Version="1.41.1" />
<PackageReference Include="MiniWord" Version="0.9.2" />
<PackageReference Include="MQTTnet.Server" Version="5.0.1.1416" />
@ -56,7 +56,7 @@
<PackageReference Include="SSH.NET" Version="2025.0.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.3" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1238" />
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1240" />
<PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup>

View File

@ -21,7 +21,7 @@ public class CommonConst
/// 日志分组名称
/// </summary>
public const string SysLogCategoryName = "System.Logging.LoggingMonitor";
/// <summary>
/// 最大并发数
/// </summary>

View File

@ -7,7 +7,7 @@
namespace Admin.NET.Core;
/// <summary>
/// 枚举拓展
/// 枚举拓展方法
/// </summary>
public static class EnumExtension
{

View File

@ -8,6 +8,9 @@ using Microsoft.AspNetCore.Authentication;
namespace Admin.NET.Core;
/// <summary>
/// HttpContext 扩展方法
/// </summary>
public static class HttpContextExtension
{
public static async Task<AuthenticationScheme[]> GetExternalProvidersAsync(this HttpContext context)

View File

@ -6,7 +6,10 @@
namespace Admin.NET.Core;
public static class ListExtensions
/// <summary>
/// List 扩展方法
/// </summary>
public static class ListExtension
{
public static async Task ForEachAsync<T>(this List<T> list, Func<T, Task> func)
{

View File

@ -7,7 +7,7 @@
namespace Admin.NET.Core;
/// <summary>
/// 对象拓展
/// 对象拓展方法
/// </summary>
public static partial class ObjectExtension
{

View File

@ -8,6 +8,9 @@ using MapsterMapper;
namespace Admin.NET.Core;
/// <summary>
/// 仓储扩展方法
/// </summary>
public static class RepositoryExtension
{
/// <summary>
@ -444,146 +447,4 @@ public static class RepositoryExtension
throw Oops.Oh(error);
}
}
/// <summary>
/// 初始化表实体
/// </summary>
/// <param name="dbProvider"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static void InitTable<T>(this SqlSugarScopeProvider dbProvider) where T : class, new()
{
InitTable(dbProvider, typeof(T));
}
/// <summary>
/// 初始化表实体
/// </summary>
/// <param name="entityType"></param>
/// <param name="dbProvider"></param>
/// <returns></returns>
public static void InitTable(this SqlSugarScopeProvider dbProvider, Type entityType)
{
// 初始化表实体,如果存在分表特性,需要额外处理
if (entityType.GetCustomAttribute<SplitTableAttribute>() == null)
dbProvider.CodeFirst.InitTables(entityType);
else
dbProvider.CodeFirst.SplitTables().InitTables(entityType);
// 将不存在实体中的字段改为可空
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(entityType);
var dbColumnInfos = dbProvider.DbMaintenance.GetColumnInfosByTableName(entityInfo.DbTableName) ?? [];
foreach (var dbColumnInfo in dbColumnInfos.Where(dbColumnInfo => !dbColumnInfo.IsPrimarykey && entityInfo.Columns.All(u => u.DbColumnName != dbColumnInfo.DbColumnName)))
{
dbColumnInfo.IsNullable = true;
dbProvider.DbMaintenance.UpdateColumn(entityInfo.DbTableName, dbColumnInfo);
}
}
/// <summary>
/// 初始化表种子数据
/// </summary>
/// <param name="db"></param>
/// <param name="handleBefore"></param>
/// <returns></returns>
public static (int, int, int)? InitTableSeedData<T>(this SqlSugarScope db, Action<object> handleBefore = null)
{
return InitTableSeedData(db, typeof(T), handleBefore);
}
/// <summary>
/// 初始化表种子数据
/// </summary>
/// <param name="db"></param>
/// <param name="seedType"></param>
/// <param name="handleBefore"></param>
/// <returns></returns>
public static (int, int, int)? InitTableSeedData(this SqlSugarScope db, Type seedType, Action<object> handleBefore = null)
{
var config = db.CurrentConnectionConfig;
var dbProvider = db.GetConnectionScope(config.ConfigId);
// 获取表实体类型
var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
if (config.ConfigId.ToString() == SqlSugarConst.MainConfigId) // 默认库(有系统表特性、没有日志表和租户表特性)
{
if (entityType.GetCustomAttribute<SysTableAttribute>() == null &&
(entityType.GetCustomAttribute<LogTableAttribute>() != null ||
entityType.GetCustomAttribute<TenantAttribute>() != null))
return default;
}
else if (config.ConfigId.ToString() == SqlSugarConst.LogConfigId) // 日志库
{
if (entityType.GetCustomAttribute<LogTableAttribute>() == null) return default;
}
else
{
var att = entityType.GetCustomAttribute<TenantAttribute>(); // 自定义的库
if (att == null || att.configId.ToString() != config.ConfigId.ToString()) return default;
}
var instance = Activator.CreateInstance(seedType);
var hasDataMethod = seedType.GetMethod("HasData");
var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>().ToArray() ?? [];
if (!seedData.Any()) return default;
// 若实体包含Id字段则设置为当前租户Id递增1
var idProp = entityType.GetProperty(nameof(EntityBaseId.Id));
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(entityType);
if (idProp != null && entityInfo.Columns.Any(u => u.PropertyName == nameof(EntityBaseId.Id)))
{
var seedId = config.ConfigId.ToLong();
foreach (var sd in seedData)
{
var id = idProp!.GetValue(sd, null);
if (id == null || id.ToString() == "0" || string.IsNullOrWhiteSpace(id.ToString()))
idProp.SetValue(sd, ++seedId);
}
}
// 执行前处理种子数据
if (handleBefore != null) foreach (var sd in seedData) handleBefore(sd);
int total, insertCount = 0, updateCount = 0;
if (entityType.GetCustomAttribute<SplitTableAttribute>(true) != null)
{
// 拆分表的操作需要实体类型,而通过反射很难实现
// 所以这里将Init方法写在“种子数据类”内部再传入 db 反射调用
var hasInitMethod = seedType.GetMethod("Init");
var parameters = new object[] { db };
var result = hasInitMethod?.Invoke(instance, parameters) as (int, int, int)?;
total = result?.Item1 ?? 0;
insertCount = result?.Item2 ?? 0;
updateCount = result?.Item3 ?? 0;
}
else
{
var seedDataList = seedData.ToList();
total = seedDataList.Count;
// 按主键进行批量增加和更新
if (entityInfo.Columns.Any(u => u.IsPrimarykey))
{
// 先修改再插入,否则会更新修改时间字段
var storage = dbProvider.StorageableByObject(seedDataList).ToStorage();
if (seedType.GetCustomAttribute<IgnoreUpdateSeedAttribute>() == null) // 有忽略更新种子特性时则不更新
{
updateCount = storage.AsUpdateable.IgnoreColumns(entityInfo.Columns.Where(u => u.PropertyInfo.GetCustomAttribute<IgnoreUpdateSeedColumnAttribute>() != null)
.Select(u => u.PropertyName).ToArray()).ExecuteCommand();
}
insertCount = storage.AsInsertable.ExecuteCommand();
}
// 无主键则只进行插入
else
{
if (!dbProvider.Queryable(entityInfo.DbTableName, entityInfo.DbTableName).Any())
{
insertCount = seedDataList.Count;
dbProvider.InsertableByObject(seedDataList).ExecuteCommand();
}
}
}
return (total, insertCount, updateCount);
}
}

View File

@ -1,58 +0,0 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
public static class SqlSugarFilterExtension
{
/// <summary>
/// 根据指定Attribute获取属性
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <returns></returns>
private static List<string> GetPropertyNames<T>(this Type type) where T : Attribute
{
return type.GetProperties()
.Where(p => p.CustomAttributes.Any(x => x.AttributeType == typeof(T)))
.Select(x => x.Name).ToList();
}
/// <summary>
/// 获取过滤表达式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="owners"></param>
/// <returns></returns>
public static LambdaExpression GetConditionExpression<T>(this Type type, List<long> owners) where T : Attribute
{
var fieldNames = type.GetPropertyNames<T>();
ParameterExpression parameter = Expression.Parameter(type, "c");
Expression right = Expression.Constant(false);
ConstantExpression ownersCollection = Expression.Constant(owners);
foreach (var fieldName in fieldNames)
{
var property = type.GetProperty(fieldName);
Expression memberExp = Expression.Property(parameter, property!);
// 如果属性是可为空的类型,则转换为其基础类型
var baseType = Nullable.GetUnderlyingType(property.PropertyType);
if (baseType != null) memberExp = Expression.Convert(memberExp, baseType);
// 调用ownersCollection.Contains方法检查是否包含属性值
right = Expression.OrElse(Expression.Call(
typeof(Enumerable),
nameof(Enumerable.Contains),
new[] { memberExp.Type },
ownersCollection,
memberExp
), right);
}
return Expression.Lambda(right, parameter);
}
}

View File

@ -220,7 +220,7 @@ public class SysDbBackupService : IDynamicApiController, ITransient
// 压缩成功后,将临时文件移动到目标路径
File.Move(tempPath, finalPath);
}
catch (Exception ex)
catch
{
// 清理临时文件
if (File.Exists(tempPath))

View File

@ -170,7 +170,7 @@ public class GenerateQRImageInput
public class GenerateQRImageUnLimitInput : GenerateQRImageInput
{
/// <summary>
/// 二维码携带的参数 eg:a=1最大32个可见字符只支持数字大小写英文以及部分特殊字符!#$&'()*+,/:;=?@-._~
/// 二维码携带的参数 eg:a=1最大32个可见字符只支持数字大小写英文以及部分特殊字符<!-- !#$&'()*+,/:;=?@-._~ -->
/// </summary>
public string Scene { get; set; }
}

View File

@ -9,10 +9,72 @@ using System.Text.Json;
namespace Admin.NET.Core;
/// <summary>
/// Sqlsugar 动态查询扩展方法
/// Sqlsugar 扩展方法
/// </summary>
public static class SqlSugarExtension
{
#region
/// <summary>
/// 切换数据库
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="db"></param>
/// <returns></returns>
public static ISqlSugarClient ForTenant<TEntity>(this ISqlSugarClient db)
{
var attr = typeof(TEntity).GetCustomAttribute<TenantAttribute>();
var tenantId = attr != null ? GetConfigIdFromAttribute(attr) : SqlSugarConst.DefaultTenantId;
return db.AsTenant().GetConnection(tenantId ?? SqlSugarConst.DefaultTenantId);
}
private static object GetConfigIdFromAttribute(TenantAttribute attr)
{
const string targetKey = "configId";
var type = attr.GetType();
// 方式1尝试通过属性获取
var prop = type.GetProperty(targetKey, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (prop != null) return prop.GetValue(attr);
// 方式2尝试通过私有字段获取
var fieldNames = new[]
{
$"<{targetKey}>k__BackingField", // 自动属性字段
$"_{targetKey}", // 常规私有字段 (如_configId)
$"m_{targetKey}", // 匈牙利命名法
"configId" // 直接字段访问
};
foreach (var name in fieldNames)
{
var field = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null) return field.GetValue(attr);
}
// 方式3通过Dynamic访问备用方案
try
{
dynamic d = attr;
return d.configId;
}
catch
{
return null;
}
}
#endregion
#region
/// <summary>
/// Sqlsugar 动态查询扩展方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="queryable"></param>
/// <param name="filter"></param>
/// <returns></returns>
public static ISugarQueryable<T> SearchBy<T>(this ISugarQueryable<T> queryable, BaseFilter filter)
{
return queryable.SearchByKeyword(filter.Keyword).AdvancedSearch(filter.Search).AdvancedFilter(filter.Filter);
@ -253,4 +315,152 @@ public static class SqlSugarExtension
return Expression.Call(selectorExpr, method, constant);
}
#endregion
#region
/// <summary>
/// 初始化表实体
/// </summary>
/// <param name="dbProvider"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static void InitTable<T>(this SqlSugarScopeProvider dbProvider) where T : class, new()
{
InitTable(dbProvider, typeof(T));
}
/// <summary>
/// 初始化表实体
/// </summary>
/// <param name="entityType"></param>
/// <param name="dbProvider"></param>
/// <returns></returns>
public static void InitTable(this SqlSugarScopeProvider dbProvider, Type entityType)
{
// 初始化表实体,如果存在分表特性,需要额外处理
if (entityType.GetCustomAttribute<SplitTableAttribute>() == null)
dbProvider.CodeFirst.InitTables(entityType);
else
dbProvider.CodeFirst.SplitTables().InitTables(entityType);
// 将不存在实体中的字段改为可空
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(entityType);
var dbColumnInfos = dbProvider.DbMaintenance.GetColumnInfosByTableName(entityInfo.DbTableName) ?? [];
foreach (var dbColumnInfo in dbColumnInfos.Where(dbColumnInfo => !dbColumnInfo.IsPrimarykey && entityInfo.Columns.All(u => u.DbColumnName != dbColumnInfo.DbColumnName)))
{
dbColumnInfo.IsNullable = true;
dbProvider.DbMaintenance.UpdateColumn(entityInfo.DbTableName, dbColumnInfo);
}
}
/// <summary>
/// 初始化表种子数据
/// </summary>
/// <param name="db"></param>
/// <param name="handleBefore"></param>
/// <returns></returns>
public static (int, int, int)? InitTableSeedData<T>(this SqlSugarScope db, Action<object> handleBefore = null)
{
return InitTableSeedData(db, typeof(T), handleBefore);
}
/// <summary>
/// 初始化表种子数据
/// </summary>
/// <param name="db"></param>
/// <param name="seedType"></param>
/// <param name="handleBefore"></param>
/// <returns></returns>
public static (int, int, int)? InitTableSeedData(this SqlSugarScope db, Type seedType, Action<object> handleBefore = null)
{
var config = db.CurrentConnectionConfig;
var dbProvider = db.GetConnectionScope(config.ConfigId);
// 获取表实体类型
var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
if (config.ConfigId.ToString() == SqlSugarConst.MainConfigId) // 默认库(有系统表特性、没有日志表和租户表特性)
{
if (entityType.GetCustomAttribute<SysTableAttribute>() == null &&
(entityType.GetCustomAttribute<LogTableAttribute>() != null ||
entityType.GetCustomAttribute<TenantAttribute>() != null))
return default;
}
else if (config.ConfigId.ToString() == SqlSugarConst.LogConfigId) // 日志库
{
if (entityType.GetCustomAttribute<LogTableAttribute>() == null) return default;
}
else
{
var att = entityType.GetCustomAttribute<TenantAttribute>(); // 自定义的库
if (att == null || att.configId.ToString() != config.ConfigId.ToString()) return default;
}
var instance = Activator.CreateInstance(seedType);
var hasDataMethod = seedType.GetMethod("HasData");
var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>().ToArray() ?? [];
if (!seedData.Any()) return default;
// 若实体包含Id字段则设置为当前租户Id递增1
var idProp = entityType.GetProperty(nameof(EntityBaseId.Id));
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(entityType);
if (idProp != null && entityInfo.Columns.Any(u => u.PropertyName == nameof(EntityBaseId.Id)))
{
var seedId = config.ConfigId.ToLong();
foreach (var sd in seedData)
{
var id = idProp!.GetValue(sd, null);
if (id == null || id.ToString() == "0" || string.IsNullOrWhiteSpace(id.ToString()))
idProp.SetValue(sd, ++seedId);
}
}
// 执行前处理种子数据
if (handleBefore != null) foreach (var sd in seedData) handleBefore(sd);
int total, insertCount = 0, updateCount = 0;
if (entityType.GetCustomAttribute<SplitTableAttribute>(true) != null)
{
// 拆分表的操作需要实体类型,而通过反射很难实现
// 所以这里将Init方法写在“种子数据类”内部再传入 db 反射调用
var hasInitMethod = seedType.GetMethod("Init");
var parameters = new object[] { db };
var result = hasInitMethod?.Invoke(instance, parameters) as (int, int, int)?;
total = result?.Item1 ?? 0;
insertCount = result?.Item2 ?? 0;
updateCount = result?.Item3 ?? 0;
}
else
{
var seedDataList = seedData.ToList();
total = seedDataList.Count;
// 按主键进行批量增加和更新
if (entityInfo.Columns.Any(u => u.IsPrimarykey))
{
// 先修改再插入,否则会更新修改时间字段
var storage = dbProvider.StorageableByObject(seedDataList).ToStorage();
if (seedType.GetCustomAttribute<IgnoreUpdateSeedAttribute>() == null) // 有忽略更新种子特性时则不更新
{
updateCount = storage.AsUpdateable.IgnoreColumns(entityInfo.Columns.Where(u => u.PropertyInfo.GetCustomAttribute<IgnoreUpdateSeedColumnAttribute>() != null)
.Select(u => u.PropertyName).ToArray()).ExecuteCommand();
}
insertCount = storage.AsInsertable.ExecuteCommand();
}
// 无主键则只进行插入
else
{
if (!dbProvider.Queryable(entityInfo.DbTableName, entityInfo.DbTableName).Any())
{
insertCount = seedDataList.Count;
dbProvider.InsertableByObject(seedDataList).ExecuteCommand();
}
}
}
return (total, insertCount, updateCount);
}
#endregion
}

View File

@ -1,56 +0,0 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
/// <summary>
/// 切换数据库
/// </summary>
public static class SqlSugarExtensions
{
public static ISqlSugarClient ForTenant<TEntity>(this ISqlSugarClient db)
{
var attr = typeof(TEntity).GetCustomAttribute<TenantAttribute>();
var tenantId = attr != null ? GetConfigIdFromAttribute(attr) : SqlSugarConst.DefaultTenantId;
return db.AsTenant().GetConnection(tenantId ?? SqlSugarConst.DefaultTenantId);
}
private static object GetConfigIdFromAttribute(TenantAttribute attr)
{
const string targetKey = "configId";
var type = attr.GetType();
// 方式1尝试通过属性获取
var prop = type.GetProperty(targetKey, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (prop != null) return prop.GetValue(attr);
// 方式2尝试通过私有字段获取
var fieldNames = new[]
{
$"<{targetKey}>k__BackingField", // 自动属性字段
$"_{targetKey}", // 常规私有字段 (如_configId)
$"m_{targetKey}", // 匈牙利命名法
"configId" // 直接字段访问
};
foreach (var name in fieldNames)
{
var field = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null) return field.GetValue(attr);
}
// 方式3通过Dynamic访问备用方案
try
{
dynamic d = attr;
return d.configId;
}
catch
{
return null;
}
}
}

View File

@ -207,6 +207,54 @@ public static class SqlSugarFilter
});
}
}
/// <summary>
/// 获取过滤表达式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="owners"></param>
/// <returns></returns>
public static LambdaExpression GetConditionExpression<T>(this Type type, List<long> owners) where T : Attribute
{
var fieldNames = type.GetPropertyNames<T>();
ParameterExpression parameter = Expression.Parameter(type, "c");
Expression right = Expression.Constant(false);
ConstantExpression ownersCollection = Expression.Constant(owners);
foreach (var fieldName in fieldNames)
{
var property = type.GetProperty(fieldName);
Expression memberExp = Expression.Property(parameter, property!);
// 如果属性是可为空的类型,则转换为其基础类型
var baseType = Nullable.GetUnderlyingType(property.PropertyType);
if (baseType != null) memberExp = Expression.Convert(memberExp, baseType);
// 调用ownersCollection.Contains方法检查是否包含属性值
right = Expression.OrElse(Expression.Call(
typeof(Enumerable),
nameof(Enumerable.Contains),
new[] { memberExp.Type },
ownersCollection,
memberExp
), right);
}
return Expression.Lambda(right, parameter);
}
/// <summary>
/// 根据指定Attribute获取属性
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <returns></returns>
private static List<string> GetPropertyNames<T>(this Type type) where T : Attribute
{
return type.GetProperties()
.Where(p => p.CustomAttributes.Any(x => x.AttributeType == typeof(T)))
.Select(x => x.Name).ToList();
}
}
/// <summary>

View File

@ -525,7 +525,6 @@ public static class SqlSugarSetup
.WhereIF(config.SeedSettings.EnableIncreSeed, u => u.IsDefined(typeof(IncreSeedAttribute), false))
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? ((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0]).Order : 0).ToList();
var semaphore = new SemaphoreSlim(CommonConst.MaxConcurrent); // 并发限制数量
int taskIndex = 0, size = seedDataTypes.Count;
var taskList = seedDataTypes.Select(seedType => Task.Run(() =>

View File

@ -24,14 +24,9 @@
</Content>
</ItemGroup>
<ItemGroup>
<Compile Remove="OcrModel\**" />
<EmbeddedResource Remove="OcrModel\**" />
<None Remove="OcrModel\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="PaddleOCRSharp" Version="4.5.0.1" />
<PackageReference Include="Paddle.Runtime.win_x64" Version="3.0.0" />
</ItemGroup>
<ItemGroup>

View File

@ -25,7 +25,7 @@
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.13.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.14.0" />
<PackageReference Include="Rezero.Api" Version="1.8.16" />
</ItemGroup>

View File

@ -2,7 +2,7 @@
"name": "admin.net.pro",
"type": "module",
"version": "2.4.33",
"lastBuildTime": "2025.05.15",
"lastBuildTime": "2025.05.18",
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
"author": "zuohuaijun",
"license": "MIT",
@ -20,7 +20,7 @@
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@logicflow/core": "^2.0.13",
"@logicflow/extension": "^2.0.17",
"@logicflow/extension": "^2.0.18",
"@microsoft/signalr": "^8.0.7",
"@vue-office/docx": "^1.6.2",
"@vue-office/excel": "^1.7.14",
@ -68,7 +68,7 @@
"splitpanes": "^4.0.3",
"vcrontab-3": "^3.3.22",
"vform3-builds": "^3.0.10",
"vue": "^3.5.13",
"vue": "^3.5.14",
"vue-clipboard3": "^2.0.0",
"vue-demi": "0.14.10",
"vue-draggable-plus": "^0.6.0",
@ -80,8 +80,8 @@
"vue-signature-pad": "^3.0.2",
"vue3-flag-icons": "^0.0.3",
"vue3-tree-org": "^4.2.2",
"vxe-pc-ui": "^4.6.8",
"vxe-table": "^4.13.28",
"vxe-pc-ui": "^4.6.11",
"vxe-table": "^4.13.30",
"xe-utils": "^3.7.4",
"xlsx-js-style": "^1.2.0"
},
@ -96,17 +96,17 @@
"@typescript-eslint/parser": "^8.32.1",
"@vitejs/plugin-vue": "^5.2.4",
"@vitejs/plugin-vue-jsx": "^4.1.2",
"@vue/compiler-sfc": "^3.5.13",
"@vue/compiler-sfc": "^3.5.14",
"code-inspector-plugin": "^0.20.10",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"eslint-plugin-vue": "^10.1.0",
"globals": "^16.1.0",
"less": "^4.3.0",
"openapi-ts-request": "^1.4.0",
"openapi-ts-request": "^1.5.0",
"prettier": "^3.5.3",
"rollup-plugin-visualizer": "^5.14.0",
"sass": "^1.88.0",
"terser": "^5.39.1",
"sass": "^1.89.0",
"terser": "^5.39.2",
"typescript": "^5.8.3",
"vite": "^6.3.5",
"vite-plugin-cdn-import": "^1.0.1",