feat: 框架代码同步 (#173)

Co-authored-by: tk <fiyne1a@dingtalk.com>
This commit is contained in:
2024-08-29 17:21:06 +08:00
committed by GitHub
parent b9b228c9e1
commit c088492cfa
95 changed files with 3055 additions and 2140 deletions

View File

@ -1,3 +1,4 @@
using NetAdmin.Domain.Dto.Dependency;
using NetAdmin.Domain.Dto.Sys.Cache;
namespace NetAdmin.SysComponent.Application.Modules.Sys;
@ -7,11 +8,21 @@ namespace NetAdmin.SysComponent.Application.Modules.Sys;
/// </summary>
public interface ICacheModule
{
/// <summary>
/// 批量删除缓存项
/// </summary>
Task<int> BulkDeleteEntryAsync(BulkReq<DelEntryReq> req);
/// <summary>
/// 缓存统计
/// </summary>
Task<CacheStatisticsRsp> CacheStatisticsAsync();
/// <summary>
/// 删除缓存项
/// </summary>
Task<int> DeleteEntryAsync(DelEntryReq req);
/// <summary>
/// 获取所有缓存项
/// </summary>

View File

@ -7,6 +7,11 @@ namespace NetAdmin.SysComponent.Application.Modules.Sys;
/// </summary>
public interface IToolsModule
{
/// <summary>
/// 执行SQL语句
/// </summary>
Task<object[][]> ExecuteSqlAsync(ExecuteSqlReq req);
/// <summary>
/// 获取更新日志
/// </summary>

View File

@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using NetAdmin.Application.Services;
using NetAdmin.Domain.Dto.Dependency;
using NetAdmin.Domain.Dto.Sys.Cache;
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
using StackExchange.Redis;
@ -21,6 +22,20 @@ public sealed class CacheService(IConnectionMultiplexer connectionMultiplexer) /
_redisInstance = redisOptions.Value.Instances.First(x => x.Name == Chars.FLG_REDIS_INSTANCE_DATA_CACHE);
}
/// <inheritdoc />
public async Task<int> BulkDeleteEntryAsync(BulkReq<DelEntryReq> req)
{
req.ThrowIfInvalid();
var ret = 0;
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var item in req.Items) {
ret += await DeleteEntryAsync(item).ConfigureAwait(false);
}
return ret;
}
/// <inheritdoc />
public async Task<CacheStatisticsRsp> CacheStatisticsAsync()
{
@ -30,6 +45,16 @@ public sealed class CacheService(IConnectionMultiplexer connectionMultiplexer) /
};
}
/// <inheritdoc />
public async Task<int> DeleteEntryAsync(DelEntryReq req)
{
req.ThrowIfInvalid();
#pragma warning disable VSTHRD103
var database = connectionMultiplexer.GetDatabase(_redisInstance.Database);
var delSuccess = await database.KeyDeleteAsync(req.Key).ConfigureAwait(false);
return delSuccess ? 1 : 0;
}
/// <inheritdoc />
public async Task<IEnumerable<GetEntryRsp>> GetAllEntriesAsync(GetAllEntriesReq req)
{

View File

@ -84,7 +84,9 @@ public sealed class ConfigService(BasicRepository<Sys_Config, long> rpo) //
public async Task<QueryConfigRsp> GetAsync(QueryConfigReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryConfigReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
var ret = await QueryInternal(new QueryReq<QueryConfigReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryConfigRsp>();
}

View File

@ -102,7 +102,9 @@ public sealed class DeptService(BasicRepository<Sys_Dept, long> rpo) //
public async Task<QueryDeptRsp> GetAsync(QueryDeptReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryDeptReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
var ret = await QueryInternal(new QueryReq<QueryDeptReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryDeptRsp>();
}

View File

@ -89,7 +89,7 @@ public sealed class DicCatalogService(BasicRepository<Sys_DicCatalog, long> rpo)
public async Task<QueryDicCatalogRsp> GetAsync(QueryDicCatalogReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryDicCatalogReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QueryDicCatalogReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryDicCatalogRsp>();

View File

@ -104,7 +104,7 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
public async Task<QueryDicContentRsp> GetAsync(QueryDicContentReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryDicContentReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QueryDicContentReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryDicContentRsp>();
@ -145,6 +145,9 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
public async Task<List<QueryDicContentRsp>> QueryByCatalogCodeAsync(string catalogCode)
{
var ret = await Rpo.Orm.Select<Sys_DicContent>()
#if DBTYPE_SQLSERVER
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#endif
.Include(a => a.Catalog)
.Where(a => a.Catalog.Code == catalogCode)
.ToListAsync()

View File

@ -73,7 +73,7 @@ public sealed class JobRecordService(BasicRepository<Sys_JobRecord, long> rpo) /
public async Task<QueryJobRecordRsp> GetAsync(QueryJobRecordReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryJobRecordReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QueryJobRecordReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryJobRecordRsp>();

View File

@ -112,9 +112,11 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
}
]
};
var job = await QueryInternal(new QueryReq<QueryJobReq> { Count = 1, Filter = req, DynamicFilter = df })
.ToOneAsync()
.ConfigureAwait(false) ?? throw new NetAdminInvalidOperationException(Ln.);
var job
= await QueryInternal(
new QueryReq<QueryJobReq> { Count = 1, Filter = req, DynamicFilter = df, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false) ?? throw new NetAdminInvalidOperationException(Ln.);
var nextExecTime = GetNextExecTime(Chars.FLG_CRON_PER_SECS);
try {
@ -175,7 +177,9 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
public async Task<QueryJobRsp> GetAsync(QueryJobReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryJobReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
var ret = await QueryInternal(new QueryReq<QueryJobReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryJobRsp>();
}
@ -201,13 +205,26 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
}
]
};
var job = await QueryInternal(new QueryReq<QueryJobReq> { DynamicFilter = df, Order = Orders.Random })
.Take(1)
var job = await QueryInternal(new QueryReq<QueryJobReq> { DynamicFilter = df, Order = Orders.Random }, false)
#if DBTYPE_SQLSERVER
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#endif
.Where(a => !Rpo.Orm.Select<Sys_JobRecord>()
.As("b")
.Where(b => b.JobId == a.Id && b.TimeId == a.NextTimeId)
.Any())
.ToOneAsync()
.ToOneAsync(a => new {
a.RequestUrl
, a.HttpMethod
, a.RequestHeader
, a.RequestBody
, a.RandomDelayBegin
, a.RandomDelayEnd
, a.UserId
, a.Id
, a.NextTimeId
, a.Version
})
.ConfigureAwait(false);
if (job == null) {
return null;
@ -215,15 +232,15 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
#if DBTYPE_SQLSERVER
var ret = await UpdateReturnListAsync( //
job with { Status = JobStatues.Running, LastExecTime = DateTime.Now }
, [nameof(job.Status), nameof(job.LastExecTime)])
job.Adapt<Sys_Job>() with { Status = JobStatues.Running, LastExecTime = DateTime.Now }
, [nameof(Sys_Job.Status), nameof(Sys_Job.LastExecTime)])
.ConfigureAwait(false);
return ret.FirstOrDefault()?.Adapt<QueryJobRsp>();
#else
return await UpdateAsync( //
job with { Status = JobStatues.Running, LastExecTime = DateTime.Now }
, [nameof(job.Status), nameof(job.LastExecTime)])
job.Adapt<Sys_Job>() with { Status = JobStatues.Running, LastExecTime = DateTime.Now }
, [nameof(Sys_Job.Status), nameof(Sys_Job.LastExecTime)])
.ConfigureAwait(false) > 0
? await GetAsync(new QueryJobReq { Id = job.Id }).ConfigureAwait(false)
: null;
@ -330,12 +347,21 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
private ISelect<Sys_Job> QueryInternal(QueryReq<QueryJobReq> req)
{
var ret = Rpo.Select.Include(a => a.User)
.WhereDynamicFilter(req.DynamicFilter)
.WhereDynamic(req.Filter)
.WhereIf( //
req.Keywords?.Length > 0
, a => a.Id == req.Keywords.Int64Try(0) || a.JobName.Contains(req.Keywords));
return QueryInternal(req, true);
}
private ISelect<Sys_Job> QueryInternal(QueryReq<QueryJobReq> req, bool includeUser)
{
var ret = Rpo.Select;
if (includeUser) {
ret = ret.Include(a => a.User);
}
ret = ret.WhereDynamicFilter(req.DynamicFilter)
.WhereDynamic(req.Filter)
.WhereIf( //
req.Keywords?.Length > 0
, a => a.Id == req.Keywords.Int64Try(0) || a.JobName.Contains(req.Keywords));
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
switch (req.Order) {

View File

@ -72,7 +72,7 @@ public sealed class LoginLogService(BasicRepository<Sys_LoginLog, long> rpo) //
public async Task<QueryLoginLogRsp> GetAsync(QueryLoginLogReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryLoginLogReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QueryLoginLogReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryLoginLogRsp>();

View File

@ -88,7 +88,9 @@ public sealed class MenuService(BasicRepository<Sys_Menu, long> rpo, IUserServic
public async Task<QueryMenuRsp> GetAsync(QueryMenuReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryMenuReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
var ret = await QueryInternal(new QueryReq<QueryMenuReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryMenuRsp>();
}

View File

@ -71,7 +71,7 @@ public sealed class RequestLogDetailService(BasicRepository<Sys_RequestLogDetail
public async Task<QueryRequestLogDetailRsp> GetAsync(QueryRequestLogDetailReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryRequestLogDetailReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QueryRequestLogDetailReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryRequestLogDetailRsp>();

View File

@ -99,7 +99,8 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo,
}.Json()
.Object<JsonElement>()
};
var ret = await QueryInternal(new QueryReq<QueryRequestLogReq> { Filter = req, DynamicFilter = df })
var ret = await QueryInternal(
new QueryReq<QueryRequestLogReq> { Filter = req, DynamicFilter = df, Order = Orders.None })
.Include(a => a.Detail)
.ToOneAsync()
.ConfigureAwait(false);

View File

@ -96,7 +96,9 @@ public sealed class RoleService(BasicRepository<Sys_Role, long> rpo) //
public async Task<QueryRoleRsp> GetAsync(QueryRoleReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryRoleReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
var ret = await QueryInternal(new QueryReq<QueryRoleReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryRoleRsp>();
}

View File

@ -71,7 +71,7 @@ public sealed class SiteMsgDeptService(BasicRepository<Sys_SiteMsgDept, long> rp
public async Task<QuerySiteMsgDeptRsp> GetAsync(QuerySiteMsgDeptReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QuerySiteMsgDeptReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QuerySiteMsgDeptReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QuerySiteMsgDeptRsp>();

View File

@ -71,7 +71,7 @@ public sealed class SiteMsgFlagService(BasicRepository<Sys_SiteMsgFlag, long> rp
public async Task<QuerySiteMsgFlagRsp> GetAsync(QuerySiteMsgFlagReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QuerySiteMsgFlagReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QuerySiteMsgFlagReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QuerySiteMsgFlagRsp>();

View File

@ -71,7 +71,7 @@ public sealed class SiteMsgRoleService(BasicRepository<Sys_SiteMsgRole, long> rp
public async Task<QuerySiteMsgRoleRsp> GetAsync(QuerySiteMsgRoleReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QuerySiteMsgRoleReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QuerySiteMsgRoleReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QuerySiteMsgRoleRsp>();

View File

@ -120,7 +120,7 @@ public sealed class SiteMsgService(
public async Task<QuerySiteMsgRsp> GetAsync(QuerySiteMsgReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QuerySiteMsgReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QuerySiteMsgReq> { Filter = req, Order = Orders.None })
.IncludeMany(a => a.Roles)
.IncludeMany(a => a.Users)
.IncludeMany(a => a.Depts)

View File

@ -71,7 +71,7 @@ public sealed class SiteMsgUserService(BasicRepository<Sys_SiteMsgUser, long> rp
public async Task<QuerySiteMsgUserRsp> GetAsync(QuerySiteMsgUserReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QuerySiteMsgUserReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QuerySiteMsgUserReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QuerySiteMsgUserRsp>();

View File

@ -7,6 +7,15 @@ namespace NetAdmin.SysComponent.Application.Services.Sys;
/// <inheritdoc cref="IToolsService" />
public sealed class ToolsService : ServiceBase<IToolsService>, IToolsService
{
/// <inheritdoc />
public Task<object[][]> ExecuteSqlAsync(ExecuteSqlReq req)
{
return App.GetService<IFreeSql>()
.Ado.CommandFluent(req.Sql)
.CommandTimeout(req.TimeoutSecs)
.ExecuteArrayAsync();
}
/// <inheritdoc />
public async Task<string> GetChangeLogAsync()
{

View File

@ -100,7 +100,7 @@ public sealed class UserProfileService(BasicRepository<Sys_UserProfile, long> rp
public async Task<QueryUserProfileRsp> GetAsync(QueryUserProfileReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryUserProfileReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QueryUserProfileReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryUserProfileRsp>();

View File

@ -172,9 +172,9 @@ public sealed class UserService(
public async Task<QueryUserRsp> GetAsync(QueryUserReq req)
{
req.ThrowIfInvalid();
var ret = await (await QueryInternalAsync(new QueryReq<QueryUserReq> { Filter = req }).ConfigureAwait(false))
.ToOneAsync()
.ConfigureAwait(false);
var ret = await (await QueryInternalAsync(new QueryReq<QueryUserReq> { Filter = req, Order = Orders.None })
.ConfigureAwait(false)).ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryUserRsp>();
}
@ -433,14 +433,51 @@ public sealed class UserService(
/// <inheritdoc />
public async Task<UserInfoRsp> UserInfoAsync()
{
static void OtherIncludes(ISelect<Sys_Role> select)
{
select.Where(a => a.Enabled)
#if DBTYPE_SQLSERVER
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#endif
.IncludeMany( //
a => a.Menus
#if DBTYPE_SQLSERVER
#pragma warning disable SA1115
, then => then.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#pragma warning restore SA1115
#endif
#pragma warning disable SA1009, SA1111
)
#pragma warning restore SA1111, SA1009
.IncludeMany( //
a => a.Depts
#if DBTYPE_SQLSERVER
#pragma warning disable SA1115
, then => then.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#pragma warning restore SA1115
#endif
#pragma warning disable SA1009, SA1111
)
#pragma warning restore SA1111, SA1009
.IncludeMany( //
a => a.Apis
#if DBTYPE_SQLSERVER
#pragma warning disable SA1115
, then => then.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#pragma warning restore SA1115
#endif
#pragma warning disable SA1009, SA1111
)
#pragma warning restore SA1111, SA1009
;
}
var dbUser = await Rpo.Where(a => a.Token == UserToken.Token && a.Enabled)
#if DBTYPE_SQLSERVER
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#endif
.Include(a => a.Dept)
.IncludeMany( //
a => a.Roles
, then => then.Where(a => a.Enabled)
.IncludeMany(a => a.Menus)
.IncludeMany(a => a.Depts)
.IncludeMany(a => a.Apis))
.IncludeMany(a => a.Roles, OtherIncludes)
.ToOneAsync()
.ConfigureAwait(false);
return dbUser.Adapt<UserInfoRsp>();

View File

@ -81,7 +81,7 @@ public sealed class VerifyCodeService(BasicRepository<Sys_VerifyCode, long> rpo,
public async Task<QueryVerifyCodeRsp> GetAsync(QueryVerifyCodeReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryVerifyCodeReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QueryVerifyCodeReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryVerifyCodeRsp>();
@ -188,11 +188,10 @@ public sealed class VerifyCodeService(BasicRepository<Sys_VerifyCode, long> rpo,
, Value = destDevice
}
})
#if DBTYPE_SQLSERVER
#if DBTYPE_SQLSERVER
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
#endif
.Take(1)
.ToOneAsync();
#endif
.ToOneAsync();
}
private ISelect<Sys_VerifyCode> QueryInternal(QueryReq<QueryVerifyCodeReq> req)

View File

@ -73,7 +73,7 @@ public sealed class ExampleService(BasicRepository<Tpl_Example, long> rpo) //
public async Task<QueryExampleRsp> GetAsync(QueryExampleReq req)
{
req.ThrowIfInvalid();
var ret = await QueryInternal(new QueryReq<QueryExampleReq> { Filter = req })
var ret = await QueryInternal(new QueryReq<QueryExampleReq> { Filter = req, Order = Orders.None })
.ToOneAsync()
.ConfigureAwait(false);
return ret.Adapt<QueryExampleRsp>();