😎1、优化库表初始化速度 2、默认开启错误文件日志 3、优化代码升级依赖

This commit is contained in:
zuohuaijun 2025-01-06 13:40:19 +08:00
parent 8ff1ed357f
commit 78b9b984ec
27 changed files with 132 additions and 110 deletions

View File

@ -10,10 +10,10 @@
"System.Net.Http.HttpClient": "Warning"
},
"File": {
"Enabled": false, //
"Enabled": true, //
"FileName": "logs/{0:yyyyMMdd}_{1}.log", //
"Append": true, //
// "MinimumLevel": "Information", //
"MinimumLevel": "Error", //
"FileSizeLimitBytes": 10485760, // 10M=10*1024*1024
"MaxRollingFiles": 30 // 30
},

View File

@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Dilon.SmartElder.Application;
namespace Admin.NET.Application;
/// <summary>
/// 系统配置表种子数据

View File

@ -4,11 +4,12 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Dilon.SmartElder.Application;
namespace Admin.NET.Application;
/// <summary>
/// 系统菜单表种子数据
/// </summary>
[SeedData(500)]
[IncreSeed]
public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
{

View File

@ -145,7 +145,7 @@ public class AppAuthService : IDynamicApiController, ITransient
throw Oops.Oh("验证码错误!");
// 账号是否存在
var user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter().FirstAsync(u => u.Phone.Equals(input.Phone));
var user = await _sysUserRep.AsQueryable().Includes(u => u.SysOrg).ClearFilter().FirstAsync(u => u.Phone.Equals(input.Phone));
_ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
return await CreateToken(user, input.LoginMode);

View File

@ -13,7 +13,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="3.1.0" />
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="3.1.1" />
<PackageReference Include="AlipaySDKNet.Standard" Version="4.9.376" />
<PackageReference Include="AngleSharp" Version="1.2.0" />
<PackageReference Include="AspectCore.Extensions.Reflection" Version="2.4.0" />
@ -35,7 +35,7 @@
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.4.6" />
<PackageReference Include="MiniExcel" Version="1.36.0" />
<PackageReference Include="MiniWord" Version="0.9.2" />
<PackageReference Include="MQTTnet" Version="5.0.0.1405" />
<PackageReference Include="MQTTnet" Version="5.0.1.1416" />
<PackageReference Include="MySqlBackup.NET.MySqlConnector" Version="2.3.8" />
<PackageReference Include="NewLife.Redis" Version="6.0.2025.101" />
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="3.6.0" />

View File

@ -22,6 +22,7 @@ public static class ConsoleLogoSetup
/ ____ \ (_| | | | | | | | | | |_| |\ | |____ | |
/_/ \_\__,_|_| |_| |_|_|_| |_(_)_| \_|______| |_| ");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(@"让.NET更简单、更通用、更流行");
Console.WriteLine("让 .NET 开发更简单、更通用、更流行!");
Console.WriteLine("https://gitee.com/zuohuaijun/Admin.NET");
}
}

View File

@ -13,18 +13,18 @@ namespace Admin.NET.Core;
[PeriodSeconds(1, TriggerId = "trigger_EnumToDictJob", Description = "枚举转字典", MaxNumberOfRuns = 1, RunOnStart = true)]
public class EnumToDictJob : IJob
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IServiceScopeFactory _serviceScopeFactory;
private const int OrderOffset = 10;
private const string DefaultTagType = "info";
public EnumToDictJob(IServiceScopeFactory scopeFactory)
public EnumToDictJob(IServiceScopeFactory serviceScopeFactory)
{
_scopeFactory = scopeFactory;
_serviceScopeFactory = serviceScopeFactory;
}
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
{
using var serviceScope = _scopeFactory.CreateScope();
using var serviceScope = _serviceScopeFactory.CreateScope();
var sysEnumService = serviceScope.ServiceProvider.GetRequiredService<SysEnumService>();
// 获取数据库连接
var db = serviceScope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
@ -85,9 +85,10 @@ public class EnumToDictJob : IJob
Log.Error($"系统枚举转换字典操作错误:{error.Message}\n堆栈跟踪{error.StackTrace}", error);
throw;
}
var msg = $"【{DateTime.Now}】系统枚举转换字典。【定时任务】";
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典");
Console.WriteLine(msg);
Console.ForegroundColor = originColor;
}

View File

@ -13,18 +13,18 @@ namespace Admin.NET.Core;
[Daily(TriggerId = "trigger_log", Description = "清理操作日志")]
public class LogJob : IJob
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ILogger _logger;
public LogJob(IServiceScopeFactory scopeFactory, ILoggerFactory loggerFactory)
public LogJob(IServiceScopeFactory serviceScopeFactory, ILoggerFactory loggerFactory)
{
_scopeFactory = scopeFactory;
_serviceScopeFactory = serviceScopeFactory;
_logger = loggerFactory.CreateLogger(CommonConst.SysLogCategoryName);
}
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
{
using var serviceScope = _scopeFactory.CreateScope();
using var serviceScope = _serviceScopeFactory.CreateScope();
var db = serviceScope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
var sysConfigService = serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
@ -35,7 +35,7 @@ public class LogJob : IJob
await db.Deleteable<SysLogDiff>().Where(u => u.CreateTime < DateTime.Now.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除差异日志
await db.Deleteable<SysJobTriggerRecord>().Where(u => u.CreatedTime < DateTime.Now.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除作业触发器运行记录
string msg = $"【{DateTime.Now}】清理系统日志成功,删除 {daysAgo} 天前的日志数据";
var msg = $"【{DateTime.Now}】清理系统日志成功,删除 {daysAgo} 天前的日志数据。【定时任务】";
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(msg);

View File

@ -15,25 +15,25 @@ namespace Admin.NET.Core;
[PeriodSeconds(1, TriggerId = "trigger_onlineUser", Description = "清理在线用户", MaxNumberOfRuns = 1, RunOnStart = true)]
public class OnlineUserJob : IJob
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ILogger _logger;
public OnlineUserJob(IServiceScopeFactory scopeFactory, ILoggerFactory loggerFactory)
public OnlineUserJob(IServiceScopeFactory serviceScopeFactory, ILoggerFactory loggerFactory)
{
_scopeFactory = scopeFactory;
_serviceScopeFactory = serviceScopeFactory;
_logger = loggerFactory.CreateLogger(CommonConst.SysLogCategoryName);
}
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
{
using var serviceScope = _scopeFactory.CreateScope();
using var serviceScope = _serviceScopeFactory.CreateScope();
var db = serviceScope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
await db.Deleteable<SysOnlineUser>().ExecuteCommandAsync(stoppingToken);
string msg = $"【{DateTime.Now}】清理在线用户成功!服务已重启...";
var msg = $"【{DateTime.Now}】清理系统在线用户。【定时任务】";
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(msg);
Console.ForegroundColor = originColor;

View File

@ -12,15 +12,17 @@ namespace Admin.NET.Core;
public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
{
private readonly IServiceScope _serviceScope;
private readonly SqlSugarScopeProvider _db;
private readonly SysConfigService _sysConfigService;
private readonly IEventPublisher _eventPublisher;
private readonly ILogger<DatabaseLoggingWriter> _logger;
private readonly SysConfigService _sysConfigService;
private readonly SqlSugarScopeProvider _db;
public DatabaseLoggingWriter(IServiceScopeFactory scopeFactory)
public DatabaseLoggingWriter(IServiceScopeFactory serviceScopeFactory, IEventPublisher eventPublisher, ILogger<DatabaseLoggingWriter> logger)
{
_serviceScope = scopeFactory.CreateScope();
_serviceScope = serviceScopeFactory.CreateScope();
_sysConfigService = _serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
_logger = _serviceScope.ServiceProvider.GetRequiredService<ILogger<DatabaseLoggingWriter>>();
_eventPublisher = eventPublisher;
_logger = logger;
// 切换日志独立数据库
_db = SqlSugarSetup.ITenant.IsAnyConnection(SqlSugarConst.LogConfigId)
@ -149,7 +151,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
// 将异常日志发送到邮件
if (await _sysConfigService.GetConfigValueByCode<bool>(ConfigConst.SysErrorMail))
{
await App.GetRequiredService<IEventPublisher>().PublishAsync(CommonConst.SendErrorMail, logMsg.Exception ?? loggingMonitor.exception);
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, logMsg.Exception ?? loggingMonitor.exception);
}
return;

View File

@ -45,7 +45,7 @@ public static class LoggingSetup
options.WithTraceId = true; // 显示线程Id
options.WithStackFrame = true; // 显示程序集
options.FileNameRule = fileName => string.Format(fileName, DateTime.Now, logLevel.ToString()); // 每天创建一个文件
options.WriteFilter = logMsg => logMsg.LogLevel >= logLevel; // 日志级别
options.WriteFilter = logMsg => logMsg.LogLevel == logLevel; // 日志级别
options.HandleWriteError = (writeError) => // 写入失败时启用备用文件
{
writeError.UseRollbackFileName(Path.GetFileNameWithoutExtension(writeError.CurrentFileName) + "-oops" + Path.GetExtension(writeError.CurrentFileName));
@ -96,7 +96,7 @@ public static class LoggingSetup
};
options.WriteFilter = (logMsg) =>
{
return logMsg.LogName == CommonConst.SysLogCategoryName; // 只写LoggingMonitor日志
return logMsg.LogName == CommonConst.SysLogCategoryName; // 只记录 LoggingMonitor 分组名称的日志
};
});
}

View File

@ -17,9 +17,9 @@ public class SysAppSeedData : ISqlSugarEntitySeedData<SysApp>
/// <returns></returns>
public IEnumerable<SysApp> HasData()
{
return new[]
{
return
[
new SysApp{ Id=SqlSugarConst.DefaultAppId, Name="默认应用", Logo="/upload/logo.png", Title="Admin.NET", ViceTitle="Admin.NET", ViceDesc="站在巨人肩膀上的 .NET 通用权限开发框架", Watermark="Admin.NET", Copyright="Copyright \u00a9 2021-present Admin.NET All rights reserved.", Icp="省ICP备12345678号", Remark="系统默认应用", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
};
];
}
}

View File

@ -17,8 +17,8 @@ public class SysCodeGenTemplateSeedData : ISqlSugarEntitySeedData<SysCodeGenTemp
/// <returns></returns>
public IEnumerable<SysCodeGenTemplate> HasData()
{
return new[]
{
return
[
new SysCodeGenTemplate{ Id=36036980201001, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Frontend, Name="web_api.ts.vm", OutputFile="api/{PagePath}/{TableNameLower}.ts", Describe ="(WEB)接口",IsDefault=true},
new SysCodeGenTemplate{ Id=36036980201002, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Frontend, Name="web_views_index.vue.vm", OutputFile="views/{PagePath}/{TableNameLower}/index.vue", Describe ="(WEB)列表页面",IsDefault=true},
new SysCodeGenTemplate{ Id=36036980201003, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Frontend, Name="web_views_editDialog.vue.vm", OutputFile="views/{PagePath}/{TableNameLower}/component/editDialog.vue", Describe ="(WEB)编辑对话框",IsDefault=true},
@ -29,6 +29,6 @@ public class SysCodeGenTemplateSeedData : ISqlSugarEntitySeedData<SysCodeGenTemp
new SysCodeGenTemplate{ Id=36036980203001, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Frontend, Name="web_views_el_table_index.vue.vm", OutputFile="views/{PagePath}/{TableNameLower}/index.vue", Describe ="(WEB)列表页面,基于el-table",IsDefault=false},
new SysCodeGenTemplate{ Id=36036980202004, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.SeedData, Name="sys_menu_seed_data.cs.vm", OutputFile="SeedData/{TableName}MenuSeedData.cs", Describe ="(服务端)业务菜单种子数据",IsDefault=true},
};
];
}
}

View File

@ -18,13 +18,13 @@ public class SysOrgSeedData : ISqlSugarEntitySeedData<SysOrg>
/// <returns></returns>
public IEnumerable<SysOrg> HasData()
{
return new[]
{
return
[
new SysOrg{ Id=SqlSugarConst.DefaultTenantId, Pid=0, Name="系统默认", Code="1001", Type="101", Level=1, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="系统默认", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 1, Pid=SqlSugarConst.DefaultTenantId, Name="市场部", Code="100101", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 2, Pid=SqlSugarConst.DefaultTenantId, Name="开发部", Code="100102", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="开发部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 3, Pid=SqlSugarConst.DefaultTenantId, Name="售后部", Code="100103", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="售后部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 4, Pid=SqlSugarConst.DefaultTenantId, Name="其他", Code="10010301", Level=3, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=SqlSugarConst.DefaultTenantId },
};
];
}
}

View File

@ -17,8 +17,8 @@ public class SysPosSeedData : ISqlSugarEntitySeedData<SysPos>
/// <returns></returns>
public IEnumerable<SysPos> HasData()
{
return new[]
{
return
[
new SysPos{ Id=1300000000101, Name="党委书记", Code="dwsj", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="党委书记", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=1300000000102, Name="董事长", Code="dsz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="董事长", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=1300000000103, Name="副董事长", Code="fdsz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副董事长", TenantId=SqlSugarConst.DefaultTenantId },
@ -35,6 +35,6 @@ public class SysPosSeedData : ISqlSugarEntitySeedData<SysPos>
new SysPos{ Id=1300000000114, Name="财务", Code="cw", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="财务", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=1300000000115, Name="职员", Code="zy", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="职员", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=1300000000116, Name="其他", Code="qt", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=SqlSugarConst.DefaultTenantId },
};
];
}
}

View File

@ -17,8 +17,8 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
/// <returns></returns>
public IEnumerable<SysRoleMenu> HasData()
{
return new[]
{
return
[
////// 数据面板【admin/1300000000101】
new SysRoleMenu{ Id=1300000000101, RoleId=1300000000101, MenuId=1300000000101 },
new SysRoleMenu{ Id=1300000000102, RoleId=1300000000101, MenuId=1300000000111 },
@ -237,6 +237,6 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
new SysRoleMenu{ Id=1300000000823, RoleId=1300000000105, MenuId=1310000000163 },
new SysRoleMenu{ Id=1300000000824, RoleId=1300000000105, MenuId=1310000000164 },
new SysRoleMenu{ Id=1300000000825, RoleId=1300000000105, MenuId=1310000000165 },
};
];
}
}

View File

@ -17,13 +17,13 @@ public class SysRoleSeedData : ISqlSugarEntitySeedData<SysRole>
/// <returns></returns>
public IEnumerable<SysRole> HasData()
{
return new[]
{
return
[
new SysRole{ Id=1300000000101, Name="系统管理员", DataScope=DataScopeEnum.All, Code="sys_admin", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="系统管理员", TenantId=SqlSugarConst.DefaultTenantId },
new SysRole{ Id=1300000000102, Name="本部门及以下数据", DataScope=DataScopeEnum.DeptChild, Code="sys_deptChild", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门及以下数据", TenantId=SqlSugarConst.DefaultTenantId },
new SysRole{ Id=1300000000103, Name="本部门数据", DataScope=DataScopeEnum.Dept, Code="sys_dept", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门数据", TenantId=SqlSugarConst.DefaultTenantId },
new SysRole{ Id=1300000000104, Name="仅本人数据", DataScope=DataScopeEnum.Self, Code="sys_self", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="仅本人数据", TenantId=SqlSugarConst.DefaultTenantId },
new SysRole{ Id=1300000000105, Name="自定义数据", DataScope=DataScopeEnum.Define, Code="sys_define", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="自定义数据", TenantId=SqlSugarConst.DefaultTenantId },
};
];
}
}

View File

@ -19,9 +19,9 @@ public class SysTenantSeedData : ISqlSugarEntitySeedData<SysTenant>
{
var defaultDbConfig = App.GetOptions<DbConnectionOptions>().ConnectionConfigs[0];
return new[]
{
return
[
new SysTenant{ Id=SqlSugarConst.DefaultTenantId, AppId=SqlSugarConst.DefaultTenantId, OrgId=SqlSugarConst.DefaultTenantId, UserId=1300000000111, Host=SqlSugarConst.DefaultTenantHost, TenantType=TenantTypeEnum.Id, DbType=defaultDbConfig.DbType, Connection=defaultDbConfig.ConnectionString, ConfigId=SqlSugarConst.MainConfigId, Remark="系统默认", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
};
];
}
}

View File

@ -17,10 +17,10 @@ public class SysUserExtOrgSeedData : ISqlSugarEntitySeedData<SysUserExtOrg>
/// <returns></returns>
public IEnumerable<SysUserExtOrg> HasData()
{
return new[]
{
return
[
new SysUserExtOrg{ Id=1300000000101, UserId=1300000000111, OrgId=1300000000202, PosId=1300000000106 },
new SysUserExtOrg{ Id=1300000000102, UserId=1300000000114, OrgId=1300000000302, PosId=1300000000108 }
};
];
}
}

View File

@ -17,13 +17,13 @@ public class SysUserRoleSeedData : ISqlSugarEntitySeedData<SysUserRole>
/// <returns></returns>
public IEnumerable<SysUserRole> HasData()
{
return new[]
{
return
[
new SysUserRole{ Id=1300000000101, UserId=1300000000111, RoleId=1300000000101 },
new SysUserRole{ Id=1300000000102, UserId=1300000000112, RoleId=1300000000102 },
new SysUserRole{ Id=1300000000103, UserId=1300000000113, RoleId=1300000000103 },
new SysUserRole{ Id=1300000000104, UserId=1300000000114, RoleId=1300000000104 },
new SysUserRole{ Id=1300000000105, UserId=1300000000115, RoleId=1300000000105 },
};
];
}
}

View File

@ -20,14 +20,14 @@ public class SysUserSeedData : ISqlSugarEntitySeedData<SysUser>
{
var encryptPassword = CryptogramUtil.Encrypt("Admin.NET++010101");
return new[]
{
return
[
new SysUser{ Id=1300000000101, Account="superadmin", Password=encryptPassword, NickName="超级管理员", RealName="超级管理员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Male, AccountType=AccountTypeEnum.SuperAdmin, Remark="超级管理员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000111, Account="admin", Password=encryptPassword, NickName="系统管理员", RealName="系统管理员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Male, AccountType=AccountTypeEnum.SysAdmin, Remark="系统管理员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId, PosId=1300000000102, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000112, Account="user1", Password=encryptPassword, NickName="部门主管", RealName="部门主管", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="部门主管", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 1, PosId=1300000000108, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000113, Account="user2", Password=encryptPassword, NickName="部门职员", RealName="部门职员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="部门职员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 2, PosId=1300000000110, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000114, Account="user3", Password=encryptPassword, NickName="普通用户", RealName="普通用户", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="普通用户", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 3, PosId=1300000000115, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000115, Account="user4", Password=encryptPassword, NickName="其他", RealName="其他", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.Member, Remark="会员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 4, PosId=1300000000116, TenantId=SqlSugarConst.DefaultTenantId },
};
];
}
}

View File

@ -11,16 +11,16 @@ namespace Admin.NET.Core.Service;
/// </summary>
public class JobMonitor : IJobMonitor
{
private readonly IEventPublisher _eventPublisher;
private readonly SysConfigService _sysConfigService;
private readonly IEventPublisher _eventPublisher;
private readonly ILogger<JobMonitor> _logger;
public JobMonitor(IServiceScopeFactory scopeFactory)
public JobMonitor(IServiceScopeFactory serviceScopeFactory, IEventPublisher eventPublisher, ILogger<JobMonitor> logger)
{
var serviceScope = scopeFactory.CreateScope();
var serviceScope = serviceScopeFactory.CreateScope();
_sysConfigService = serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
_eventPublisher = serviceScope.ServiceProvider.GetRequiredService<IEventPublisher>();
_logger = serviceScope.ServiceProvider.GetRequiredService<ILogger<JobMonitor>>();
_eventPublisher = eventPublisher;
_logger = logger;
}
public Task OnExecutingAsync(JobExecutingContext context, CancellationToken stoppingToken)
@ -32,16 +32,14 @@ public class JobMonitor : IJobMonitor
{
if (context.Exception == null) return;
var errorInfo = $"【{context.Trigger.Description}】定时任务错误:{context.Exception}";
var exception = $"定时任务【{context.Trigger.Description}】错误:{context.Exception}";
// 将作业异常信息记录到本地
_logger.LogError(exception);
if (await _sysConfigService.GetConfigValueByCode<bool>(ConfigConst.SysErrorMail))
{
// 将异常作业发送到邮件
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, errorInfo, stoppingToken);
}
else
{
// 将异常信息存储本地记录
_logger.LogError(errorInfo);
// 将作业异常信息发送到邮件
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, exception, stoppingToken);
}
}
}

View File

@ -389,15 +389,27 @@ public static class SqlSugarSetup
else
entityTypes = entityTypes.Where(u => u.GetCustomAttribute<TenantAttribute>()?.configId.ToString() == config.ConfigId.ToString()).ToList(); // 自定义的库
int count = 0, sum = entityTypes.Count;
foreach (var entityType in entityTypes)
int taskIndex = 0, entityTypeCount = entityTypes.Count;
var taskList = entityTypes.Select(entityType => Task.Run(() =>
{
Console.WriteLine($"创建表 {entityType} ({config.ConfigId} - {++count}/{sum})");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化表 {entityType,-64} ({config.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{entityTypeCount:D003})");
// 将不存在实体中的字段改为可空
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(entityType);
var dbColumnInfos = dbProvider.DbMaintenance.GetColumnInfosByTableName(entityInfo.DbTableName) ?? [];
foreach (var dbColumnInfo in dbColumnInfos.Where(dbColumnInfo => entityInfo.Columns.All(u => u.DbColumnName != dbColumnInfo.DbColumnName)))
{
dbColumnInfo.IsNullable = true;
dbProvider.DbMaintenance.UpdateColumn(entityInfo.DbTableName, dbColumnInfo);
}
if (entityType.GetCustomAttribute<SplitTableAttribute>() == null)
dbProvider.CodeFirst.InitTables(entityType);
else
dbProvider.CodeFirst.SplitTables().InitTables(entityType);
}
}));
Task.WaitAll(taskList.ToArray());
}
// 初始化种子数据
@ -420,35 +432,33 @@ 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();
int count = 0, sum = seedDataTypes.Count;
int taskIndex = 0, seedDataTypeCount = seedDataTypes.Count;
foreach (var seedType in seedDataTypes)
{
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))
continue;
return;
}
else if (config.ConfigId.ToString() == SqlSugarConst.LogConfigId) // 日志库
{
if (entityType.GetCustomAttribute<LogTableAttribute>() == null)
continue;
return;
}
else
{
var att = entityType.GetCustomAttribute<TenantAttribute>(); // 自定义的库
if (att == null || att.configId.ToString() != config.ConfigId.ToString()) continue;
if (att == null || att.configId.ToString() != config.ConfigId.ToString()) return;
}
var instance = Activator.CreateInstance(seedType);
var hasDataMethod = seedType.GetMethod("HasData");
var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>();
if (seedData == null) continue;
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(entityType);
Console.WriteLine($"添加数据 {entityInfo.DbTableName} ({config.ConfigId} - {++count}/{sum},数据量:{seedData.Count()})");
if (seedData == null) return;
// 若实体包含Id字段则设置为当前租户Id递增1
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(entityType);
if (entityInfo.Columns.Any(u => u.PropertyName == nameof(EntityBaseId.Id)))
{
var seedId = config.ConfigId.ToLong();
@ -470,26 +480,31 @@ public static class SqlSugarSetup
}
else
{
var seedDataList = seedData.ToList();
int updateCount = 0, insertCount = 0;
// 按主键进行批量增加和更新
if (entityInfo.Columns.Any(u => u.IsPrimarykey))
{
// 按主键进行批量增加和更新
var storage = dbProvider.StorageableByObject(seedData.ToList()).ToStorage();
// 先修改再插入,否则会更新修改时间字段
var storage = dbProvider.StorageableByObject(seedDataList).ToStorage();
if (seedType.GetCustomAttribute<IgnoreUpdateSeedAttribute>() == null) // 有忽略更新种子特性时则不更新
{
int updateCount = storage.AsUpdateable.IgnoreColumns(entityInfo.Columns.Where(u => u.PropertyInfo.GetCustomAttribute<IgnoreUpdateSeedColumnAttribute>() != null).Select(u => u.PropertyName).ToArray()).ExecuteCommand();
Console.WriteLine($" 修改 {updateCount}/{seedData.Count()} 条记录");
updateCount = storage.AsUpdateable.IgnoreColumns(entityInfo.Columns.Where(u => u.PropertyInfo.GetCustomAttribute<IgnoreUpdateSeedColumnAttribute>() != null)
.Select(u => u.PropertyName).ToArray()).ExecuteCommand();
}
int insertCount = storage.AsInsertable.ExecuteCommand();
Console.WriteLine($" 插入 {insertCount}/{seedData.Count()} 条记录");
insertCount = storage.AsInsertable.ExecuteCommand();
}
// 无主键则只进行插入
else
{
// 无主键则只进行插入
if (!dbProvider.Queryable(entityInfo.DbTableName, entityInfo.DbTableName).Any())
dbProvider.InsertableByObject(seedData.ToList()).ExecuteCommand();
{
insertCount = seedDataList.Count;
dbProvider.InsertableByObject(seedDataList).ExecuteCommand();
}
}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化种子数据 {seedType.FullName,-58} ({config.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{seedDataTypeCount:D003},数据量:{seedDataList.Count:D003},新增 {insertCount:D003} 条记录,更新 {updateCount:D003} 条记录)");
}
}

View File

@ -78,14 +78,14 @@ public class Startup : AppStartup
{
if (App.GetConfig<bool>("JobSchedule:Enabled", true))
{
options.LogEnabled = false; // 是否输出作业调度器日志
options.AddPersistence<DbJobPersistence>(); // 添加作业持久化器
options.AddMonitor<JobMonitor>(); // 添加作业执行监视器
// 定义未捕获的异常
options.UnobservedTaskExceptionHandler = (obj, args) =>
{
if (args.Exception?.Message != null)
Log.Error($"JobSchedule 有未处理异常:{args.Exception?.Message}", args.Exception);
};
//// 定义未捕获的异常
//options.UnobservedTaskExceptionHandler = (obj, args) =>
//{
// Log.Error($"作业调度异常:{args.Exception?.Message}", args.Exception);
//};
}
});
// 脱敏检测

View File

@ -2,7 +2,7 @@
"name": "admin.net.pro",
"type": "module",
"version": "2.4.33",
"lastBuildTime": "2025.01.04",
"lastBuildTime": "2025.01.06",
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
"author": "zuohuaijun",
"license": "MIT",
@ -74,18 +74,18 @@
"vue-router": "^4.5.0",
"vue-signature-pad": "^3.0.2",
"vue3-tree-org": "^4.2.2",
"vxe-pc-ui": "^4.3.61",
"vxe-table": "^4.10.0",
"vxe-pc-ui": "^4.3.65",
"vxe-table": "^4.10.1",
"vxe-table-plugin-element": "^4.0.4",
"vxe-table-plugin-export-xlsx": "^4.0.7",
"xe-utils": "^3.7.0",
"xlsx-js-style": "^1.2.0"
},
"devDependencies": {
"@iconify/vue": "^4.2.0",
"@iconify/vue": "^4.3.0",
"@plugin-web-update-notification/vite": "^1.7.1",
"@types/lodash-es": "^4.17.12",
"@types/node": "^20.17.10",
"@types/node": "^20.17.11",
"@types/nprogress": "^0.2.3",
"@types/sortablejs": "^1.15.8",
"@typescript-eslint/eslint-plugin": "^8.19.0",
@ -100,7 +100,7 @@
"less": "^4.2.1",
"prettier": "^3.4.2",
"rollup-plugin-visualizer": "^5.13.1",
"sass": "^1.83.0",
"sass": "^1.83.1",
"terser": "^5.37.0",
"typescript": "^5.7.2",
"vite": "^6.0.7",

View File

@ -187,7 +187,11 @@ const onHandleCommandClick = (path: string) => {
if (action === 'confirm') {
instance.confirmButtonLoading = true;
instance.confirmButtonText = t('message.user.logOutExit');
await getAPI(SysAuthApi).apiSysAuthLogoutPost();
try {
await getAPI(SysAuthApi).apiSysAuthLogoutPost();
} catch (error) {
console.error(error);
}
instance.confirmButtonLoading = false;
done();
} else {

View File

@ -41,7 +41,7 @@
}
"
>
<el-button style="margin: 0px -20px; color: inherit"> 选项 </el-button>
<el-button style="margin: 0 -20px; color: inherit"> 选项 </el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="True"> True </el-dropdown-item>