mirror of
				https://github.com/nsnail/NetAdmin.git
				synced 2025-11-04 13:10:50 +08:00 
			
		
		
		
	feat: ✨ 框架代码同步 (#158)
[skip ci] Co-authored-by: tk <fiyne1a@dingtalk.com>
This commit is contained in:
		@@ -1,3 +1,4 @@
 | 
			
		||||
using Microsoft.IdentityModel.Logging;
 | 
			
		||||
using NetAdmin.AdmServer.Host;
 | 
			
		||||
using NetAdmin.AdmServer.Host.Extensions;
 | 
			
		||||
using NetAdmin.Host.Extensions;
 | 
			
		||||
@@ -78,8 +79,9 @@ namespace NetAdmin.AdmServer.Host
 | 
			
		||||
        public Task<int> Execute(CommandContext context, CommandLineArgs settings)
 | 
			
		||||
            #pragma warning restore ASA001
 | 
			
		||||
        {
 | 
			
		||||
            Args = settings;
 | 
			
		||||
            _    = Serve.Run(RunOptions.Default.WithArgs(context.Remaining.Raw.ToArray()));
 | 
			
		||||
            Args                             = settings;
 | 
			
		||||
            IdentityModelEventSource.ShowPII = true;
 | 
			
		||||
            _                                = Serve.Run(RunOptions.Default.WithArgs(context.Remaining.Raw.ToArray()));
 | 
			
		||||
            return Task.FromResult(0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -979,7 +979,7 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [InlineData(default)]
 | 
			
		||||
    [Theory]
 | 
			
		||||
    public Task<IOrderedEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return default;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1075,7 +1075,7 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [InlineData(default)]
 | 
			
		||||
    [Theory]
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return default;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1083,7 +1083,7 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [InlineData(default)]
 | 
			
		||||
    [Theory]
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return default;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1099,7 +1099,7 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [InlineData(default)]
 | 
			
		||||
    [Theory]
 | 
			
		||||
    public Task<IOrderedEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return default;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1107,8 +1107,7 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [InlineData(default)]
 | 
			
		||||
    [Theory]
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(
 | 
			
		||||
        QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return default;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1116,7 +1115,7 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [InlineData(default)]
 | 
			
		||||
    [Theory]
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return default;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,46 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
 | 
			
		||||
        set => Rpo.DbContextOptions.EnableCascadeSave = value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     导出实体
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    protected async Task<IActionResult> ExportAsync<TQuery, TExport>( //
 | 
			
		||||
        Func<QueryReq<TQuery>, ISelect<TEntity>> selector, QueryReq<TQuery> query, string fileName
 | 
			
		||||
      , Expression<Func<TEntity, object>>        listExp = null)
 | 
			
		||||
        where TQuery : DataAbstraction, new()
 | 
			
		||||
    {
 | 
			
		||||
        var select = selector(query)
 | 
			
		||||
            #if DBTYPE_SQLSERVER
 | 
			
		||||
                     .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
 | 
			
		||||
            #endif
 | 
			
		||||
            .Take(Numbers.MAX_LIMIT_EXPORT);
 | 
			
		||||
 | 
			
		||||
        object list = listExp == null
 | 
			
		||||
            ? await select.ToListAsync().ConfigureAwait(false)
 | 
			
		||||
            : await select.ToListAsync(listExp).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        var listTyped = list.Adapt<List<TExport>>();
 | 
			
		||||
        var stream    = new MemoryStream();
 | 
			
		||||
        var writer    = new StreamWriter(stream);
 | 
			
		||||
        var csv       = new CsvWriter(writer, CultureInfo.InvariantCulture);
 | 
			
		||||
        csv.WriteHeader<TExport>();
 | 
			
		||||
        await csv.NextRecordAsync().ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        foreach (var item in listTyped) {
 | 
			
		||||
            csv.WriteRecord(item);
 | 
			
		||||
            await csv.NextRecordAsync().ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await csv.FlushAsync().ConfigureAwait(false);
 | 
			
		||||
        _ = stream.Seek(0, SeekOrigin.Begin);
 | 
			
		||||
 | 
			
		||||
        App.HttpContext.Response.Headers.ContentDisposition
 | 
			
		||||
            = new ContentDispositionHeaderValue(Chars.FLG_HTTP_HEADER_VALUE_ATTACHMENT) {
 | 
			
		||||
                  FileNameStar = $"{fileName}_{DateTime.Now:yyyy.MM.dd-HH.mm.ss}.csv"
 | 
			
		||||
              }.ToString();
 | 
			
		||||
        return new FileStreamResult(stream, Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_OCTET_STREAM);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     更新实体
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -77,43 +117,6 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
 | 
			
		||||
    }
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     导出实体
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    protected async Task<IActionResult> ExportAsync<TQuery, TExport>( //
 | 
			
		||||
        Func<QueryReq<TQuery>, ISelect<TEntity>> selector, QueryReq<TQuery> query, string fileName)
 | 
			
		||||
        where TQuery : DataAbstraction, new()
 | 
			
		||||
    {
 | 
			
		||||
        var data = await selector(query)
 | 
			
		||||
                         #if DBTYPE_SQLSERVER
 | 
			
		||||
                         .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
 | 
			
		||||
                         #endif
 | 
			
		||||
                         .Take(Numbers.MAX_LIMIT_EXPORT)
 | 
			
		||||
                         .ToListAsync()
 | 
			
		||||
                         .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        var list   = data.Adapt<List<TExport>>();
 | 
			
		||||
        var stream = new MemoryStream();
 | 
			
		||||
        var writer = new StreamWriter(stream);
 | 
			
		||||
        var csv    = new CsvWriter(writer, CultureInfo.InvariantCulture);
 | 
			
		||||
        csv.WriteHeader<TExport>();
 | 
			
		||||
        await csv.NextRecordAsync().ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        foreach (var item in list) {
 | 
			
		||||
            csv.WriteRecord(item);
 | 
			
		||||
            await csv.NextRecordAsync().ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await csv.FlushAsync().ConfigureAwait(false);
 | 
			
		||||
        _ = stream.Seek(0, SeekOrigin.Begin);
 | 
			
		||||
 | 
			
		||||
        App.HttpContext.Response.Headers.ContentDisposition
 | 
			
		||||
            = new ContentDispositionHeaderValue(Chars.FLG_HTTP_HEADER_VALUE_ATTACHMENT) {
 | 
			
		||||
                  FileNameStar = $"{fileName}_{DateTime.Now:yyyy.MM.dd-HH.mm.ss}.csv"
 | 
			
		||||
              }.ToString();
 | 
			
		||||
        return new FileStreamResult(stream, Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_OCTET_STREAM);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private IUpdate<TEntity> BuildUpdate(        //
 | 
			
		||||
        TEntity             entity               //
 | 
			
		||||
      , IEnumerable<string> includeFields        //
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,8 @@ public abstract class DistributedCache<TService>(IDistributedCache cache, TServi
 | 
			
		||||
                                              , TimeSpan? slideLifeTime = null)
 | 
			
		||||
    {
 | 
			
		||||
        var cacheRead = await GetAsync<T>(key).ConfigureAwait(false);
 | 
			
		||||
        if (cacheRead is not null) {
 | 
			
		||||
        if (cacheRead is not null && App.HttpContext?.Request.Headers.CacheControl.FirstOrDefault() !=
 | 
			
		||||
            Chars.FLG_HTTP_HEADER_VALUE_NO_CACHE) {
 | 
			
		||||
            return cacheRead;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,12 @@ namespace NetAdmin.Domain.Contexts;
 | 
			
		||||
/// </summary>
 | 
			
		||||
public sealed record ContextUserToken : DataAbstraction
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     部门编号
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// ReSharper disable once MemberCanBePrivate.Global
 | 
			
		||||
    public long DeptId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     用户编号
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -39,6 +45,8 @@ public sealed record ContextUserToken : DataAbstraction
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static ContextUserToken Create(QueryUserRsp user)
 | 
			
		||||
    {
 | 
			
		||||
        return new ContextUserToken { Id = user.Id, Token = user.Token, UserName = user.UserName };
 | 
			
		||||
        return new ContextUserToken {
 | 
			
		||||
                                        Id = user.Id, Token = user.Token, UserName = user.UserName, DeptId = user.DeptId
 | 
			
		||||
                                    };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,12 @@
 | 
			
		||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     创建者客户端IP字段接口
 | 
			
		||||
/// </summary>
 | 
			
		||||
public interface IFieldCreatedClientIp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     创建者客户端IP
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    int? CreatedClientIp { get; init; }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,15 +1,10 @@
 | 
			
		||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     创建者客户端字段接口
 | 
			
		||||
///     创建者客户端用户代理字段接口
 | 
			
		||||
/// </summary>
 | 
			
		||||
public interface IFieldCreatedClient
 | 
			
		||||
public interface IFieldCreatedClientUserAgent
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     创建者客户端IP
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    int? CreatedClientIp { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     创建者客户端用户代理
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -0,0 +1,12 @@
 | 
			
		||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     修改客户端IP字段接口
 | 
			
		||||
/// </summary>
 | 
			
		||||
public interface IFieldModifiedClientIp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     客户端IP
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    int ModifiedClientIp { get; init; }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,15 +1,10 @@
 | 
			
		||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     修改客户端字段接口
 | 
			
		||||
///     修改客户端用户代理字段接口
 | 
			
		||||
/// </summary>
 | 
			
		||||
public interface IFieldModifiedClient
 | 
			
		||||
public interface IFieldModifiedClientUserAgent
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     客户端IP
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    int ModifiedClientIp { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     客户端用户代理
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -4,6 +4,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
 | 
			
		||||
///     Api接口表
 | 
			
		||||
/// </summary>
 | 
			
		||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_Api))]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(PathCrc32), nameof(PathCrc32), true)]
 | 
			
		||||
public record Sys_Api : ImmutableEntity<string>, IFieldSummary
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -54,6 +55,14 @@ public record Sys_Api : ImmutableEntity<string>, IFieldSummary
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string ParentId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     路径CRC32
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public int PathCrc32 { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     角色集合
 | 
			
		||||
    /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ public record Sys_DicCatalog : VersionEntity
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     字典编码
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string Code { get; init; }
 | 
			
		||||
@@ -34,7 +34,7 @@ public record Sys_DicCatalog : VersionEntity
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     字典名称
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string Name { get; init; }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,6 @@ namespace NetAdmin.Domain.DbMaps.Sys;
 | 
			
		||||
///     字典内容表
 | 
			
		||||
/// </summary>
 | 
			
		||||
[SqlIndex($"{Chars.FLG_DB_INDEX_PREFIX}{nameof(CatalogId)}_{nameof(Key)}", $"{nameof(CatalogId)},{nameof(Key)}", true)]
 | 
			
		||||
[SqlIndex($"{Chars.FLG_DB_INDEX_PREFIX}{nameof(CatalogId)}_{nameof(Value)}", $"{nameof(CatalogId)},{nameof(Value)}"
 | 
			
		||||
        , true)]
 | 
			
		||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_DicContent))]
 | 
			
		||||
public record Sys_DicContent : VersionEntity
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -79,6 +79,22 @@ public record Sys_Job : VersionEntity, IFieldEnabled, IFieldSummary
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual long? NextTimeId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     随机延时起始值(毫秒)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual int? RandomDelayBegin { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     随机延时结束值(毫秒)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual int? RandomDelayEnd { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求体
 | 
			
		||||
    /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
 | 
			
		||||
///     计划作业执行记录表
 | 
			
		||||
/// </summary>
 | 
			
		||||
[SqlIndex($"{Chars.FLG_DB_INDEX_PREFIX}{nameof(JobId)}_{nameof(TimeId)}", $"{nameof(JobId)},{nameof(TimeId)}", true)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(CreatedTime),       nameof(CreatedTime),                 false)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(CreatedTime),       $"{nameof(CreatedTime)} DESC",       false)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(JobId),             nameof(JobId),                       false)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(HttpStatusCode),    nameof(HttpStatusCode),              false)]
 | 
			
		||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_JobRecord))]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,36 +1,38 @@
 | 
			
		||||
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.Domain.DbMaps.Sys;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     请求日志表
 | 
			
		||||
/// </summary>
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(ApiId),          nameof(ApiId),          false)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(CreatedTime),    nameof(CreatedTime),    false)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(UserId),         nameof(UserId),         false)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(HttpStatusCode), nameof(HttpStatusCode), false)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(ApiPathCrc32),   nameof(ApiPathCrc32),          false)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(CreatedTime),    $"{nameof(CreatedTime)} DESC", false)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(OwnerId),        nameof(OwnerId),               false)]
 | 
			
		||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX          + nameof(HttpStatusCode), nameof(HttpStatusCode),        false)]
 | 
			
		||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_RequestLog))]
 | 
			
		||||
public record Sys_RequestLog : SimpleEntity, IFieldCreatedTime, IFieldCreatedClient
 | 
			
		||||
public record Sys_RequestLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFieldCreatedClientIp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     接口
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    [Navigate(nameof(ApiId))]
 | 
			
		||||
    [Navigate(nameof(ApiPathCrc32), TempPrimary = nameof(Sys_Api.PathCrc32))]
 | 
			
		||||
    public Sys_Api Api { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     接口编号
 | 
			
		||||
    ///     接口路径CRC32
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string ApiId { get; init; }
 | 
			
		||||
    public virtual int ApiPathCrc32 { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [Column(Position = -1)]
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public int? CreatedClientIp { get; init; }
 | 
			
		||||
    public virtual int? CreatedClientIp { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [Column(ServerTime = DateTimeKind.Local, CanUpdate = false, Position = -1)]
 | 
			
		||||
@@ -38,161 +40,55 @@ public record Sys_RequestLog : SimpleEntity, IFieldCreatedTime, IFieldCreatedCli
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual DateTime CreatedTime { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_1022)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     明细
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string CreatedUserAgent { get; init; }
 | 
			
		||||
    [Navigate(nameof(Id))]
 | 
			
		||||
    public Sys_RequestLogDetail Detail { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     执行耗时(微秒)
 | 
			
		||||
    ///     执行耗时(毫秒)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual long Duration { get; init; }
 | 
			
		||||
    public virtual int Duration { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     程序响应码
 | 
			
		||||
    ///     请求方法
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_TINY_INT)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual ErrorCodes ErrorCode { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     异常信息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string Exception { get; init; }
 | 
			
		||||
    public virtual HttpMethods HttpMethod { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     HTTP状态码
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_SMALL_INT)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual int HttpStatusCode { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求方法
 | 
			
		||||
    ///     拥有者
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_15)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string Method { get; init; }
 | 
			
		||||
    [Navigate(nameof(OwnerId))]
 | 
			
		||||
    public Sys_User Owner { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求内容
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string RequestBody { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求content-type
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string RequestContentType { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求头信息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string RequestHeaders { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求地址
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string RequestUrl { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     响应内容
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string ResponseBody { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     响应content-type
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string ResponseContentType { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     响应头
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string ResponseHeaders { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     服务器IP
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual int? ServerIp { get; init; }
 | 
			
		||||
    public virtual long? OwnerDeptId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求跟踪标识
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string TraceId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     用户
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    [Navigate(nameof(UserId))]
 | 
			
		||||
    public Sys_User User { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     用户编号
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual long? UserId { get; init; }
 | 
			
		||||
    public virtual long? OwnerId { get; init; }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										132
									
								
								src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLogDetail.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLogDetail.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
			
		||||
namespace NetAdmin.Domain.DbMaps.Sys;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     请求日志明细表
 | 
			
		||||
/// </summary>
 | 
			
		||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_RequestLogDetail))]
 | 
			
		||||
public record Sys_RequestLogDetail : SimpleEntity, IFieldCreatedTime, IFieldCreatedClientUserAgent
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [Column(ServerTime = DateTimeKind.Local, CanUpdate = false, Position = -1)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual DateTime CreatedTime { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_1022)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string CreatedUserAgent { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     程序响应码
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual ErrorCodes ErrorCode { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     异常信息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string Exception { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求内容
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string RequestBody { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求content-type
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string RequestContentType { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求头信息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string RequestHeaders { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求地址
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string RequestUrl { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     响应内容
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string ResponseBody { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     响应content-type
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string ResponseContentType { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     响应头
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    #if DBTYPE_SQLSERVER
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
 | 
			
		||||
    #else
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
 | 
			
		||||
    #endif
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string ResponseHeaders { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     服务器IP
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual int? ServerIp { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     请求跟踪标识
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    [JsonIgnore]
 | 
			
		||||
    public virtual string TraceId { get; init; }
 | 
			
		||||
}
 | 
			
		||||
@@ -37,6 +37,42 @@ public sealed record DynamicFilterInfo : DataAbstraction
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static implicit operator FreeSql.Internal.Model.DynamicFilterInfo(DynamicFilterInfo d)
 | 
			
		||||
    {
 | 
			
		||||
        return d.Adapt<FreeSql.Internal.Model.DynamicFilterInfo>();
 | 
			
		||||
        var ret = d.Adapt<FreeSql.Internal.Model.DynamicFilterInfo>();
 | 
			
		||||
        ProcessDynamicFilter(ret);
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void ProcessDynamicFilter(FreeSql.Internal.Model.DynamicFilterInfo d)
 | 
			
		||||
    {
 | 
			
		||||
        if (d?.Filters != null) {
 | 
			
		||||
            foreach (var filterInfo in d.Filters) {
 | 
			
		||||
                ProcessDynamicFilter(filterInfo);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (d?.Operator != DynamicFilterOperator.DateRange) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var values = ((JsonElement)d.Value).Deserialize<string[]>();
 | 
			
		||||
        if (!DateTime.TryParse(values[0], CultureInfo.InvariantCulture, out _)) {
 | 
			
		||||
            var result = values[0]
 | 
			
		||||
                         .ExecuteCSharpCodeAsync<DateTime>([typeof(DateTime).Assembly], nameof(System))
 | 
			
		||||
                         .ConfigureAwait(false)
 | 
			
		||||
                         .GetAwaiter()
 | 
			
		||||
                         .GetResult();
 | 
			
		||||
            values[0] = $"{result:yyyy-MM-dd HH:mm:ss}";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!DateTime.TryParse(values[1], CultureInfo.InvariantCulture, out _)) {
 | 
			
		||||
            var result = values[1]
 | 
			
		||||
                         .ExecuteCSharpCodeAsync<DateTime>([typeof(DateTime).Assembly], nameof(System))
 | 
			
		||||
                         .ConfigureAwait(false)
 | 
			
		||||
                         .GetAwaiter()
 | 
			
		||||
                         .GetResult();
 | 
			
		||||
            values[1] = $"{result:yyyy-MM-dd HH:mm:ss}";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        d.Value = values;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -32,6 +32,14 @@ public record CreateJobReq : Sys_Job
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public override long? NextTimeId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [Range(1, int.MaxValue, ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.随机延时起始时间不正确))]
 | 
			
		||||
    public override int? RandomDelayBegin { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [Range(1, int.MaxValue, ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.随机延时结束时间不正确))]
 | 
			
		||||
    public override int? RandomDelayEnd { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_Job.RequestBody" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string RequestBody { get; init; }
 | 
			
		||||
 
 | 
			
		||||
@@ -90,6 +90,14 @@ public record QueryJobRsp : Sys_Job
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override long? NextTimeId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override int? RandomDelayBegin { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override int? RandomDelayEnd { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_Job.RequestBody" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string RequestBody { get; init; }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,12 @@
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.RequestLogDetail;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.Domain.Dto.Sys.RequestLog;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     请求:创建请求日志
 | 
			
		||||
/// </summary>
 | 
			
		||||
public sealed record CreateRequestLogReq : Sys_RequestLog;
 | 
			
		||||
public sealed record CreateRequestLogReq : Sys_RequestLog
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.Detail" />
 | 
			
		||||
    public new CreateRequestLogDetailReq Detail { get; init; }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,7 @@
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.Api;
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.RequestLogDetail;
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.User;
 | 
			
		||||
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.Domain.Dto.Sys.RequestLog;
 | 
			
		||||
 | 
			
		||||
@@ -7,39 +10,51 @@ namespace NetAdmin.Domain.Dto.Sys.RequestLog;
 | 
			
		||||
/// </summary>
 | 
			
		||||
public record ExportRequestLogRsp : QueryRequestLogRsp
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     接口路径
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [CsvIndex(2)]
 | 
			
		||||
    [JsonInclude]
 | 
			
		||||
    [Name(nameof(Ln.接口路径))]
 | 
			
		||||
    public string ApiId => Api.Id;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [CsvIndex(6)]
 | 
			
		||||
    [Ignore(false)]
 | 
			
		||||
    [Name(nameof(Ln.客户端IP))]
 | 
			
		||||
    public override string CreatedClientIp => base.CreatedClientIp;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     用户名
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [CsvIndex(5)]
 | 
			
		||||
    [JsonInclude]
 | 
			
		||||
    [Name(nameof(Ln.用户名))]
 | 
			
		||||
    public string UserName => Owner?.UserName;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    public override string LoginName => base.LoginName;
 | 
			
		||||
    public override QueryApiRsp Api { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [CsvIndex(7)]
 | 
			
		||||
    [Ignore(false)]
 | 
			
		||||
    [Name(nameof(Ln.操作系统))]
 | 
			
		||||
    public override string Os => base.Os;
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    public override DateTime CreatedTime { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [CsvIndex(2)]
 | 
			
		||||
    [Ignore(false)]
 | 
			
		||||
    [Name(nameof(Ln.接口路径))]
 | 
			
		||||
    public override string ApiId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [CsvIndex(8)]
 | 
			
		||||
    [Ignore(false)]
 | 
			
		||||
    [Name(nameof(Ln.用户代理))]
 | 
			
		||||
    public override string CreatedUserAgent { get; init; }
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    public override QueryRequestLogDetailRsp Detail { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [CsvIndex(4)]
 | 
			
		||||
    [Ignore(false)]
 | 
			
		||||
    [Name(nameof(Ln.执行耗时))]
 | 
			
		||||
    public override long Duration { get; init; }
 | 
			
		||||
    public override int Duration { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [CsvIndex(3)]
 | 
			
		||||
    [Ignore(false)]
 | 
			
		||||
    [Name(nameof(Ln.请求方式))]
 | 
			
		||||
    public override HttpMethods HttpMethod { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [CsvIndex(1)]
 | 
			
		||||
@@ -54,32 +69,14 @@ public record ExportRequestLogRsp : QueryRequestLogRsp
 | 
			
		||||
    public override long Id { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [CsvIndex(3)]
 | 
			
		||||
    [Ignore(false)]
 | 
			
		||||
    [Name(nameof(Ln.请求方式))]
 | 
			
		||||
    public override string Method { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [CsvIndex(9)]
 | 
			
		||||
    [Ignore(false)]
 | 
			
		||||
    [Name(nameof(Ln.跟踪编号))]
 | 
			
		||||
    public override string TraceId { get; init; }
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    public override QueryUserLiteRsp Owner { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    public override QueryUserRsp User { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     用户名
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [CsvIndex(5)]
 | 
			
		||||
    [Ignore(false)]
 | 
			
		||||
    [Name(nameof(Ln.用户名))]
 | 
			
		||||
    public string UserName { get; init; }
 | 
			
		||||
    public override long? OwnerDeptId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public override void Register(TypeAdapterConfig config)
 | 
			
		||||
    {
 | 
			
		||||
        _ = config.ForType<Sys_RequestLog, ExportRequestLogRsp>().Map(d => d.UserName, s => s.User.UserName);
 | 
			
		||||
    }
 | 
			
		||||
    [Ignore]
 | 
			
		||||
    public override long? OwnerId { get; init; }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,11 +1,14 @@
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.Api;
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.RequestLogDetail;
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.User;
 | 
			
		||||
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.Domain.Dto.Sys.RequestLog;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     响应:查询请求日志
 | 
			
		||||
/// </summary>
 | 
			
		||||
public record QueryRequestLogRsp : Sys_RequestLog, IRegister
 | 
			
		||||
public record QueryRequestLogRsp : Sys_RequestLog
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     创建者客户端IP
 | 
			
		||||
@@ -13,101 +16,39 @@ public record QueryRequestLogRsp : Sys_RequestLog, IRegister
 | 
			
		||||
    [JsonInclude]
 | 
			
		||||
    public new virtual string CreatedClientIp => base.CreatedClientIp?.ToIpV4();
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     登录名
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [JsonInclude]
 | 
			
		||||
    public virtual string LoginName => RequestBody?.ToObject<LoginByPwdReq>()?.Account;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     操作系统
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [JsonInclude]
 | 
			
		||||
    public virtual string Os => UserAgentParser.Create(CreatedUserAgent)?.Platform;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.ApiId" />
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.Api" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string ApiId { get; init; }
 | 
			
		||||
    public new virtual QueryApiRsp Api { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     接口描述
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string ApiSummary { get; init; }
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.ApiPathCrc32" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
 | 
			
		||||
    public override int ApiPathCrc32 { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
 | 
			
		||||
    public override DateTime CreatedTime { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.CreatedUserAgent" />
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.Detail" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string CreatedUserAgent { get; init; }
 | 
			
		||||
    public new virtual QueryRequestLogDetailRsp Detail { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.Duration" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
 | 
			
		||||
    public override long Duration { get; init; }
 | 
			
		||||
    public override int Duration { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.ErrorCode" />
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.HttpMethod" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
 | 
			
		||||
    public override ErrorCodes ErrorCode { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.Exception" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string Exception { get; init; }
 | 
			
		||||
    public override HttpMethods HttpMethod { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.HttpStatusCode" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
 | 
			
		||||
    public override int HttpStatusCode { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.Method" />
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.Owner" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string Method { get; init; }
 | 
			
		||||
    public new virtual QueryUserLiteRsp Owner { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.RequestBody" />
 | 
			
		||||
    /// <inheritdoc cref="IFieldOwner.OwnerId" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string RequestBody { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.RequestContentType" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string RequestContentType { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.RequestHeaders" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string RequestHeaders { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.RequestUrl" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string RequestUrl { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.ResponseBody" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string ResponseBody { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.ResponseContentType" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string ResponseContentType { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.ResponseHeaders" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string ResponseHeaders { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.ServerIp" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override int? ServerIp { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.TraceId" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string TraceId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.User" />
 | 
			
		||||
    public new virtual QueryUserRsp User { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLog.UserId" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override long? UserId { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public virtual void Register(TypeAdapterConfig config)
 | 
			
		||||
    {
 | 
			
		||||
        _ = config.ForType<Sys_RequestLog, QueryRequestLogRsp>().Map(d => d.ApiSummary, s => s.Api.Summary);
 | 
			
		||||
    }
 | 
			
		||||
    public override long? OwnerId { get; init; }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
namespace NetAdmin.Domain.Dto.Sys.RequestLogDetail;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     请求:创建请求日志明细
 | 
			
		||||
/// </summary>
 | 
			
		||||
public record CreateRequestLogDetailReq : Sys_RequestLogDetail;
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
namespace NetAdmin.Domain.Dto.Sys.RequestLogDetail;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     请求:查询请求日志明细
 | 
			
		||||
/// </summary>
 | 
			
		||||
public sealed record QueryRequestLogDetailReq : Sys_RequestLogDetail
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc cref="EntityBase{T}.Id" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
 | 
			
		||||
    public override long Id { get; init; }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,73 @@
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.User;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.Domain.Dto.Sys.RequestLogDetail;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     响应:查询请求日志明细
 | 
			
		||||
/// </summary>
 | 
			
		||||
public sealed record QueryRequestLogDetailRsp : Sys_RequestLogDetail
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     登录名
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [JsonInclude]
 | 
			
		||||
    public string LoginName => RequestBody?.ToObject<LoginByPwdReq>()?.Account;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     操作系统
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [JsonInclude]
 | 
			
		||||
    public string Os => UserAgentParser.Create(CreatedUserAgent)?.Platform;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="IFieldCreatedClientUserAgent.CreatedUserAgent" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string CreatedUserAgent { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.ErrorCode" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
 | 
			
		||||
    public override ErrorCodes ErrorCode { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.Exception" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string Exception { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="EntityBase{T}.Id" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
 | 
			
		||||
    public override long Id { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.RequestBody" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string RequestBody { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.RequestContentType" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string RequestContentType { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.RequestHeaders" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string RequestHeaders { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.RequestUrl" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string RequestUrl { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.ResponseBody" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string ResponseBody { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.ResponseContentType" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string ResponseContentType { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.ResponseHeaders" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string ResponseHeaders { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.ServerIp" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override int? ServerIp { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_RequestLogDetail.TraceId" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string TraceId { get; init; }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								src/backend/NetAdmin.Domain/Dto/Sys/User/QueryUserLiteRsp.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/backend/NetAdmin.Domain/Dto/Sys/User/QueryUserLiteRsp.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
namespace NetAdmin.Domain.Dto.Sys.User;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     响应:查询用户精简版
 | 
			
		||||
/// </summary>
 | 
			
		||||
public record QueryUserLiteRsp : Sys_User
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc cref="EntityBase{T}.Id" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
 | 
			
		||||
    public override long Id { get; init; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="Sys_User.UserName" />
 | 
			
		||||
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 | 
			
		||||
    public override string UserName { get; init; }
 | 
			
		||||
}
 | 
			
		||||
@@ -11,20 +11,19 @@ public sealed record SqlCommandAfterEvent : SqlCommandBeforeEvent
 | 
			
		||||
    public SqlCommandAfterEvent(CommandAfterEventArgs e) //
 | 
			
		||||
        : base(e)
 | 
			
		||||
    {
 | 
			
		||||
        ElapsedMicroseconds = (long)((double)e.ElapsedTicks / Stopwatch.Frequency * 1_000_000);
 | 
			
		||||
        ElapsedMilliseconds = (long)((double)e.ElapsedTicks / Stopwatch.Frequency * 1_000);
 | 
			
		||||
        EventId             = nameof(SqlCommandAfterEvent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     耗时(单位:微秒)
 | 
			
		||||
    ///     耗时(单位:毫秒)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// de
 | 
			
		||||
    private long ElapsedMicroseconds { get; }
 | 
			
		||||
    private long ElapsedMilliseconds { get; }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public override string ToString()
 | 
			
		||||
    {
 | 
			
		||||
        return string.Format(CultureInfo.InvariantCulture, "SQL-{0}: {2} ms {1}", Id
 | 
			
		||||
                           , Sql?.Sub(0, Numbers.MAX_LIMIT_PRINT_LEN_SQL), ElapsedMicroseconds / 1000);
 | 
			
		||||
        return string.Format(CultureInfo.InvariantCulture, "SQL-{0}: {2} ms {1}", Id, Sql, ElapsedMilliseconds);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
        <ProjectReference Include="../NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj"/>
 | 
			
		||||
    </ItemGroup>
 | 
			
		||||
    <ItemGroup>
 | 
			
		||||
        <PackageReference Include="CronExpressionDescriptor" Version="2.34.0"/>
 | 
			
		||||
        <PackageReference Include="CronExpressionDescriptor" Version="2.36.0"/>
 | 
			
		||||
        <PackageReference Include="Cronos" Version="0.8.4"/>
 | 
			
		||||
        <PackageReference Include="CsvHelper.NS" Version="33.0.2-ns2"/>
 | 
			
		||||
        <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0-preview.6.24328.4"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -35,20 +35,15 @@ public abstract class WorkBase<TLogger>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    protected UnitOfWorkManager UowManager { get; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     获取锁
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    protected Task<IRedLock> GetLockerAsync(string lockId)
 | 
			
		||||
    {
 | 
			
		||||
        return _redLocker.RedLockFactory.CreateLockAsync(lockId, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_EXPIRY)
 | 
			
		||||
                                                       , TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_WAIT)
 | 
			
		||||
                                                       , TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_RETRY));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     通用工作流
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    protected abstract ValueTask WorkflowAsync(CancellationToken cancelToken);
 | 
			
		||||
    protected abstract ValueTask WorkflowAsync( //
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once UnusedParameter.Global
 | 
			
		||||
        #pragma warning disable SA1114
 | 
			
		||||
        CancellationToken cancelToken);
 | 
			
		||||
    #pragma warning restore SA1114
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     通用工作流
 | 
			
		||||
@@ -69,4 +64,14 @@ public abstract class WorkBase<TLogger>
 | 
			
		||||
 | 
			
		||||
        await WorkflowAsync(cancelToken).ConfigureAwait(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     获取锁
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    private Task<IRedLock> GetLockerAsync(string lockId)
 | 
			
		||||
    {
 | 
			
		||||
        return _redLocker.RedLockFactory.CreateLockAsync(lockId, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_EXPIRY)
 | 
			
		||||
                                                       , TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_WAIT)
 | 
			
		||||
                                                       , TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_RETRY));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -58,7 +58,7 @@ public sealed class RequestAuditMiddleware(
 | 
			
		||||
                               .FirstOrDefault()
 | 
			
		||||
                               ?.Enum<ErrorCodes>() ?? 0;
 | 
			
		||||
 | 
			
		||||
        _ = await requestLogger.LogAsync(context, (long)sw.Elapsed.TotalMicroseconds, responseBody, errorCode
 | 
			
		||||
        _ = await requestLogger.LogAsync(context, (long)sw.Elapsed.TotalMilliseconds, responseBody, errorCode
 | 
			
		||||
                                       , exception)
 | 
			
		||||
                               .ConfigureAwait(false);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
    </ItemGroup>
 | 
			
		||||
    <ItemGroup>
 | 
			
		||||
        <PackageReference Include="IGeekFan.AspNetCore.Knife4jUI.NS" Condition="'$(Configuration)' == 'Debug'" Version="0.0.15-ns2"/>
 | 
			
		||||
        <PackageReference Include="Spectre.Console.Cli.NS" Version="0.45.1-preview.0.161"/>
 | 
			
		||||
        <PackageReference Include="Spectre.Console.Cli.NS" Version="0.45.1-preview.0.179"/>
 | 
			
		||||
        <PackageReference Include="prometheus-net.AspNetCore" Condition="'$(Configuration)' != 'Debug'" Version="8.2.1"/>
 | 
			
		||||
    </ItemGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
using NetAdmin.Domain.Contexts;
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.RequestLog;
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.RequestLogDetail;
 | 
			
		||||
using NetAdmin.Domain.Events.Sys;
 | 
			
		||||
using Yitter.IdGenerator;
 | 
			
		||||
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.Host.Utils;
 | 
			
		||||
 | 
			
		||||
@@ -19,36 +22,39 @@ public sealed class RequestLogger(ILogger<RequestLogger> logger, IEventPublisher
 | 
			
		||||
    {
 | 
			
		||||
        // 从请求头中读取用户信息
 | 
			
		||||
        var associatedUser = GetAssociatedUser(context);
 | 
			
		||||
        var auditData = new CreateRequestLogReq {
 | 
			
		||||
                                                    Duration           = duration
 | 
			
		||||
                                                  , Method             = context.Request.Method
 | 
			
		||||
                                                  , RequestContentType = context.Request.ContentType
 | 
			
		||||
                                                  , RequestBody = Array.Exists( //
 | 
			
		||||
                                                        _textContentTypes
 | 
			
		||||
                                                      , x => context.Request.ContentType?.Contains(
 | 
			
		||||
                                                            x, StringComparison.OrdinalIgnoreCase) ?? false)
 | 
			
		||||
                                                        ? (await context.ReadBodyContentAsync().ConfigureAwait(false))
 | 
			
		||||
                                                        ?.Sub(0, Numbers.MAX_LIMIT_PRINT_LEN_CONTENT)
 | 
			
		||||
                                                        : string.Empty
 | 
			
		||||
                                                  , RequestUrl = context.Request.GetRequestUrlAddress()
 | 
			
		||||
                                                  , ResponseBody
 | 
			
		||||
                                                        = responseBody?.Sub(0, Numbers.MAX_LIMIT_PRINT_LEN_CONTENT)
 | 
			
		||||
                                                  , ServerIp = context.GetLocalIpAddressToIPv4()?.IpV4ToInt32()
 | 
			
		||||
                                                  , ApiId = context.Request.Path.Value?.TrimStart('/')
 | 
			
		||||
                                                  , RequestHeaders = context.Request.Headers.Json()
 | 
			
		||||
                                                  , ResponseContentType = context.Response.ContentType
 | 
			
		||||
                                                  , ResponseHeaders = context.Response.Headers.Json()
 | 
			
		||||
                                                  , HttpStatusCode = context.Response.StatusCode
 | 
			
		||||
                                                  , ErrorCode = errorCode
 | 
			
		||||
                                                  , Exception = exception?.Error.ToString()
 | 
			
		||||
                                                  , UserId = associatedUser?.UserId
 | 
			
		||||
                                                  , CreatedUserAgent = context.Request.Headers.UserAgent.ToString()
 | 
			
		||||
                                                  , CreatedClientIp = context.GetRealIpAddress()
 | 
			
		||||
                                                                             ?.MapToIPv4()
 | 
			
		||||
                                                                             .ToString()
 | 
			
		||||
                                                                             .IpV4ToInt32()
 | 
			
		||||
                                                  , TraceId = context.TraceIdentifier
 | 
			
		||||
                                                };
 | 
			
		||||
        var id             = YitIdHelper.NextId();
 | 
			
		||||
        var requestBody = Array.Exists( //
 | 
			
		||||
            _textContentTypes
 | 
			
		||||
          , x => context.Request.ContentType?.Contains(x, StringComparison.OrdinalIgnoreCase) ?? false)
 | 
			
		||||
            ? await context.ReadBodyContentAsync().ConfigureAwait(false)
 | 
			
		||||
            : string.Empty;
 | 
			
		||||
        var auditData = new CreateRequestLogReq //
 | 
			
		||||
                        {
 | 
			
		||||
                            Detail = new CreateRequestLogDetailReq //
 | 
			
		||||
                                     {
 | 
			
		||||
                                         Id                  = id
 | 
			
		||||
                                       , CreatedUserAgent    = context.Request.Headers.UserAgent.ToString()
 | 
			
		||||
                                       , ErrorCode           = errorCode
 | 
			
		||||
                                       , Exception           = exception?.Error.ToString()
 | 
			
		||||
                                       , RequestBody         = requestBody
 | 
			
		||||
                                       , RequestContentType  = context.Request.ContentType
 | 
			
		||||
                                       , RequestHeaders      = context.Request.Headers.Json()
 | 
			
		||||
                                       , RequestUrl          = context.Request.GetRequestUrlAddress()
 | 
			
		||||
                                       , ResponseBody        = responseBody
 | 
			
		||||
                                       , ResponseContentType = context.Response.ContentType
 | 
			
		||||
                                       , ResponseHeaders     = context.Response.Headers.Json()
 | 
			
		||||
                                       , ServerIp            = context.GetLocalIpAddressToIPv4()?.IpV4ToInt32()
 | 
			
		||||
                                       , TraceId             = context.TraceIdentifier
 | 
			
		||||
                                     }
 | 
			
		||||
                          , Duration        = (int)duration
 | 
			
		||||
                          , HttpMethod      = Enum.Parse<HttpMethods>(context.Request.Method, true)
 | 
			
		||||
                          , ApiPathCrc32    = context.Request.Path.Value!.TrimStart('/').Crc32()
 | 
			
		||||
                          , HttpStatusCode  = context.Response.StatusCode
 | 
			
		||||
                          , CreatedClientIp = context.GetRealIpAddress()?.MapToIPv4().ToString().IpV4ToInt32()
 | 
			
		||||
                          , OwnerId         = associatedUser?.UserId
 | 
			
		||||
                          , OwnerDeptId     = associatedUser?.DeptId
 | 
			
		||||
                          , Id              = id
 | 
			
		||||
                        };
 | 
			
		||||
 | 
			
		||||
        // 打印日志
 | 
			
		||||
        logger.Info(auditData);
 | 
			
		||||
@@ -59,7 +65,7 @@ public sealed class RequestLogger(ILogger<RequestLogger> logger, IEventPublisher
 | 
			
		||||
        return auditData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private (long UserId, string UserName)? GetAssociatedUser(HttpContext context)
 | 
			
		||||
    private (long UserId, long DeptId, string UserName)? GetAssociatedUser(HttpContext context)
 | 
			
		||||
    {
 | 
			
		||||
        var token = context.Request.Headers.Authorization.FirstOrDefault();
 | 
			
		||||
        if (token == null) {
 | 
			
		||||
@@ -69,7 +75,7 @@ public sealed class RequestLogger(ILogger<RequestLogger> logger, IEventPublisher
 | 
			
		||||
        ContextUserToken userToken = null;
 | 
			
		||||
        try {
 | 
			
		||||
            var jsonWebToken
 | 
			
		||||
                = JWTEncryption.ReadJwtToken(token.TrimStart($"{Chars.FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA} "));
 | 
			
		||||
                = JWTEncryption.ReadJwtToken(token.TrimPrefix($"{Chars.FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA} "));
 | 
			
		||||
            var claim = jsonWebToken?.Claims.FirstOrDefault(y => y.Type == nameof(ContextUserToken));
 | 
			
		||||
            userToken = claim?.Value.ToObject<ContextUserToken>();
 | 
			
		||||
        }
 | 
			
		||||
@@ -77,6 +83,6 @@ public sealed class RequestLogger(ILogger<RequestLogger> logger, IEventPublisher
 | 
			
		||||
            logger.Warn($"{Ln.读取用户令牌出错}: {ex}");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return userToken == null ? null : (userToken.Id, userToken.UserName);
 | 
			
		||||
        return userToken == null ? null : (userToken.Id, userToken.DeptId, userToken.UserName);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -104,10 +104,10 @@ public sealed class SqlAuditor : ISingleton
 | 
			
		||||
            case nameof(IFieldCreatedUser.CreatedUserName):
 | 
			
		||||
                SetCreatedUserName(e, userInfo);
 | 
			
		||||
                break;
 | 
			
		||||
            case nameof(IFieldCreatedClient.CreatedClientIp):
 | 
			
		||||
            case nameof(IFieldCreatedClientIp.CreatedClientIp):
 | 
			
		||||
                SetCreatedClientIp(e);
 | 
			
		||||
                break;
 | 
			
		||||
            case nameof(IFieldCreatedClient.CreatedUserAgent):
 | 
			
		||||
            case nameof(IFieldCreatedClientUserAgent.CreatedUserAgent):
 | 
			
		||||
                SetCreatedUserAgent(e);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@ public static class Chars
 | 
			
		||||
    public const string FLG_DB_FIELD_TYPE_NVARCHAR_MAX                 = "nvarchar(max)";
 | 
			
		||||
    public const string FLG_DB_FIELD_TYPE_SMALL_INT                    = "smallint";
 | 
			
		||||
    public const string FLG_DB_FIELD_TYPE_TEXT                         = "text";
 | 
			
		||||
    public const string FLG_DB_FIELD_TYPE_TINY_INT                     = "tinyint";
 | 
			
		||||
    public const string FLG_DB_FIELD_TYPE_VARCHAR                      = "varchar";
 | 
			
		||||
    public const string FLG_DB_FIELD_TYPE_VARCHAR_1022                 = "varchar(1022)";
 | 
			
		||||
    public const string FLG_DB_FIELD_TYPE_VARCHAR_127                  = "varchar(127)";
 | 
			
		||||
@@ -54,6 +55,7 @@ public static class Chars
 | 
			
		||||
    public const string FLG_HTTP_HEADER_KEY_USER_AGENT                 = "User-Agent";
 | 
			
		||||
    public const string FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN             = "X-ACCESS-TOKEN";
 | 
			
		||||
    public const string FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN_HEADER_KEY  = "X-Authorization";
 | 
			
		||||
    public const string FLG_HTTP_HEADER_KEY_X_CACHE_CONTROL            = "X-Cache-Control";
 | 
			
		||||
    public const string FLG_HTTP_HEADER_KEY_X_FORWARDED_FOR            = "X-Forwarded-For";
 | 
			
		||||
    public const string FLG_HTTP_HEADER_KEY_X_REAL_IP                  = "X-Real-IP";
 | 
			
		||||
    public const string FLG_HTTP_HEADER_VALUE_APPLICATION_JSON         = "application/json";
 | 
			
		||||
@@ -61,6 +63,7 @@ public static class Chars
 | 
			
		||||
    public const string FLG_HTTP_HEADER_VALUE_APPLICATION_URLENCODED   = "application/x-www-form-urlencoded";
 | 
			
		||||
    public const string FLG_HTTP_HEADER_VALUE_ATTACHMENT               = "attachment";
 | 
			
		||||
    public const string FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA              = "Bearer";
 | 
			
		||||
    public const string FLG_HTTP_HEADER_VALUE_NO_CACHE                 = "no-cache";
 | 
			
		||||
    public const string FLG_HTTP_METHOD_CONNECT                        = "CONNECT";
 | 
			
		||||
    public const string FLG_HTTP_METHOD_DELETE                         = "DELETE";
 | 
			
		||||
    public const string FLG_HTTP_METHOD_GET                            = "GET";
 | 
			
		||||
 
 | 
			
		||||
@@ -30,5 +30,6 @@ public static class Numbers
 | 
			
		||||
    public const int SECS_RED_LOCK_EXPIRY        = 30;  // 秒:RedLock-锁过期时间,假如持有锁的进程挂掉,最多在此时间内锁将被释放(如持有锁的进程正常,此值不会生效)
 | 
			
		||||
    public const int SECS_RED_LOCK_RETRY         = 1;   // 秒:RedLock-锁等待时间内,多久尝试获取一次
 | 
			
		||||
    public const int SECS_RED_LOCK_WAIT          = 10;  // 秒:RedLock-锁等待时间,相同的 resource 如果当前的锁被其他线程占用,最多等待时间
 | 
			
		||||
    public const int SECS_TIMEOUT_HTTP_CLIENT    = 15;  // 秒:超时时间-默认HTTP客户端
 | 
			
		||||
    public const int SECS_TIMEOUT_JOB            = 600; // 秒:超时时间-作业
 | 
			
		||||
}
 | 
			
		||||
@@ -10,8 +10,7 @@ public static class HttpRequestMessageExtensions
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static async Task<HttpRequestMessage> LogAsync<T>(this HttpRequestMessage me, ILogger<T> logger)
 | 
			
		||||
    {
 | 
			
		||||
        logger.Info(
 | 
			
		||||
            $"HTTP Request {(await me.BuildJsonAsync().ConfigureAwait(false))?.Sub(0, Numbers.MAX_LIMIT_PRINT_LEN_CONTENT)}");
 | 
			
		||||
        logger.Info($"HTTP Request {await me.BuildJsonAsync().ConfigureAwait(false)}");
 | 
			
		||||
        return me;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,8 +11,7 @@ public static class HttpResponseMessageExtensions
 | 
			
		||||
    public static async Task LogAsync<T>(this HttpResponseMessage me, ILogger<T> logger
 | 
			
		||||
                                       , Func<string, string>     bodyPreHandle = null)
 | 
			
		||||
    {
 | 
			
		||||
        logger.Info($"HTTP Response {(await me.BuildJsonAsync(bodyPreHandle).ConfigureAwait(false))?.Sub(
 | 
			
		||||
            0, Numbers.MAX_LIMIT_PRINT_LEN_CONTENT)}");
 | 
			
		||||
        logger.Info($"HTTP Response {await me.BuildJsonAsync(bodyPreHandle).ConfigureAwait(false)}");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -21,8 +20,7 @@ public static class HttpResponseMessageExtensions
 | 
			
		||||
    public static async Task LogExceptionAsync<T>(this HttpResponseMessage me, string errors, ILogger<T> logger
 | 
			
		||||
                                                , Func<string, string>     bodyHandle = null)
 | 
			
		||||
    {
 | 
			
		||||
        logger.Warn(
 | 
			
		||||
            $"{errors}: {(await me.BuildJsonAsync(bodyHandle).ConfigureAwait(false))?.Sub(0, Numbers.MAX_LIMIT_PRINT_LEN_CONTENT)}");
 | 
			
		||||
        logger.Warn($"{errors}: {await me.BuildJsonAsync(bodyHandle).ConfigureAwait(false)}");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
using Microsoft.CodeAnalysis.CSharp.Scripting;
 | 
			
		||||
using Microsoft.CodeAnalysis.Scripting;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.Infrastructure.Extensions;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -5,8 +8,24 @@ namespace NetAdmin.Infrastructure.Extensions;
 | 
			
		||||
/// </summary>
 | 
			
		||||
public static class StringExtensions
 | 
			
		||||
{
 | 
			
		||||
    private static readonly Regex _regex  = new("Options$");
 | 
			
		||||
    private static readonly Regex _regex2 = new("Async$");
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     计算Crc32
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static int Crc32(this string me)
 | 
			
		||||
    {
 | 
			
		||||
        return BitConverter.ToInt32(System.IO.Hashing.Crc32.Hash(Encoding.UTF8.GetBytes(me)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     执行C#代码
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static Task<T> ExecuteCSharpCodeAsync<T>(this   string   me, Assembly[] assemblies
 | 
			
		||||
                                                  , params string[] importNamespaces)
 | 
			
		||||
    {
 | 
			
		||||
        // 使用 Roslyn 编译并执行代码
 | 
			
		||||
        return CSharpScript.EvaluateAsync<T>(
 | 
			
		||||
            me, ScriptOptions.Default.WithReferences(assemblies).WithImports(importNamespaces));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     object -> json
 | 
			
		||||
@@ -31,7 +50,7 @@ public static class StringExtensions
 | 
			
		||||
    public static string TrimEndAsync(this string me)
 | 
			
		||||
        #pragma warning restore VSTHRD200, ASA002, RCS1047
 | 
			
		||||
    {
 | 
			
		||||
        return _regex2.Replace(me, string.Empty);
 | 
			
		||||
        return TrimSuffix(me, "Async");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -39,14 +58,22 @@ public static class StringExtensions
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static string TrimEndOptions(this string me)
 | 
			
		||||
    {
 | 
			
		||||
        return _regex.Replace(me, string.Empty);
 | 
			
		||||
        return TrimSuffix(me, "Options");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     去掉前部字符串
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static string TrimStart(this string me, string clearStr)
 | 
			
		||||
    public static string TrimPrefix(this string me, string clearStr)
 | 
			
		||||
    {
 | 
			
		||||
        return Regex.Replace(me, $"^{clearStr}", string.Empty);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     去掉尾部字符串
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static string TrimSuffix(this string me, string clearStr)
 | 
			
		||||
    {
 | 
			
		||||
        return Regex.Replace(me, $"{clearStr}$", string.Empty);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -24,11 +24,6 @@ public static class GlobalStatic
 | 
			
		||||
    #endif
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     日志保存跳过的API编号
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static string[] LogSavingSkipApiIds => ["api/probe/health.check", "api/adm/device.log/create"];
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     系统内部密钥
 | 
			
		||||
    /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,9 +8,10 @@
 | 
			
		||||
    <ItemGroup>
 | 
			
		||||
        <PackageReference Include="FreeSql.DbContext.NS" Version="3.2.833-preview20260627-ns1"/>
 | 
			
		||||
        <PackageReference Include="FreeSql.Provider.Sqlite.NS" Version="3.2.833-preview20260627-ns1"/>
 | 
			
		||||
        <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.4"/>
 | 
			
		||||
        <PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.4-ns1"/>
 | 
			
		||||
        <PackageReference Include="Furion.Pure.NS" Version="4.9.4-ns1"/>
 | 
			
		||||
        <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.4.6"/>
 | 
			
		||||
        <PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.4.6-ns4"/>
 | 
			
		||||
        <PackageReference Include="Furion.Pure.NS" Version="4.9.4.6-ns4"/>
 | 
			
		||||
        <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.10.0"/>
 | 
			
		||||
        <PackageReference Include="Minio" Version="6.0.3"/>
 | 
			
		||||
        <PackageReference Include="NSExt" Version="2.2.0"/>
 | 
			
		||||
        <PackageReference Include="RedLock.net" Version="2.3.2"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -42,17 +42,17 @@ public interface IJobModule : ICrudModule<CreateJobReq, QueryJobRsp // 创建类
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     获取作业记录条形图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Task<IOrderedEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
    Task<IEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     状态码分组作业记录饼图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Task<IOrderedEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
    Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     名称分组作业记录饼图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Task<IOrderedEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
    Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     分页查询作业记录
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,13 @@
 | 
			
		||||
using NetAdmin.Application.Modules;
 | 
			
		||||
using NetAdmin.Domain.Dto.Dependency;
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.RequestLogDetail;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.SysComponent.Application.Modules.Sys;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     请求日志明细模块
 | 
			
		||||
/// </summary>
 | 
			
		||||
public interface IRequestLogDetailModule : ICrudModule<CreateRequestLogDetailReq, QueryRequestLogDetailRsp // 创建类型
 | 
			
		||||
  , QueryRequestLogDetailReq, QueryRequestLogDetailRsp                                                     // 查询类型
 | 
			
		||||
  , DelReq                                                                                                 // 删除类型
 | 
			
		||||
>;
 | 
			
		||||
@@ -16,15 +16,15 @@ public interface IRequestLogModule : ICrudModule<CreateRequestLogReq, QueryReque
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     获取条形图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Task<IOrderedEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req);
 | 
			
		||||
    Task<IEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     描述分组饼图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req);
 | 
			
		||||
    Task<IEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     状态码分组饼图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryRequestLogReq> req);
 | 
			
		||||
    Task<IEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryRequestLogReq> req);
 | 
			
		||||
}
 | 
			
		||||
@@ -108,13 +108,16 @@ public sealed class ApiService(
 | 
			
		||||
        QueryApiRsp SelectQueryApiRsp(IGrouping<TypeInfo, ControllerActionDescriptor> group)
 | 
			
		||||
        {
 | 
			
		||||
            var first = group.First()!;
 | 
			
		||||
 | 
			
		||||
            var id = Regex.Replace( //
 | 
			
		||||
                first.AttributeRouteInfo!.Template!, $"/{first.ActionName}$", string.Empty);
 | 
			
		||||
            return new QueryApiRsp {
 | 
			
		||||
                                       Summary = xmlCommentReader.GetComments(group.Key)
 | 
			
		||||
                                     , Name    = first.ControllerName
 | 
			
		||||
                                     , Id = Regex.Replace( //
 | 
			
		||||
                                           first.AttributeRouteInfo!.Template!, $"/{first.ActionName}$", string.Empty)
 | 
			
		||||
                                       Summary   = xmlCommentReader.GetComments(group.Key)
 | 
			
		||||
                                     , Name      = first.ControllerName
 | 
			
		||||
                                     , Id        = id
 | 
			
		||||
                                     , Children  = GetChildren(group)
 | 
			
		||||
                                     , Namespace = regex.Match(group.Key.Namespace!).Groups[1].Value.ToLowerInvariant()
 | 
			
		||||
                                     , PathCrc32 = id.Crc32()
 | 
			
		||||
                                   };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -136,19 +139,25 @@ public sealed class ApiService(
 | 
			
		||||
    private IEnumerable<QueryApiRsp> GetChildren(IEnumerable<ControllerActionDescriptor> actionDescriptors)
 | 
			
		||||
    {
 | 
			
		||||
        return actionDescriptors //
 | 
			
		||||
            .Select(x => new QueryApiRsp {
 | 
			
		||||
                                             Summary = xmlCommentReader.GetComments(x.MethodInfo)
 | 
			
		||||
                                           , Name    = x.ActionName
 | 
			
		||||
                                           , Id      = x.AttributeRouteInfo!.Template
 | 
			
		||||
                                           , Method = x.ActionConstraints?.OfType<HttpMethodActionConstraint>()
 | 
			
		||||
                                                       .FirstOrDefault()
 | 
			
		||||
                                                       ?.HttpMethods.First()
 | 
			
		||||
                                         });
 | 
			
		||||
            .Select(x => {
 | 
			
		||||
                var id = x.AttributeRouteInfo!.Template;
 | 
			
		||||
                return new QueryApiRsp {
 | 
			
		||||
                                           Summary = xmlCommentReader.GetComments(x.MethodInfo)
 | 
			
		||||
                                         , Name    = x.ActionName
 | 
			
		||||
                                         , Id      = id
 | 
			
		||||
                                         , Method = x.ActionConstraints?.OfType<HttpMethodActionConstraint>()
 | 
			
		||||
                                                     .FirstOrDefault()
 | 
			
		||||
                                                     ?.HttpMethods.First()
 | 
			
		||||
                                         , PathCrc32 = id.Crc32()
 | 
			
		||||
                                       };
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ISelect<Sys_Api> QueryInternal(QueryReq<QueryApiReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -142,6 +142,8 @@ public sealed class ConfigService(BasicRepository<Sys_Config, long> rpo) //
 | 
			
		||||
                     .WhereDynamicFilter(req.DynamicFilter)
 | 
			
		||||
                     .WhereIf( //
 | 
			
		||||
                         req.Filter?.Enabled.HasValue ?? false, a => a.Enabled == req.Filter.Enabled.Value);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,15 +14,15 @@ public interface IJobRecordService : IService, IJobRecordModule
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     获取条形图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Task<IOrderedEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
    Task<IEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     状态码分组饼图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
    Task<IEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     名称分组饼图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByNameAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
    Task<IEnumerable<GetPieChartRsp>> GetPieChartByNameAsync(QueryReq<QueryJobRecordReq> req);
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
using NetAdmin.Application.Services;
 | 
			
		||||
using NetAdmin.SysComponent.Application.Modules.Sys;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     请求日志明细服务
 | 
			
		||||
/// </summary>
 | 
			
		||||
public interface IRequestLogDetailService : IService, IRequestLogDetailModule;
 | 
			
		||||
@@ -149,6 +149,7 @@ public sealed class DeptService(BasicRepository<Sys_Dept, long> rpo) //
 | 
			
		||||
            ret = ret.AsTreeCte();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -175,6 +175,7 @@ public sealed class DevService(IApiService apiService) : ServiceBase<DevService>
 | 
			
		||||
            await File.WriteAllTextAsync(file, content).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SeparateLocalFunctionsWithJumpStatement
 | 
			
		||||
        IEnumerable<string> Select(QueryApiRsp item)
 | 
			
		||||
        {
 | 
			
		||||
            return item.Children.Select(x => tplInner.Replace("$actionDesc$", x.Summary)
 | 
			
		||||
 
 | 
			
		||||
@@ -128,6 +128,8 @@ public sealed class DicCatalogService(BasicRepository<Sys_DicCatalog, long> rpo)
 | 
			
		||||
    private ISelect<Sys_DicCatalog> QueryInternal(QueryReq<QueryDicCatalogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -155,6 +155,8 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
 | 
			
		||||
    private ISelect<Sys_DicContent> QueryInternal(QueryReq<QueryDicContentReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -80,7 +80,7 @@ public sealed class JobRecordService(BasicRepository<Sys_JobRecord, long> rpo) /
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<IOrderedEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public async Task<IEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
 | 
			
		||||
@@ -105,8 +105,7 @@ public sealed class JobRecordService(BasicRepository<Sys_JobRecord, long> rpo) /
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(
 | 
			
		||||
        QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public async Task<IEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var ret = await QueryInternal(req with { Order = Orders.None })
 | 
			
		||||
@@ -124,7 +123,7 @@ public sealed class JobRecordService(BasicRepository<Sys_JobRecord, long> rpo) /
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public async Task<IEnumerable<GetPieChartRsp>> GetPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var ret = await QueryInternal(req with { Order = Orders.None })
 | 
			
		||||
@@ -178,6 +177,8 @@ public sealed class JobRecordService(BasicRepository<Sys_JobRecord, long> rpo) /
 | 
			
		||||
                         req.Keywords?.Length > 0
 | 
			
		||||
                       , a => a.JobId       == req.Keywords.Int64Try(0) || a.Id == req.Keywords.Int64Try(0) ||
 | 
			
		||||
                              a.Job.JobName == req.Keywords);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -77,11 +77,13 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
 | 
			
		||||
                        .Set(a => a.JobName                 == req.JobName)
 | 
			
		||||
                        .SetIf(req.RequestHeaders == null, a => a.RequestHeader, null)
 | 
			
		||||
                        .SetIf(req.RequestHeaders != null, a => a.RequestHeader, req.RequestHeaders.Json())
 | 
			
		||||
                        .Set(a => a.RequestBody == req.RequestBody)
 | 
			
		||||
                        .Set(a => a.RequestUrl  == req.RequestUrl)
 | 
			
		||||
                        .Set(a => a.UserId      == req.UserId)
 | 
			
		||||
                        .Set(a => a.Summary     == req.Summary)
 | 
			
		||||
                        .Where(a => a.Id        == req.Id);
 | 
			
		||||
                        .Set(a => a.RequestBody      == req.RequestBody)
 | 
			
		||||
                        .Set(a => a.RequestUrl       == req.RequestUrl)
 | 
			
		||||
                        .Set(a => a.RandomDelayBegin == req.RandomDelayBegin)
 | 
			
		||||
                        .Set(a => a.RandomDelayEnd   == req.RandomDelayEnd)
 | 
			
		||||
                        .Set(a => a.UserId           == req.UserId)
 | 
			
		||||
                        .Set(a => a.Summary          == req.Summary)
 | 
			
		||||
                        .Where(a => a.Id             == req.Id);
 | 
			
		||||
 | 
			
		||||
        #if DBTYPE_SQLSERVER
 | 
			
		||||
        return (await update.ExecuteUpdatedAsync().ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryJobRsp>();
 | 
			
		||||
@@ -236,22 +238,21 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IOrderedEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        return jobRecordService.GetBarChartAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(
 | 
			
		||||
        QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        return jobRecordService.GetPieChartByHttpStatusCodeAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        return jobRecordService.GetPieChartByNameAsync(req);
 | 
			
		||||
@@ -335,6 +336,8 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
 | 
			
		||||
                     .WhereIf( //
 | 
			
		||||
                         req.Keywords?.Length > 0
 | 
			
		||||
                       , a => a.Id == req.Keywords.Int64Try(0) || a.JobName.Contains(req.Keywords));
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,131 @@
 | 
			
		||||
using NetAdmin.Application.Repositories;
 | 
			
		||||
using NetAdmin.Application.Services;
 | 
			
		||||
using NetAdmin.Domain.Dto.Dependency;
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.RequestLogDetail;
 | 
			
		||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc cref="IRequestLogDetailService" />
 | 
			
		||||
public sealed class RequestLogDetailService(BasicRepository<Sys_RequestLogDetail, long> rpo) //
 | 
			
		||||
    : RepositoryService<Sys_RequestLogDetail, long, IRequestLogDetailService>(rpo), IRequestLogDetailService
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var ret = 0;
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once LoopCanBeConvertedToQuery
 | 
			
		||||
        foreach (var item in req.Items) {
 | 
			
		||||
            ret += await DeleteAsync(item).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<long> CountAsync(QueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        return QueryInternal(req)
 | 
			
		||||
            #if DBTYPE_SQLSERVER
 | 
			
		||||
               .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
 | 
			
		||||
            #endif
 | 
			
		||||
            .CountAsync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<QueryRequestLogDetailRsp> CreateAsync(CreateRequestLogDetailReq req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
 | 
			
		||||
        return ret.Adapt<QueryRequestLogDetailRsp>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<int> DeleteAsync(DelReq req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        return Rpo.DeleteAsync(a => a.Id == req.Id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<bool> ExistAsync(QueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        return QueryInternal(req)
 | 
			
		||||
            #if DBTYPE_SQLSERVER
 | 
			
		||||
               .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
 | 
			
		||||
            #endif
 | 
			
		||||
            .AnyAsync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IActionResult> ExportAsync(QueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        throw new NotImplementedException();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<QueryRequestLogDetailRsp> GetAsync(QueryRequestLogDetailReq req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var ret = await QueryInternal(new QueryReq<QueryRequestLogDetailReq> { Filter = req })
 | 
			
		||||
                        .ToOneAsync()
 | 
			
		||||
                        .ConfigureAwait(false);
 | 
			
		||||
        return ret.Adapt<QueryRequestLogDetailRsp>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<PagedQueryRsp<QueryRequestLogDetailRsp>> PagedQueryAsync(
 | 
			
		||||
        PagedQueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var list = await QueryInternal(req)
 | 
			
		||||
                         .Page(req.Page, req.PageSize)
 | 
			
		||||
                         #if DBTYPE_SQLSERVER
 | 
			
		||||
                         .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
 | 
			
		||||
                         #endif
 | 
			
		||||
                         .Count(out var total)
 | 
			
		||||
                         .ToListAsync()
 | 
			
		||||
                         .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        return new PagedQueryRsp<QueryRequestLogDetailRsp>(req.Page, req.PageSize, total
 | 
			
		||||
                                                         , list.Adapt<IEnumerable<QueryRequestLogDetailRsp>>());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<IEnumerable<QueryRequestLogDetailRsp>> QueryAsync(QueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var ret = await QueryInternal(req)
 | 
			
		||||
                        #if DBTYPE_SQLSERVER
 | 
			
		||||
                        .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
 | 
			
		||||
                        #endif
 | 
			
		||||
                        .Take(req.Count)
 | 
			
		||||
                        .ToListAsync()
 | 
			
		||||
                        .ConfigureAwait(false);
 | 
			
		||||
        return ret.Adapt<IEnumerable<QueryRequestLogDetailRsp>>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ISelect<Sys_RequestLogDetail> QueryInternal(QueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
            case Orders.Random:
 | 
			
		||||
                return ret.OrderByRandom();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
 | 
			
		||||
        if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
 | 
			
		||||
            ret = ret.OrderByDescending(a => a.Id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -8,7 +8,9 @@ using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
 | 
			
		||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc cref="IRequestLogService" />
 | 
			
		||||
public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo) //
 | 
			
		||||
public sealed class RequestLogService(
 | 
			
		||||
    BasicRepository<Sys_RequestLog, long> rpo
 | 
			
		||||
  , RequestLogDetailService               requestLogDetailService) //
 | 
			
		||||
    : RepositoryService<Sys_RequestLog, long, IRequestLogService>(rpo), IRequestLogService
 | 
			
		||||
{
 | 
			
		||||
    private static readonly Regex _regex = new(Chars.RGXL_IP_V4);
 | 
			
		||||
@@ -43,6 +45,7 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
 | 
			
		||||
        _ = await requestLogDetailService.CreateAsync(req.Detail).ConfigureAwait(false);
 | 
			
		||||
        return ret.Adapt<QueryRequestLogRsp>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -68,7 +71,17 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo)
 | 
			
		||||
    public Task<IActionResult> ExportAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        return ExportAsync<QueryRequestLogReq, ExportRequestLogRsp>(QueryInternal, req, Ln.请求日志导出);
 | 
			
		||||
        return ExportAsync<QueryRequestLogReq, ExportRequestLogRsp>( //
 | 
			
		||||
            QueryInternal, req, Ln.请求日志导出, a => new {
 | 
			
		||||
                                                        a.Id
 | 
			
		||||
                                                      , Api = new { a.Api.Id }
 | 
			
		||||
                                                      , a.CreatedClientIp
 | 
			
		||||
                                                      , a.CreatedTime
 | 
			
		||||
                                                      , a.Duration
 | 
			
		||||
                                                      , a.HttpMethod
 | 
			
		||||
                                                      , a.HttpStatusCode
 | 
			
		||||
                                                      , Owner = new { a.Owner.UserName }
 | 
			
		||||
                                                    });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
@@ -76,17 +89,18 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var ret = await QueryInternal(new QueryReq<QueryRequestLogReq> { Filter = req })
 | 
			
		||||
                        .Include(a => a.Detail)
 | 
			
		||||
                        .ToOneAsync()
 | 
			
		||||
                        .ConfigureAwait(false);
 | 
			
		||||
        return ret.Adapt<QueryRequestLogRsp>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<IOrderedEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public async Task<IEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
 | 
			
		||||
        var ret = await QueryInternal(req with { Order = Orders.None })
 | 
			
		||||
        var ret = await QueryInternal(req with { Order = Orders.None }, false)
 | 
			
		||||
                        #if DBTYPE_SQLSERVER
 | 
			
		||||
                        .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
 | 
			
		||||
                        #endif
 | 
			
		||||
@@ -107,7 +121,7 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public async Task<IEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var ret = await QueryInternal(req with { Order = Orders.None })
 | 
			
		||||
@@ -121,11 +135,10 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(
 | 
			
		||||
        QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public async Task<IEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        req.ThrowIfInvalid();
 | 
			
		||||
        var ret = await QueryInternal(req with { Order = Orders.None })
 | 
			
		||||
        var ret = await QueryInternal(req with { Order = Orders.None }, false)
 | 
			
		||||
                        #if DBTYPE_SQLSERVER
 | 
			
		||||
                        .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
 | 
			
		||||
                        #endif
 | 
			
		||||
@@ -148,42 +161,40 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo)
 | 
			
		||||
                     .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
 | 
			
		||||
                     #endif
 | 
			
		||||
                     .Count(out var total);
 | 
			
		||||
        object list = req.DynamicFilter?.Filters?.Exists(
 | 
			
		||||
            x => nameof(QueryRequestLogReq.ApiId).Equals(x.Field, StringComparison.OrdinalIgnoreCase) &&
 | 
			
		||||
                 Chars.FLG_PATH_API_SYS_USER_LOGIN_BY_PWD.Equals( //
 | 
			
		||||
                     x.Value.ToString(), StringComparison.OrdinalIgnoreCase)) ?? false
 | 
			
		||||
            ? await select.ToListAsync(a => new {
 | 
			
		||||
                                                    a.ApiId
 | 
			
		||||
                                                  , ApiSummary = a.Api.Summary
 | 
			
		||||
                                                  , a.CreatedClientIp
 | 
			
		||||
                                                  , a.CreatedTime
 | 
			
		||||
                                                  , a.Duration
 | 
			
		||||
                                                  , a.Method
 | 
			
		||||
                                                  , a.CreatedUserAgent
 | 
			
		||||
                                                  , a.HttpStatusCode
 | 
			
		||||
                                                  , a.Id
 | 
			
		||||
                                                  , a.UserId
 | 
			
		||||
                                                  , a.User
 | 
			
		||||
                                                  , a.RequestBody
 | 
			
		||||
                                                })
 | 
			
		||||
                          .ConfigureAwait(false)
 | 
			
		||||
            : await select.ToListAsync(a => new {
 | 
			
		||||
                                                    a.ApiId
 | 
			
		||||
                                                  , ApiSummary = a.Api.Summary
 | 
			
		||||
                                                  , a.CreatedClientIp
 | 
			
		||||
                                                  , a.CreatedTime
 | 
			
		||||
                                                  , a.Duration
 | 
			
		||||
                                                  , a.Method
 | 
			
		||||
                                                  , a.CreatedUserAgent
 | 
			
		||||
                                                  , a.HttpStatusCode
 | 
			
		||||
                                                  , a.Id
 | 
			
		||||
                                                  , a.UserId
 | 
			
		||||
                                                  , a.User
 | 
			
		||||
                                                })
 | 
			
		||||
                          .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        object ret
 | 
			
		||||
            = req.DynamicFilter?.Filters?.Exists(
 | 
			
		||||
                x => nameof(QueryRequestLogReq.ApiPathCrc32).Equals(x.Field, StringComparison.OrdinalIgnoreCase) &&
 | 
			
		||||
                     x.Value.ToString().Int32() == Chars.FLG_PATH_API_SYS_USER_LOGIN_BY_PWD.Crc32()) ?? false
 | 
			
		||||
                ? await select.Include(a => a.Detail)
 | 
			
		||||
                              .ToListAsync(a => new {
 | 
			
		||||
                                                        Api   = new { a.Api.Summary, a.Api.Id }
 | 
			
		||||
                                                      , Owner = new { a.Owner.Id, a.Owner.UserName }
 | 
			
		||||
                                                      , a.CreatedClientIp
 | 
			
		||||
                                                      , a.CreatedTime
 | 
			
		||||
                                                      , a.Duration
 | 
			
		||||
                                                      , a.HttpMethod
 | 
			
		||||
                                                      , a.HttpStatusCode
 | 
			
		||||
                                                      , a.Id
 | 
			
		||||
                                                      , a.ApiPathCrc32
 | 
			
		||||
                                                      , Detail = new { a.Detail.RequestBody, a.Detail.CreatedUserAgent }
 | 
			
		||||
                                                    })
 | 
			
		||||
                              .ConfigureAwait(false)
 | 
			
		||||
                : await select.ToListAsync(a => new {
 | 
			
		||||
                                                        Api   = new { a.Api.Summary, a.Api.Id }
 | 
			
		||||
                                                      , Owner = new { a.Owner.Id, a.Owner.UserName }
 | 
			
		||||
                                                      , a.CreatedClientIp
 | 
			
		||||
                                                      , a.CreatedTime
 | 
			
		||||
                                                      , a.Duration
 | 
			
		||||
                                                      , a.HttpMethod
 | 
			
		||||
                                                      , a.HttpStatusCode
 | 
			
		||||
                                                      , a.Id
 | 
			
		||||
                                                      , a.ApiPathCrc32
 | 
			
		||||
                                                    })
 | 
			
		||||
                              .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        return new PagedQueryRsp<QueryRequestLogRsp>(req.Page, req.PageSize, total
 | 
			
		||||
                                                   , list.Adapt<IEnumerable<QueryRequestLogRsp>>());
 | 
			
		||||
                                                   , ret.Adapt<IEnumerable<QueryRequestLogRsp>>());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
@@ -202,7 +213,17 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo)
 | 
			
		||||
 | 
			
		||||
    private ISelect<Sys_RequestLog> QueryInternal(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.Include(a => a.Api).Include(a => a.User).WhereDynamicFilter(req.DynamicFilter);
 | 
			
		||||
        return QueryInternal(req, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ISelect<Sys_RequestLog> QueryInternal(QueryReq<QueryRequestLogReq> req, bool include)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select;
 | 
			
		||||
        if (include) {
 | 
			
		||||
            ret = ret.Include(a => a.Api).Include(a => a.Owner);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret = ret.WhereDynamicFilter(req.DynamicFilter);
 | 
			
		||||
        if (req.Filter?.Id is not 0) {
 | 
			
		||||
            ret = ret.WhereDynamic(req.Filter);
 | 
			
		||||
        }
 | 
			
		||||
@@ -210,10 +231,11 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo)
 | 
			
		||||
        if (req.Keywords?.Length > 0) {
 | 
			
		||||
            ret = _regex.IsMatch(req.Keywords)
 | 
			
		||||
                ? ret.Where(a => a.CreatedClientIp == req.Keywords.IpV4ToInt32())
 | 
			
		||||
                : ret.Where(a => a.Id            == req.Keywords.Int64Try(0) || a.UserId == req.Keywords.Int64Try(0) ||
 | 
			
		||||
                                 a.User.UserName == req.Keywords             || a.RequestBody.Contains(req.Keywords));
 | 
			
		||||
                : ret.Where(a => a.Id == req.Keywords.Int64Try(0) || a.OwnerId == req.Keywords.Int64Try(0) ||
 | 
			
		||||
                                 a.Owner.UserName == req.Keywords);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -161,6 +161,8 @@ public sealed class RoleService(BasicRepository<Sys_Role, long> rpo) //
 | 
			
		||||
                         req.Keywords?.Length > 0
 | 
			
		||||
                       , a => a.Id == req.Keywords.Int64Try(0) || a.Name.Contains(req.Keywords) ||
 | 
			
		||||
                              a.Summary.Contains(req.Keywords));
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -111,6 +111,8 @@ public sealed class SiteMsgDeptService(BasicRepository<Sys_SiteMsgDept, long> rp
 | 
			
		||||
    private ISelect<Sys_SiteMsgDept> QueryInternal(QueryReq<QuerySiteMsgDeptReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -119,6 +119,8 @@ public sealed class SiteMsgFlagService(BasicRepository<Sys_SiteMsgFlag, long> rp
 | 
			
		||||
    private ISelect<Sys_SiteMsgFlag> QueryInternal(QueryReq<QuerySiteMsgFlagReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -111,6 +111,8 @@ public sealed class SiteMsgRoleService(BasicRepository<Sys_SiteMsgRole, long> rp
 | 
			
		||||
    private ISelect<Sys_SiteMsgRole> QueryInternal(QueryReq<QuerySiteMsgRoleReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -301,6 +301,8 @@ public sealed class SiteMsgService(
 | 
			
		||||
                         req.Keywords?.Length > 0
 | 
			
		||||
                       , a => a.Id == req.Keywords.Int64Try(0) || a.Title.Contains(req.Keywords) ||
 | 
			
		||||
                              a.Summary.Contains(req.Keywords));
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -111,6 +111,8 @@ public sealed class SiteMsgUserService(BasicRepository<Sys_SiteMsgUser, long> rp
 | 
			
		||||
    private ISelect<Sys_SiteMsgUser> QueryInternal(QueryReq<QuerySiteMsgUserReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -490,6 +490,8 @@ public sealed class UserService(
 | 
			
		||||
                       , a => a.Id     == req.Keywords.Int64Try(0) || a.UserName == req.Keywords ||
 | 
			
		||||
                              a.Mobile == req.Keywords             ||
 | 
			
		||||
                              a.Email  == req.Keywords             || a.Summary.Contains(req.Keywords));
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -198,6 +198,8 @@ public sealed class VerifyCodeService(BasicRepository<Sys_VerifyCode, long> rpo,
 | 
			
		||||
    private ISelect<Sys_VerifyCode> QueryInternal(QueryReq<QueryVerifyCodeReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,8 @@ public sealed class ExampleService(BasicRepository<Tpl_Example, long> rpo) //
 | 
			
		||||
    private ISelect<Tpl_Example> QueryInternal(QueryReq<QueryExampleReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
 | 
			
		||||
 | 
			
		||||
        // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
 | 
			
		||||
        switch (req.Order) {
 | 
			
		||||
            case Orders.None:
 | 
			
		||||
                return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,10 @@
 | 
			
		||||
using NetAdmin.Cache;
 | 
			
		||||
using NetAdmin.SysComponent.Application.Modules.Sys;
 | 
			
		||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.SysComponent.Cache.Sys.Dependency;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     请求日志明细缓存
 | 
			
		||||
/// </summary>
 | 
			
		||||
public interface IRequestLogDetailCache : ICache<IDistributedCache, IRequestLogDetailService>, IRequestLogDetailModule;
 | 
			
		||||
@@ -81,8 +81,8 @@ public sealed class DicCache(IDistributedCache cache, IDicService service) //
 | 
			
		||||
    public Task<string> GetDicValueAsync(GetDicValueReq req)
 | 
			
		||||
    {
 | 
			
		||||
        #if !DEBUG
 | 
			
		||||
        return GetOrCreateAsync(                                                  //
 | 
			
		||||
            GetCacheKey(req.GetHashCode().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
        return GetOrCreateAsync(                                                   //
 | 
			
		||||
            GetCacheKey(req.Json().Crc32().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
          , () => Service.GetDicValueAsync(req), TimeSpan.FromSeconds(Numbers.SECS_CACHE_DEFAULT));
 | 
			
		||||
        #else
 | 
			
		||||
        return Service.GetDicValueAsync(req);
 | 
			
		||||
 
 | 
			
		||||
@@ -85,11 +85,11 @@ public sealed class JobCache(IDistributedCache cache, IJobService service)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IOrderedEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        #if !DEBUG
 | 
			
		||||
        return GetOrCreateAsync(                                                  //
 | 
			
		||||
            GetCacheKey(req.GetHashCode().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
        return GetOrCreateAsync(                                                   //
 | 
			
		||||
            GetCacheKey(req.Json().Crc32().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
          , () => Service.GetRecordBarChartAsync(req), TimeSpan.FromSeconds(Numbers.SECS_CACHE_CHART));
 | 
			
		||||
        #else
 | 
			
		||||
        return Service.GetRecordBarChartAsync(req);
 | 
			
		||||
@@ -97,12 +97,11 @@ public sealed class JobCache(IDistributedCache cache, IJobService service)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(
 | 
			
		||||
        QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        #if !DEBUG
 | 
			
		||||
        return GetOrCreateAsync(                                                  //
 | 
			
		||||
            GetCacheKey(req.GetHashCode().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
        return GetOrCreateAsync(                                                   //
 | 
			
		||||
            GetCacheKey(req.Json().Crc32().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
          , () => Service.GetRecordPieChartByHttpStatusCodeAsync(req)
 | 
			
		||||
          , TimeSpan.FromSeconds(Numbers.SECS_CACHE_DEFAULT));
 | 
			
		||||
        #else
 | 
			
		||||
@@ -111,11 +110,11 @@ public sealed class JobCache(IDistributedCache cache, IJobService service)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        #if !DEBUG
 | 
			
		||||
        return GetOrCreateAsync(                                                  //
 | 
			
		||||
            GetCacheKey(req.GetHashCode().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
        return GetOrCreateAsync(                                                   //
 | 
			
		||||
            GetCacheKey(req.Json().Crc32().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
          , () => Service.GetRecordPieChartByNameAsync(req), TimeSpan.FromSeconds(Numbers.SECS_CACHE_CHART));
 | 
			
		||||
        #else
 | 
			
		||||
        return Service.GetRecordPieChartByNameAsync(req);
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,22 @@ public sealed class RequestLogCache(IDistributedCache cache, IRequestLogService
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    #if !DEBUG
 | 
			
		||||
    public async Task<long> CountAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    #else
 | 
			
		||||
    public Task<long> CountAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
        #endif
 | 
			
		||||
    {
 | 
			
		||||
        #if !DEBUG
 | 
			
		||||
        var ret = await GetOrCreateAsync(                                              //
 | 
			
		||||
                GetCacheKey(req.Json().Crc32().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
              , async () => (long?)await Service.CountAsync(req).ConfigureAwait(false)
 | 
			
		||||
              , TimeSpan.FromSeconds(Numbers.SECS_CACHE_DEFAULT))
 | 
			
		||||
            .ConfigureAwait(false);
 | 
			
		||||
        return ret ?? 0;
 | 
			
		||||
        #else
 | 
			
		||||
        return Service.CountAsync(req);
 | 
			
		||||
        #endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
@@ -54,11 +67,11 @@ public sealed class RequestLogCache(IDistributedCache cache, IRequestLogService
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IOrderedEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        #if !DEBUG
 | 
			
		||||
        return GetOrCreateAsync(                                                  //
 | 
			
		||||
            GetCacheKey(req.GetHashCode().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
        return GetOrCreateAsync(                                                   //
 | 
			
		||||
            GetCacheKey(req.Json().Crc32().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
          , () => Service.GetBarChartAsync(req), TimeSpan.FromSeconds(Numbers.SECS_CACHE_CHART));
 | 
			
		||||
        #else
 | 
			
		||||
        return Service.GetBarChartAsync(req);
 | 
			
		||||
@@ -66,11 +79,11 @@ public sealed class RequestLogCache(IDistributedCache cache, IRequestLogService
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        #if !DEBUG
 | 
			
		||||
        return GetOrCreateAsync(                                                  //
 | 
			
		||||
            GetCacheKey(req.GetHashCode().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
        return GetOrCreateAsync(                                                   //
 | 
			
		||||
            GetCacheKey(req.Json().Crc32().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
          , () => Service.GetPieChartByApiSummaryAsync(req), TimeSpan.FromSeconds(Numbers.SECS_CACHE_CHART));
 | 
			
		||||
        #else
 | 
			
		||||
        return Service.GetPieChartByApiSummaryAsync(req);
 | 
			
		||||
@@ -78,11 +91,11 @@ public sealed class RequestLogCache(IDistributedCache cache, IRequestLogService
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        #if !DEBUG
 | 
			
		||||
        return GetOrCreateAsync(                                                  //
 | 
			
		||||
            GetCacheKey(req.GetHashCode().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
        return GetOrCreateAsync(                                                   //
 | 
			
		||||
            GetCacheKey(req.Json().Crc32().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
          , () => Service.GetPieChartByHttpStatusCodeAsync(req), TimeSpan.FromSeconds(Numbers.SECS_CACHE_CHART));
 | 
			
		||||
        #else
 | 
			
		||||
        return Service.GetPieChartByHttpStatusCodeAsync(req);
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,66 @@
 | 
			
		||||
using NetAdmin.Cache;
 | 
			
		||||
using NetAdmin.Domain.Dto.Dependency;
 | 
			
		||||
using NetAdmin.Domain.Dto.Sys.RequestLogDetail;
 | 
			
		||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
 | 
			
		||||
using NetAdmin.SysComponent.Cache.Sys.Dependency;
 | 
			
		||||
 | 
			
		||||
namespace NetAdmin.SysComponent.Cache.Sys;
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc cref="IRequestLogDetailCache" />
 | 
			
		||||
public sealed class RequestLogDetailCache(IDistributedCache cache, IRequestLogDetailService service)
 | 
			
		||||
    : DistributedCache<IRequestLogDetailService>(cache, service), IScoped, IRequestLogDetailCache
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Service.BulkDeleteAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<long> CountAsync(QueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Service.CountAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<QueryRequestLogDetailRsp> CreateAsync(CreateRequestLogDetailReq req)
 | 
			
		||||
    {
 | 
			
		||||
        return Service.CreateAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<int> DeleteAsync(DelReq req)
 | 
			
		||||
    {
 | 
			
		||||
        return Service.DeleteAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<bool> ExistAsync(QueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Service.ExistAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IActionResult> ExportAsync(QueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Service.ExportAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<QueryRequestLogDetailRsp> GetAsync(QueryRequestLogDetailReq req)
 | 
			
		||||
    {
 | 
			
		||||
        return Service.GetAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<PagedQueryRsp<QueryRequestLogDetailRsp>> PagedQueryAsync(PagedQueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Service.PagedQueryAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public Task<IEnumerable<QueryRequestLogDetailRsp>> QueryAsync(QueryReq<QueryRequestLogDetailReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Service.QueryAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -99,8 +99,8 @@ public sealed class UserCache(IDistributedCache cache, IUserService service, IVe
 | 
			
		||||
    public Task<IEnumerable<QueryUserRsp>> QueryAsync(QueryReq<QueryUserReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        #if !DEBUG
 | 
			
		||||
        return GetOrCreateAsync(                                                  //
 | 
			
		||||
            GetCacheKey(req.GetHashCode().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
        return GetOrCreateAsync(                                                   //
 | 
			
		||||
            GetCacheKey(req.Json().Crc32().ToString(CultureInfo.InvariantCulture)) //
 | 
			
		||||
          , () => Service.QueryAsync(req), TimeSpan.FromSeconds(Numbers.SECS_CACHE_DEFAULT));
 | 
			
		||||
        #else
 | 
			
		||||
        return Service.QueryAsync(req);
 | 
			
		||||
 
 | 
			
		||||
@@ -119,7 +119,7 @@ public sealed class JobController(IJobCache cache) : ControllerBase<IJobCache, I
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     获取作业记录条形图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Task<IOrderedEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Cache.GetRecordBarChartAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
@@ -127,8 +127,7 @@ public sealed class JobController(IJobCache cache) : ControllerBase<IJobCache, I
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     状态码分组作业记录饼图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(
 | 
			
		||||
        QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Cache.GetRecordPieChartByHttpStatusCodeAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
@@ -136,7 +135,7 @@ public sealed class JobController(IJobCache cache) : ControllerBase<IJobCache, I
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     名称分组作业记录饼图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Cache.GetRecordPieChartByNameAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -82,7 +82,7 @@ public sealed class LogController(IRequestLogCache cache) : ControllerBase<IRequ
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     获取条形图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Task<IOrderedEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Cache.GetBarChartAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
@@ -90,7 +90,7 @@ public sealed class LogController(IRequestLogCache cache) : ControllerBase<IRequ
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     描述分组饼图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Cache.GetPieChartByApiSummaryAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
@@ -98,7 +98,7 @@ public sealed class LogController(IRequestLogCache cache) : ControllerBase<IRequ
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///     状态码分组饼图数据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public Task<IOrderedEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    public Task<IEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryRequestLogReq> req)
 | 
			
		||||
    {
 | 
			
		||||
        return Cache.GetPieChartByHttpStatusCodeAsync(req);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,18 @@ public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var request = BuildRequest(job);
 | 
			
		||||
        var sw      = new Stopwatch();
 | 
			
		||||
 | 
			
		||||
        // 随机延时
 | 
			
		||||
        if (job.RandomDelayBegin is > 0 && job.RandomDelayEnd is > 0) {
 | 
			
		||||
            var (start, end) = (job.RandomDelayBegin.Value, job.RandomDelayEnd.Value);
 | 
			
		||||
            if (start > end) {
 | 
			
		||||
                (start, end) = (end, start);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await Task.Delay(new[] { start, end }.Rand(), CancellationToken.None).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var sw = new Stopwatch();
 | 
			
		||||
        sw.Start();
 | 
			
		||||
        var rsp = await request.SendAsync(CancellationToken.None).ConfigureAwait(false);
 | 
			
		||||
        if (rsp.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden) {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,13 +18,6 @@ public sealed class OperationLogger : IEventSubscriber
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 跳过指定的请求
 | 
			
		||||
        if (Array.Exists( //
 | 
			
		||||
                GlobalStatic.LogSavingSkipApiIds
 | 
			
		||||
              , x => x.Equals(operationEvent.Data.ApiId, StringComparison.OrdinalIgnoreCase))) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        operationEvent.Data.TruncateStrings();
 | 
			
		||||
        _ = await App.GetService<IRequestLogService>().CreateAsync(operationEvent.Data).ConfigureAwait(false);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user