diff --git a/assets/res/Fields.ln b/assets/res/Fields.ln index b1a1b845..e86f980b 100644 --- a/assets/res/Fields.ln +++ b/assets/res/Fields.ln @@ -98,6 +98,8 @@ 电子邮箱 男 登录 +登录名 +登录日志导出 硕士 示例导出 离异 @@ -123,6 +125,7 @@ 请求日志导出 调试 跟踪 +跟踪标识 跟踪编号 身份证 运行 diff --git a/build/code.quality.props b/build/code.quality.props index e54f22a2..a6b66f29 100644 --- a/build/code.quality.props +++ b/build/code.quality.props @@ -23,7 +23,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/backend/NetAdmin.AdmServer.Tests/AllTests.cs b/src/backend/NetAdmin.AdmServer.Tests/AllTests.cs index eb60988c..0506d843 100644 --- a/src/backend/NetAdmin.AdmServer.Tests/AllTests.cs +++ b/src/backend/NetAdmin.AdmServer.Tests/AllTests.cs @@ -823,11 +823,14 @@ public class AllTests(WebApplicationFactory factory, ITestOutputHelper /// [InlineData(default)] [Theory] - public async Task> GetAllEntriesAsync(PagedQueryReq req) + public Task> GetAllEntriesAsync(GetAllEntriesReq req) { - var rsp = await PostAsync("/api/sys/cache/get.all.entries" - , JsonContent.Create(new PagedQueryReq())) - .ConfigureAwait(true); + var rsp = PostAsync("/api/sys/cache/get.all.entries", JsonContent.Create(new GetAllEntriesReq())) + .ConfigureAwait(true) + .GetAwaiter() + #pragma warning disable xUnit1031 + .GetResult(); + #pragma warning restore xUnit1031 Assert.Equal(HttpStatusCode.OK, rsp.StatusCode); return default; } @@ -1029,6 +1032,12 @@ public class AllTests(WebApplicationFactory factory, ITestOutputHelper return default; } + /// + public Task GetEntryAsync(GetEntriesReq req) + { + return default; + } + /// [Fact] public IDictionary> GetEnums() diff --git a/src/backend/NetAdmin.Application/Services/RedLockerService.cs b/src/backend/NetAdmin.Application/Services/RedLockerService.cs index 3f69db2e..9f5a83c3 100644 --- a/src/backend/NetAdmin.Application/Services/RedLockerService.cs +++ b/src/backend/NetAdmin.Application/Services/RedLockerService.cs @@ -12,19 +12,39 @@ public abstract class RedLockerService( where TEntity : EntityBase // where TPrimary : IEquatable { + /// + /// 获取锁 + /// + protected Task GetLockerAsync(string lockName) + { + return GetLockerAsync(lockName, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_WAIT) + , TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_RETRY_INTERVAL)); + } + /// /// 获取锁 /// /// NetAdminGetLockerException - protected async Task GetLockerAsync(string lockName) + protected async Task GetLockerAsync(string lockName, TimeSpan waitTime, TimeSpan retryInterval) { // 加锁 - var redLock = await redLocker.RedLockFactory.CreateLockAsync( // - lockName, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_EXPIRY) - , TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_WAIT) - , TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_RETRY)) - .ConfigureAwait(false); + var lockTask = waitTime == default || retryInterval == default + ? redLocker.RedLockFactory.CreateLockAsync(lockName, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_EXPIRY)) + : redLocker.RedLockFactory.CreateLockAsync( // + lockName, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_EXPIRY), waitTime, retryInterval); + var redLock = await lockTask.ConfigureAwait(false); return redLock.IsAcquired ? redLock : throw new NetAdminGetLockerException(); } + + /// + /// 获取锁 + /// + /// + /// 不重试,失败直接抛出异常 + /// + protected Task GetLockerOnceAsync(string lockName) + { + return GetLockerAsync(lockName, default, default); + } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Contexts/ContextUserToken.cs b/src/backend/NetAdmin.Domain/Contexts/ContextUserToken.cs index c7dc47ad..b87994d7 100644 --- a/src/backend/NetAdmin.Domain/Contexts/ContextUserToken.cs +++ b/src/backend/NetAdmin.Domain/Contexts/ContextUserToken.cs @@ -49,4 +49,14 @@ public sealed record ContextUserToken : DataAbstraction Id = user.Id, Token = user.Token, UserName = user.UserName, DeptId = user.DeptId }; } + + /// + /// 从 Json Web Token 创建上下文用户 + /// + public static ContextUserToken Create(string jwt) + { + var claim = JWTEncryption.ReadJwtToken(jwt.TrimPrefix($"{Chars.FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA} ")) + ?.Claims.FirstOrDefault(x => x.Type == nameof(ContextUserToken)); + return claim?.Value.ToObject(); + } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Api.cs b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Api.cs index 3ab7a8b0..94f4c745 100644 --- a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Api.cs +++ b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Api.cs @@ -61,7 +61,7 @@ public record Sys_Api : ImmutableEntity, IFieldSummary [Column] [CsvIgnore] [JsonIgnore] - public int PathCrc32 { get; init; } + public virtual int PathCrc32 { get; init; } /// /// 角色集合 diff --git a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_LoginLog.cs b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_LoginLog.cs new file mode 100644 index 00000000..660678e6 --- /dev/null +++ b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_LoginLog.cs @@ -0,0 +1,150 @@ +namespace NetAdmin.Domain.DbMaps.Sys; + +/// +/// 登录日志表 +/// +[SqlIndex(Chars.FLG_DB_INDEX_PREFIX + nameof(CreatedTime), $"{nameof(CreatedTime)} DESC", false)] +[SqlIndex(Chars.FLG_DB_INDEX_PREFIX + nameof(HttpStatusCode), nameof(HttpStatusCode), false)] +[SqlIndex(Chars.FLG_DB_INDEX_PREFIX + nameof(OwnerId), nameof(OwnerId), false)] +[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_LoginLog))] +public record Sys_LoginLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFieldCreatedClientIp + , IFieldCreatedClientUserAgent +{ + /// + [Column] + [CsvIgnore] + [JsonIgnore] + public virtual int? CreatedClientIp { get; init; } + + /// + [Column(ServerTime = DateTimeKind.Local, CanUpdate = false, Position = -1)] + [CsvIgnore] + [JsonIgnore] + public virtual DateTime CreatedTime { get; init; } + + /// + #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 + [CsvIgnore] + [JsonIgnore] + public virtual string CreatedUserAgent { get; init; } + + /// + /// 执行耗时(毫秒) + /// + [Column] + [CsvIgnore] + [JsonIgnore] + public virtual int Duration { get; init; } + + /// + /// 程序响应码 + /// + [Column] + [CsvIgnore] + [JsonIgnore] + public virtual ErrorCodes ErrorCode { get; init; } + + /// + /// HTTP状态码 + /// + [Column(DbType = Chars.FLG_DB_FIELD_TYPE_SMALL_INT)] + [CsvIgnore] + [JsonIgnore] + public virtual int HttpStatusCode { get; init; } + + /// + /// 登录用户名 + /// + [Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)] + [CsvIgnore] + [JsonIgnore] + public virtual string LoginUserName { get; init; } + + /// + /// 拥有者 + /// + [CsvIgnore] + [JsonIgnore] + [Navigate(nameof(OwnerId))] + public Sys_User Owner { get; init; } + + /// + [Column] + [CsvIgnore] + [JsonIgnore] + public virtual long? OwnerDeptId { get; init; } + + /// + [Column] + [CsvIgnore] + [JsonIgnore] + public virtual long? OwnerId { get; init; } + + /// + /// 请求内容 + /// + #if DBTYPE_SQLSERVER + [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)] + #else + [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] + #endif + [CsvIgnore] + [JsonIgnore] + public virtual string RequestBody { get; init; } + + /// + /// 请求头信息 + /// + #if DBTYPE_SQLSERVER + [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)] + #else + [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] + #endif + [CsvIgnore] + [JsonIgnore] + public virtual string RequestHeaders { get; init; } + + /// + /// 请求地址 + /// + [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)] + [CsvIgnore] + [JsonIgnore] + public virtual string RequestUrl { get; init; } + + /// + /// 响应内容 + /// + #if DBTYPE_SQLSERVER + [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)] + #else + [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] + #endif + [CsvIgnore] + [JsonIgnore] + public virtual string ResponseBody { get; init; } + + /// + /// 响应头 + /// + #if DBTYPE_SQLSERVER + [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)] + #else + [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] + #endif + [CsvIgnore] + [JsonIgnore] + public virtual string ResponseHeaders { get; init; } + + /// + /// 服务器IP + /// + [Column] + [CsvIgnore] + [JsonIgnore] + public virtual int? ServerIp { get; init; } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLog.cs b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLog.cs index f9d70af3..1bab3d85 100644 --- a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLog.cs +++ b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLog.cs @@ -5,11 +5,13 @@ namespace NetAdmin.Domain.DbMaps.Sys; /// /// 请求日志表 /// -[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))] +[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)}_{{yyyyMMdd}}" + , AsTable = $"{nameof(CreatedTime)}=2024-1-1(1 day)")] public record Sys_RequestLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFieldCreatedClientIp { /// @@ -91,4 +93,12 @@ public record Sys_RequestLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFi [CsvIgnore] [JsonIgnore] public virtual long? OwnerId { get; init; } + + /// + /// 请求跟踪标识 + /// + [Column] + [CsvIgnore] + [JsonIgnore] + public virtual Guid TraceId { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLogDetail.cs b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLogDetail.cs index 5cb47f85..e27d628d 100644 --- a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLogDetail.cs +++ b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLogDetail.cs @@ -4,6 +4,7 @@ namespace NetAdmin.Domain.DbMaps.Sys; /// 请求日志明细表 /// [Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_RequestLogDetail))] +[SqlIndex(Chars.FLG_DB_INDEX_PREFIX + nameof(CreatedTime), $"{nameof(CreatedTime)} DESC", false)] public record Sys_RequestLogDetail : SimpleEntity, IFieldCreatedTime, IFieldCreatedClientUserAgent { /// @@ -121,12 +122,4 @@ public record Sys_RequestLogDetail : SimpleEntity, IFieldCreatedTime, IFieldCrea [CsvIgnore] [JsonIgnore] public virtual int? ServerIp { get; init; } - - /// - /// 请求跟踪标识 - /// - [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)] - [CsvIgnore] - [JsonIgnore] - public virtual string TraceId { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Dependency/DynamicFilterInfo.cs b/src/backend/NetAdmin.Domain/Dto/Dependency/DynamicFilterInfo.cs index 053e0d93..79012507 100644 --- a/src/backend/NetAdmin.Domain/Dto/Dependency/DynamicFilterInfo.cs +++ b/src/backend/NetAdmin.Domain/Dto/Dependency/DynamicFilterInfo.cs @@ -50,29 +50,34 @@ public sealed record DynamicFilterInfo : DataAbstraction } } - if (d?.Operator != DynamicFilterOperator.DateRange) { - return; + if (new[] { nameof(IFieldCreatedClientIp.CreatedClientIp), nameof(IFieldModifiedClientIp.ModifiedClientIp) } + .Contains(d?.Field, StringComparer.OrdinalIgnoreCase)) { + var val = d!.Value?.ToString(); + if (val?.IsIpV4() == true) { + d.Value = val.IpV4ToInt32(); + } } + else if (d?.Operator == DynamicFilterOperator.DateRange) { + var values = ((JsonElement)d.Value).Deserialize(); + if (!DateTime.TryParse(values[0], CultureInfo.InvariantCulture, out _)) { + var result = values[0] + .ExecuteCSharpCodeAsync([typeof(DateTime).Assembly], nameof(System)) + .ConfigureAwait(false) + .GetAwaiter() + .GetResult(); + values[0] = $"{result:yyyy-MM-dd HH:mm:ss}"; + } - var values = ((JsonElement)d.Value).Deserialize(); - if (!DateTime.TryParse(values[0], CultureInfo.InvariantCulture, out _)) { - var result = values[0] - .ExecuteCSharpCodeAsync([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([typeof(DateTime).Assembly], nameof(System)) + .ConfigureAwait(false) + .GetAwaiter() + .GetResult(); + values[1] = $"{result:yyyy-MM-dd HH:mm:ss}"; + } + + d.Value = values; } - - if (!DateTime.TryParse(values[1], CultureInfo.InvariantCulture, out _)) { - var result = values[1] - .ExecuteCSharpCodeAsync([typeof(DateTime).Assembly], nameof(System)) - .ConfigureAwait(false) - .GetAwaiter() - .GetResult(); - values[1] = $"{result:yyyy-MM-dd HH:mm:ss}"; - } - - d.Value = values; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Api/ExportApiRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Api/ExportApiRsp.cs index d9601868..0c975774 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Api/ExportApiRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Api/ExportApiRsp.cs @@ -10,26 +10,26 @@ public record ExportApiRsp : QueryApiRsp public override IEnumerable Children { get; init; } /// - [CsvIgnore(false)] [CsvIndex(0)] + [CsvIgnore(false)] [CsvName(nameof(Ln.接口路径))] public override string Id { get; init; } /// - [CsvIgnore(false)] [CsvIndex(2)] + [CsvIgnore(false)] [CsvName(nameof(Ln.请求方式))] public override string Method { get; init; } /// - [CsvIgnore(false)] [CsvIndex(1)] + [CsvIgnore(false)] [CsvName(nameof(Ln.接口名称))] public override string Name { get; init; } /// - [CsvIgnore(false)] [CsvIndex(3)] + [CsvIgnore(false)] [CsvName(nameof(Ln.接口描述))] public override string Summary { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Api/QueryApiRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Api/QueryApiRsp.cs index 36465425..3ada91ac 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Api/QueryApiRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Api/QueryApiRsp.cs @@ -27,6 +27,10 @@ public record QueryApiRsp : Sys_Api [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public override string ParentId { get; init; } + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override int PathCrc32 { get; init; } + /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public override string Summary { get; init; } diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetAllEntriesReq.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetAllEntriesReq.cs index 18107420..98d4e2a5 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetAllEntriesReq.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetAllEntriesReq.cs @@ -6,7 +6,7 @@ namespace NetAdmin.Domain.Dto.Sys.Cache; public sealed record GetAllEntriesReq : DataAbstraction { /// - /// 数据库索引号 + /// 关键词 /// - public int DbIndex { get; init; } + public string Keywords { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetAllEntriesRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetAllEntriesRsp.cs deleted file mode 100644 index 1716a4d2..00000000 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetAllEntriesRsp.cs +++ /dev/null @@ -1,55 +0,0 @@ -namespace NetAdmin.Domain.Dto.Sys.Cache; - -/// -/// 响应:获取所有缓存项 -/// -public sealed record GetAllEntriesRsp : DataAbstraction -{ - /// - /// Initializes a new instance of the class. - /// - public GetAllEntriesRsp() { } - - /// - /// Initializes a new instance of the class. - /// - public GetAllEntriesRsp(long absExp, string key, long sldExp, string data) - { - AbsExp = absExp; - Key = key; - SldExp = sldExp; - Data = data; - } - - /// - /// 绝对过期时间 - /// - public DateTime? AbsExpTime => AbsExp == -1 ? null : DateTime.FromBinary(AbsExp).ToLocalTime(); - - /// - /// 滑动过期时间 - /// - public DateTime? SldExpTime => SldExp == -1 ? null : DateTime.FromBinary(SldExp).ToLocalTime(); - - /// - /// 绝对过期时间 - /// - [JsonInclude] - public long AbsExp { get; init; } - - /// - /// 缓存值 - /// - public string Data { get; init; } - - /// - /// 缓存键 - /// - public string Key { get; init; } - - /// - /// 滑动过期时间 - /// - [JsonInclude] - public long SldExp { get; init; } -} \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetEntriesReq.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetEntriesReq.cs new file mode 100644 index 00000000..47b986e3 --- /dev/null +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetEntriesReq.cs @@ -0,0 +1,12 @@ +namespace NetAdmin.Domain.Dto.Sys.Cache; + +/// +/// 请求:获取缓存项 +/// +public sealed record GetEntriesReq : DataAbstraction +{ + /// + /// 缓存键 + /// + public string Key { get; init; } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetEntryRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetEntryRsp.cs new file mode 100644 index 00000000..08de42d9 --- /dev/null +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Cache/GetEntryRsp.cs @@ -0,0 +1,34 @@ +using StackExchange.Redis; + +namespace NetAdmin.Domain.Dto.Sys.Cache; + +/// +/// 响应:获取所有缓存项 +/// +public sealed record GetEntryRsp : DataAbstraction +{ + /// + /// Initializes a new instance of the class. + /// + public GetEntryRsp() { } + + /// + /// 缓存值 + /// + public string Data { get; set; } + + /// + /// 过期时间 + /// + public DateTime? ExpireTime { get; init; } + + /// + /// 缓存键 + /// + public string Key { get; init; } + + /// + /// 数据类型 + /// + public RedisType Type { get; init; } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Config/ExportConfigRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Config/ExportConfigRsp.cs index 3611b6bf..ef260b0b 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Config/ExportConfigRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Config/ExportConfigRsp.cs @@ -9,20 +9,20 @@ namespace NetAdmin.Domain.Dto.Sys.Config; public record ExportConfigRsp : QueryConfigRsp, IRegister { /// - [CsvIgnore(false)] [CsvIndex(6)] + [CsvIgnore(false)] [CsvName(nameof(Ln.是否启用))] public override bool Enabled { get; init; } /// - [CsvIgnore(false)] [CsvIndex(0)] + [CsvIgnore(false)] [CsvName(nameof(Ln.唯一编码))] public override long Id { get; init; } /// - [CsvIgnore(false)] [CsvIndex(3)] + [CsvIgnore(false)] [CsvName(nameof(Ln.人工审核))] public override bool UserRegisterConfirm { get; init; } @@ -33,8 +33,8 @@ public record ExportConfigRsp : QueryConfigRsp, IRegister /// /// 默认部门 /// - [CsvIgnore(false)] [CsvIndex(1)] + [CsvIgnore(false)] [CsvName(nameof(Ln.默认部门))] public string UserRegisterDeptName { get; init; } @@ -45,8 +45,8 @@ public record ExportConfigRsp : QueryConfigRsp, IRegister /// /// 默认角色 /// - [CsvIgnore(false)] [CsvIndex(2)] + [CsvIgnore(false)] [CsvName(nameof(Ln.默认角色))] public string UserRegisterRoleName { get; init; } diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Dept/ExportDeptRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Dept/ExportDeptRsp.cs index 2c848c9a..dfb0fc33 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Dept/ExportDeptRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Dept/ExportDeptRsp.cs @@ -10,38 +10,38 @@ public record ExportDeptRsp : QueryDeptRsp public override IEnumerable Children { get; init; } /// - [CsvIgnore(false)] [CsvIndex(5)] + [CsvIgnore(false)] [CsvName(nameof(Ln.创建时间))] public override DateTime CreatedTime { get; init; } /// - [CsvIgnore(false)] [CsvIndex(4)] + [CsvIgnore(false)] [CsvName(nameof(Ln.是否启用))] public override bool Enabled { get; init; } /// - [CsvIgnore(false)] [CsvIndex(0)] + [CsvIgnore(false)] [CsvName(nameof(Ln.唯一编码))] public override long Id { get; init; } /// - [CsvIgnore(false)] [CsvIndex(1)] + [CsvIgnore(false)] [CsvName(nameof(Ln.部门名称))] public override string Name { get; init; } /// - [CsvIgnore(false)] [CsvIndex(2)] + [CsvIgnore(false)] [CsvName(nameof(Ln.排序))] public override long Sort { get; init; } /// - [CsvIgnore(false)] [CsvIndex(3)] + [CsvIgnore(false)] [CsvName(nameof(Ln.备注))] public override string Summary { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Dic/Content/ExportDicContentRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Dic/Content/ExportDicContentRsp.cs index 6b8386f8..f8e9639a 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Dic/Content/ExportDicContentRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Dic/Content/ExportDicContentRsp.cs @@ -6,20 +6,20 @@ namespace NetAdmin.Domain.Dto.Sys.Dic.Content; public record ExportDicContentRsp : QueryDicContentRsp { /// - [CsvIgnore(false)] [CsvIndex(2)] + [CsvIgnore(false)] [CsvName(nameof(Ln.创建时间))] public override DateTime CreatedTime { get; init; } /// - [CsvIgnore(false)] [CsvIndex(0)] + [CsvIgnore(false)] [CsvName(nameof(Ln.项名))] public override string Key { get; init; } /// - [CsvIgnore(false)] [CsvIndex(1)] + [CsvIgnore(false)] [CsvName(nameof(Ln.项值))] public override string Value { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Job/ExportJobRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Job/ExportJobRsp.cs index f96dff0a..544cfcf6 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Job/ExportJobRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Job/ExportJobRsp.cs @@ -10,68 +10,68 @@ namespace NetAdmin.Domain.Dto.Sys.Job; public record ExportJobRsp : QueryJobRsp { /// - [CsvIgnore(false)] [CsvIndex(5)] + [CsvIgnore(false)] [CsvName(nameof(Ln.上次执行状态))] public override string LastStatusCode => base.LastStatusCode; /// - [CsvIgnore(false)] [CsvIndex(10)] + [CsvIgnore(false)] [CsvName(nameof(Ln.创建时间))] public override DateTime CreatedTime { get; init; } /// - [CsvIgnore(false)] [CsvIndex(9)] + [CsvIgnore(false)] [CsvName(nameof(Ln.是否启用))] public override bool Enabled { get; init; } /// - [CsvIgnore(false)] [CsvIndex(2)] + [CsvIgnore(false)] [CsvName(nameof(Ln.执行计划))] public override string ExecutionCron { get; init; } /// - [CsvIgnore(false)] [CsvIndex(4)] + [CsvIgnore(false)] [CsvName(nameof(Ln.请求方式))] public override HttpMethods HttpMethod { get; init; } /// - [CsvIgnore(false)] [CsvIndex(0)] + [CsvIgnore(false)] [CsvName(nameof(Ln.唯一编码))] public override long Id { get; init; } /// - [CsvIgnore(false)] [CsvIndex(1)] + [CsvIgnore(false)] [CsvName(nameof(Ln.作业名称))] public override string JobName { get; init; } /// - [CsvIgnore(false)] [CsvIndex(7)] + [CsvIgnore(false)] [CsvName(nameof(Ln.上次执行耗时))] public override long? LastDuration { get; init; } /// - [CsvIgnore(false)] [CsvIndex(6)] + [CsvIgnore(false)] [CsvName(nameof(Ln.上次执行时间))] public override DateTime? LastExecTime { get; init; } /// - [CsvIgnore(false)] [CsvIndex(8)] + [CsvIgnore(false)] [CsvName(nameof(Ln.下次执行时间))] public override DateTime? NextExecTime { get; init; } /// - [CsvIgnore(false)] [CsvIndex(3)] + [CsvIgnore(false)] [CsvName(nameof(Ln.作业状态))] public override JobStatues Status { get; init; } diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/JobRecord/ExportJobRecordRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/JobRecord/ExportJobRecordRsp.cs index 60dde7b7..66531d2f 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/JobRecord/ExportJobRecordRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/JobRecord/ExportJobRecordRsp.cs @@ -8,26 +8,26 @@ namespace NetAdmin.Domain.Dto.Sys.JobRecord; public record ExportJobRecordRsp : QueryJobRecordRsp, IRegister { /// - [CsvIgnore(false)] [CsvIndex(1)] + [CsvIgnore(false)] [CsvName(nameof(Ln.响应状态码))] public override string HttpStatusCode => base.HttpStatusCode; /// - [CsvIgnore(false)] [CsvIndex(6)] + [CsvIgnore(false)] [CsvName(nameof(Ln.创建时间))] public override DateTime CreatedTime { get; init; } /// - [CsvIgnore(false)] [CsvIndex(3)] + [CsvIgnore(false)] [CsvName(nameof(Ln.执行耗时))] public override long Duration { get; init; } /// - [CsvIgnore(false)] [CsvIndex(0)] + [CsvIgnore(false)] [CsvName(nameof(Ln.唯一编码))] public override long Id { get; init; } @@ -38,14 +38,14 @@ public record ExportJobRecordRsp : QueryJobRecordRsp, IRegister /// /// 作业名称 /// - [CsvIgnore(false)] [CsvIndex(4)] + [CsvIgnore(false)] [CsvName(nameof(Ln.作业名称))] public string JobName { get; set; } /// - [CsvIgnore(false)] [CsvIndex(5)] + [CsvIgnore(false)] [CsvName(nameof(Ln.响应体))] public override string ResponseBody { get; init; } diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/CreateLoginLogReq.cs b/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/CreateLoginLogReq.cs new file mode 100644 index 00000000..31863a90 --- /dev/null +++ b/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/CreateLoginLogReq.cs @@ -0,0 +1,50 @@ +using NetAdmin.Domain.Contexts; +using NetAdmin.Domain.Dto.Sys.RequestLog; +using NetAdmin.Domain.Dto.Sys.User; + +namespace NetAdmin.Domain.Dto.Sys.LoginLog; + +/// +/// 请求:创建登录日志 +/// +public record CreateLoginLogReq : Sys_LoginLog, IRegister +{ + /// + public void Register(TypeAdapterConfig config) + { + _ = config.ForType().MapWith(x => Convert(x)); + } + + private static CreateLoginLogReq Convert(CreateRequestLogReq s) + { + var body = s.Detail.ResponseBody.ToObject>(); + ContextUserToken userToken = null; + if (body.Data?.AccessToken != null) { + try { + userToken = ContextUserToken.Create(body.Data.AccessToken); + } + catch { + // ignored + } + } + + return new CreateLoginLogReq { + Id = s.Id + , CreatedClientIp = s.CreatedClientIp + , CreatedTime = s.CreatedTime + , Duration = s.Duration + , HttpStatusCode = s.HttpStatusCode + , ErrorCode = s.Detail.ErrorCode + , RequestBody = s.Detail.RequestBody + , RequestHeaders = s.Detail.RequestHeaders + , RequestUrl = s.Detail.RequestUrl + , ResponseBody = s.Detail.ResponseBody + , ResponseHeaders = s.Detail.ResponseHeaders + , ServerIp = s.Detail.ServerIp + , CreatedUserAgent = s.Detail.CreatedUserAgent + , OwnerId = userToken?.Id + , OwnerDeptId = userToken?.DeptId + , LoginUserName = s.Detail.RequestBody?.ToObject()?.Account + }; + } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/ExportLoginLogRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/ExportLoginLogRsp.cs new file mode 100644 index 00000000..ef5e00cb --- /dev/null +++ b/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/ExportLoginLogRsp.cs @@ -0,0 +1,55 @@ +using NetAdmin.Domain.Dto.Sys.User; + +namespace NetAdmin.Domain.Dto.Sys.LoginLog; + +/// +/// 响应:导出登录日志 +/// +public sealed record ExportLoginLogRsp : QueryLoginLogRsp +{ + /// + [CsvIndex(3)] + [CsvIgnore(false)] + [CsvName(nameof(Ln.客户端IP))] + public override string CreatedClientIp => base.CreatedClientIp; + + /// + [CsvIndex(4)] + [CsvIgnore(false)] + [CsvName(nameof(Ln.操作系统))] + public override string Os => base.Os; + + /// + [CsvIgnore(false)] + [CsvIndex(6)] + [CsvName(nameof(Ln.创建时间))] + public override DateTime CreatedTime { get; init; } + + /// + [CsvIndex(5)] + [CsvIgnore(false)] + [CsvName(nameof(Ln.用户代理))] + public override string CreatedUserAgent { get; init; } + + /// + [CsvIndex(1)] + [CsvIgnore(false)] + [CsvName(nameof(Ln.响应状态码))] + public override int HttpStatusCode { get; init; } + + /// + [CsvIndex(0)] + [CsvIgnore(false)] + [CsvName(nameof(Ln.唯一编码))] + public override long Id { get; init; } + + /// + [CsvIgnore(false)] + [CsvIndex(2)] + [CsvName(nameof(Ln.登录名))] + public override string LoginUserName { get; init; } + + /// + [CsvIgnore] + public override QueryUserRsp Owner { get; init; } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/QueryLoginLogReq.cs b/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/QueryLoginLogReq.cs new file mode 100644 index 00000000..4daf06ee --- /dev/null +++ b/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/QueryLoginLogReq.cs @@ -0,0 +1,11 @@ +namespace NetAdmin.Domain.Dto.Sys.LoginLog; + +/// +/// 请求:查询登录日志 +/// +public sealed record QueryLoginLogReq : Sys_LoginLog +{ + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override long Id { get; init; } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/QueryLoginLogRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/QueryLoginLogRsp.cs new file mode 100644 index 00000000..34cd517c --- /dev/null +++ b/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/QueryLoginLogRsp.cs @@ -0,0 +1,77 @@ +using NetAdmin.Domain.Dto.Sys.User; + +namespace NetAdmin.Domain.Dto.Sys.LoginLog; + +/// +/// 响应:查询登录日志 +/// +public record QueryLoginLogRsp : Sys_LoginLog +{ + /// + /// 创建者客户端IP + /// + [JsonInclude] + public new virtual string CreatedClientIp => base.CreatedClientIp?.ToIpV4(); + + /// + /// 操作系统 + /// + [JsonInclude] + public virtual string Os => UserAgentParser.Create(CreatedUserAgent)?.Platform; + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override DateTime CreatedTime { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string CreatedUserAgent { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override int Duration { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override ErrorCodes ErrorCode { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override int HttpStatusCode { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override long Id { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string LoginUserName { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public new virtual QueryUserRsp Owner { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string RequestBody { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string RequestHeaders { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string RequestUrl { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string ResponseBody { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string ResponseHeaders { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override int? ServerIp { get; init; } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/ExportRequestLogRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/ExportRequestLogRsp.cs index b0165e8b..e4324262 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/ExportRequestLogRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/ExportRequestLogRsp.cs @@ -14,13 +14,13 @@ public record ExportRequestLogRsp : QueryRequestLogRsp /// 接口路径 /// [CsvIndex(2)] - [CsvName(nameof(Ln.接口路径))] [JsonInclude] + [CsvName(nameof(Ln.接口路径))] public string ApiId => Api.Id; /// - [CsvIgnore(false)] [CsvIndex(6)] + [CsvIgnore(false)] [CsvName(nameof(Ln.客户端IP))] public override string CreatedClientIp => base.CreatedClientIp; @@ -28,8 +28,8 @@ public record ExportRequestLogRsp : QueryRequestLogRsp /// 用户名 /// [CsvIndex(5)] - [CsvName(nameof(Ln.用户名))] [JsonInclude] + [CsvName(nameof(Ln.用户名))] public string UserName => Owner?.UserName; /// @@ -37,7 +37,9 @@ public record ExportRequestLogRsp : QueryRequestLogRsp public override QueryApiRsp Api { get; init; } /// - [CsvIgnore] + [CsvIgnore(false)] + [CsvIndex(8)] + [CsvName(nameof(Ln.创建时间))] public override DateTime CreatedTime { get; init; } /// @@ -45,38 +47,36 @@ public record ExportRequestLogRsp : QueryRequestLogRsp public override QueryRequestLogDetailRsp Detail { get; init; } /// - [CsvIgnore(false)] [CsvIndex(4)] + [CsvIgnore(false)] [CsvName(nameof(Ln.执行耗时))] public override int Duration { get; init; } /// - [CsvIgnore(false)] [CsvIndex(3)] + [CsvIgnore(false)] [CsvName(nameof(Ln.请求方式))] public override HttpMethods HttpMethod { get; init; } /// - [CsvIgnore(false)] [CsvIndex(1)] + [CsvIgnore(false)] [CsvName(nameof(Ln.响应状态码))] public override int HttpStatusCode { get; init; } /// - [CsvIgnore(false)] [CsvIndex(0)] + [CsvIgnore(false)] [CsvName(nameof(Ln.唯一编码))] public override long Id { get; init; } /// [CsvIgnore] - public override QueryUserLiteRsp Owner { get; init; } + public override QueryUserRsp Owner { get; init; } /// - [CsvIgnore] - public override long? OwnerDeptId { get; init; } - - /// - [CsvIgnore] - public override long? OwnerId { get; init; } + [CsvIndex(7)] + [CsvIgnore(false)] + [CsvName(nameof(Ln.跟踪标识))] + public override Guid TraceId { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogReq.cs b/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogReq.cs index ca81e857..0a2ee62d 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogReq.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogReq.cs @@ -3,4 +3,9 @@ namespace NetAdmin.Domain.Dto.Sys.RequestLog; /// /// 请求:查询请求日志 /// -public sealed record QueryRequestLogReq : Sys_RequestLog; \ No newline at end of file +public sealed record QueryRequestLogReq : Sys_RequestLog +{ + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override DateTime CreatedTime { get; init; } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogRsp.cs index 6978037e..66c0f7a8 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogRsp.cs @@ -46,9 +46,13 @@ public record QueryRequestLogRsp : Sys_RequestLog /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public new virtual QueryUserLiteRsp Owner { get; init; } + public new virtual QueryUserRsp Owner { get; init; } /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public override long? OwnerId { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override Guid TraceId { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/RequestLogDetail/QueryRequestLogDetailRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/RequestLogDetail/QueryRequestLogDetailRsp.cs index 1b04be0e..eaaf33c4 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/RequestLogDetail/QueryRequestLogDetailRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/RequestLogDetail/QueryRequestLogDetailRsp.cs @@ -66,8 +66,4 @@ public sealed record QueryRequestLogDetailRsp : Sys_RequestLogDetail /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public override int? ServerIp { get; init; } - - /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public override string TraceId { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Role/ExportRoleRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Role/ExportRoleRsp.cs index 291ada57..da2f5038 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Role/ExportRoleRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Role/ExportRoleRsp.cs @@ -8,50 +8,50 @@ namespace NetAdmin.Domain.Dto.Sys.Role; public sealed record ExportRoleRsp : QueryRoleRsp { /// - [CsvIgnore(false)] [CsvIndex(7)] + [CsvIgnore(false)] [CsvName(nameof(Ln.创建时间))] public override DateTime CreatedTime { get; init; } /// - [CsvIgnore(false)] [CsvIndex(4)] + [CsvIgnore(false)] [CsvName(nameof(Ln.数据范围))] public override DataScopes DataScope { get; init; } /// - [CsvIgnore(false)] [CsvIndex(5)] + [CsvIgnore(false)] [CsvName(nameof(Ln.显示仪表板))] public override bool DisplayDashboard { get; init; } /// - [CsvIgnore(false)] [CsvIndex(6)] + [CsvIgnore(false)] [CsvName(nameof(Ln.是否启用))] public override bool Enabled { get; init; } /// - [CsvIgnore(false)] [CsvIndex(0)] + [CsvIgnore(false)] [CsvName(nameof(Ln.唯一编码))] public override long Id { get; init; } /// - [CsvIgnore(false)] [CsvIndex(3)] + [CsvIgnore(false)] [CsvName(nameof(Ln.无限权限))] public override bool IgnorePermissionControl { get; init; } /// - [CsvIgnore(false)] [CsvIndex(1)] + [CsvIgnore(false)] [CsvName(nameof(Ln.角色名称))] public override string Name { get; init; } /// - [CsvIgnore(false)] [CsvIndex(2)] + [CsvIgnore(false)] [CsvName(nameof(Ln.排序))] public override long Sort { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/SiteMsg/ExportSiteMsgRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/SiteMsg/ExportSiteMsgRsp.cs index 5bddc162..036691c9 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/SiteMsg/ExportSiteMsgRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/SiteMsg/ExportSiteMsgRsp.cs @@ -11,14 +11,14 @@ namespace NetAdmin.Domain.Dto.Sys.SiteMsg; public record ExportSiteMsgRsp : QuerySiteMsgRsp { /// - [CsvIgnore(false)] [CsvIndex(5)] + [CsvIgnore(false)] [CsvName(nameof(Ln.创建时间))] public override DateTime CreatedTime { get; init; } /// - [CsvIgnore(false)] [CsvIndex(1)] + [CsvIgnore(false)] [CsvName(nameof(Ln.用户名))] public override string CreatedUserName { get; init; } @@ -27,14 +27,14 @@ public record ExportSiteMsgRsp : QuerySiteMsgRsp public override IEnumerable Depts { get; init; } /// - [CsvIgnore(false)] [CsvIndex(0)] + [CsvIgnore(false)] [CsvName(nameof(Ln.唯一编码))] public override long Id { get; init; } /// - [CsvIgnore(false)] [CsvIndex(2)] + [CsvIgnore(false)] [CsvName(nameof(Ln.消息类型))] public override SiteMsgTypes MsgType { get; init; } @@ -43,14 +43,14 @@ public record ExportSiteMsgRsp : QuerySiteMsgRsp public override IEnumerable Roles { get; init; } /// - [CsvIgnore(false)] [CsvIndex(4)] + [CsvIgnore(false)] [CsvName(nameof(Ln.消息摘要))] public override string Summary { get; init; } /// - [CsvIgnore(false)] [CsvIndex(3)] + [CsvIgnore(false)] [CsvName(nameof(Ln.消息主题))] public override string Title { get; init; } diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/User/ExportUserRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/User/ExportUserRsp.cs index 546aa748..31ae043b 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/User/ExportUserRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/User/ExportUserRsp.cs @@ -9,8 +9,8 @@ namespace NetAdmin.Domain.Dto.Sys.User; public record ExportUserRsp : QueryUserRsp { /// - [CsvIgnore(false)] [CsvIndex(7)] + [CsvIgnore(false)] [CsvName(nameof(Ln.创建时间))] public override DateTime CreatedTime { get; init; } @@ -26,26 +26,26 @@ public record ExportUserRsp : QueryUserRsp public string DeptName { get; init; } /// - [CsvIgnore(false)] [CsvIndex(3)] + [CsvIgnore(false)] [CsvName(nameof(Ln.邮箱号))] public override string Email { get; init; } /// - [CsvIgnore(false)] [CsvIndex(6)] + [CsvIgnore(false)] [CsvName(nameof(Ln.是否启用))] public override bool Enabled { get; init; } /// - [CsvIgnore(false)] [CsvIndex(0)] + [CsvIgnore(false)] [CsvName(nameof(Ln.唯一编码))] public override long Id { get; init; } /// - [CsvIgnore(false)] [CsvIndex(2)] + [CsvIgnore(false)] [CsvName(nameof(Ln.手机号))] public override string Mobile { get; init; } @@ -61,8 +61,8 @@ public record ExportUserRsp : QueryUserRsp public override IEnumerable Roles { get; init; } /// - [CsvIgnore(false)] [CsvIndex(1)] + [CsvIgnore(false)] [CsvName(nameof(Ln.用户名))] public override string UserName { get; init; } diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/User/QueryUserLiteRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/User/QueryUserLiteRsp.cs deleted file mode 100644 index 13e5eff0..00000000 --- a/src/backend/NetAdmin.Domain/Dto/Sys/User/QueryUserLiteRsp.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace NetAdmin.Domain.Dto.Sys.User; - -/// -/// 响应:查询用户精简版 -/// -public record QueryUserLiteRsp : Sys_User -{ - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Never)] - public override long Id { get; init; } - - /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public override string UserName { get; init; } -} \ No newline at end of file diff --git a/src/backend/NetAdmin.Host/BackgroundRunning/WorkBase.cs b/src/backend/NetAdmin.Host/BackgroundRunning/WorkBase.cs index 334067f8..2e544f65 100644 --- a/src/backend/NetAdmin.Host/BackgroundRunning/WorkBase.cs +++ b/src/backend/NetAdmin.Host/BackgroundRunning/WorkBase.cs @@ -72,6 +72,6 @@ public abstract class WorkBase { 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)); + , TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_RETRY_INTERVAL)); } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Host/Utils/RequestLogger.cs b/src/backend/NetAdmin.Host/Utils/RequestLogger.cs index a60b3b28..5c13cfd8 100644 --- a/src/backend/NetAdmin.Host/Utils/RequestLogger.cs +++ b/src/backend/NetAdmin.Host/Utils/RequestLogger.cs @@ -44,7 +44,6 @@ public sealed class RequestLogger(ILogger logger, IEventPublisher , ResponseContentType = context.Response.ContentType , ResponseHeaders = context.Response.Headers.Json() , ServerIp = context.GetLocalIpAddressToIPv4()?.IpV4ToInt32() - , TraceId = context.TraceIdentifier } , Duration = (int)duration , HttpMethod = Enum.Parse(context.Request.Method, true) @@ -54,6 +53,7 @@ public sealed class RequestLogger(ILogger logger, IEventPublisher , OwnerId = associatedUser?.UserId , OwnerDeptId = associatedUser?.DeptId , Id = id + , TraceId = context.GetTraceId() }; // 打印日志 @@ -74,13 +74,10 @@ public sealed class RequestLogger(ILogger logger, IEventPublisher ContextUserToken userToken = null; try { - var jsonWebToken - = 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(); + userToken = ContextUserToken.Create(token); } catch (Exception ex) { - logger.Warn($"{Ln.读取用户令牌出错}: {ex}"); + logger.Warn($"{Ln.读取用户令牌出错} {ex}"); } return userToken == null ? null : (userToken.Id, userToken.DeptId, userToken.UserName); diff --git a/src/backend/NetAdmin.Infrastructure/Constant/Numbers.cs b/src/backend/NetAdmin.Infrastructure/Constant/Numbers.cs index bf4118aa..33435377 100644 --- a/src/backend/NetAdmin.Infrastructure/Constant/Numbers.cs +++ b/src/backend/NetAdmin.Infrastructure/Constant/Numbers.cs @@ -24,12 +24,12 @@ public static class Numbers public const int MAX_LIMIT_QUERY_PAGE_NO = 10000; // 最大限制:分页查询页码 public const int MAX_LIMIT_QUERY_PAGE_SIZE = 100; // 最大限制:分页查询页容量 - public const int SECS_CACHE_CHART = 300; // 秒:缓存时间-仪表 - public const int SECS_CACHE_DEFAULT = 60; // 秒:缓存时间-默认 - public const int SECS_CACHE_DIC_CATALOG_CODE = 300; // 秒:缓存时间-字典配置-目录代码 - 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; // 秒:超时时间-作业 + public const int SECS_CACHE_CHART = 300; // 秒:缓存时间-仪表 + public const int SECS_CACHE_DEFAULT = 60; // 秒:缓存时间-默认 + public const int SECS_CACHE_DIC_CATALOG_CODE = 300; // 秒:缓存时间-字典配置-目录代码 + public const int SECS_RED_LOCK_EXPIRY = 30; // 秒:RedLock-锁过期时间,假如持有锁的进程挂掉,最多在此时间内锁将被释放(如持有锁的进程正常,此值不会生效) + public const int SECS_RED_LOCK_RETRY_INTERVAL = 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; // 秒:超时时间-作业 } \ No newline at end of file diff --git a/src/backend/NetAdmin.Infrastructure/Extensions/HttpContextExtensions.cs b/src/backend/NetAdmin.Infrastructure/Extensions/HttpContextExtensions.cs index daad770e..a2ec84be 100644 --- a/src/backend/NetAdmin.Infrastructure/Extensions/HttpContextExtensions.cs +++ b/src/backend/NetAdmin.Infrastructure/Extensions/HttpContextExtensions.cs @@ -22,4 +22,12 @@ public static class HttpContextExtensions ? ip2 : me.Connection.RemoteIpAddress; } + + /// + /// 获取跟踪标识 + /// + public static Guid GetTraceId(this HttpContext me) + { + return me.TraceIdentifier.Md5(Encoding.UTF8).Guid(); + } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Infrastructure/Extensions/StringExtensions.cs b/src/backend/NetAdmin.Infrastructure/Extensions/StringExtensions.cs index 27f6e836..f02b26d4 100644 --- a/src/backend/NetAdmin.Infrastructure/Extensions/StringExtensions.cs +++ b/src/backend/NetAdmin.Infrastructure/Extensions/StringExtensions.cs @@ -8,6 +8,8 @@ namespace NetAdmin.Infrastructure.Extensions; /// public static class StringExtensions { + private static readonly Regex _regexIpV4 = new(Chars.RGXL_IP_V4); + /// /// 计算Crc32 /// @@ -27,6 +29,14 @@ public static class StringExtensions me, ScriptOptions.Default.WithReferences(assemblies).WithImports(importNamespaces)); } + /// + /// 是否IPV4地址 + /// + public static bool IsIpV4(this string me) + { + return _regexIpV4.IsMatch(me); + } + /// /// object -> json /// @@ -43,24 +53,6 @@ public static class StringExtensions return me.Object(toType, GlobalStatic.JsonSerializerOptions); } - /// - /// 去掉尾部字符串“Async” - /// - #pragma warning disable RCS1047, ASA002, VSTHRD200 - public static string TrimEndAsync(this string me) - #pragma warning restore VSTHRD200, ASA002, RCS1047 - { - return TrimSuffix(me, "Async"); - } - - /// - /// 去掉尾部字符串“Options” - /// - public static string TrimEndOptions(this string me) - { - return TrimSuffix(me, "Options"); - } - /// /// 去掉前部字符串 /// @@ -69,6 +61,16 @@ public static class StringExtensions return Regex.Replace(me, $"^{clearStr}", string.Empty); } + /// + /// 去掉尾部字符串“Async” + /// + #pragma warning disable RCS1047, ASA002, VSTHRD200 + public static string TrimPrefixAsync(this string me) + #pragma warning restore VSTHRD200, ASA002, RCS1047 + { + return TrimPrefix(me, "Async"); + } + /// /// 去掉尾部字符串 /// @@ -76,4 +78,12 @@ public static class StringExtensions { return Regex.Replace(me, $"{clearStr}$", string.Empty); } + + /// + /// 去掉尾部字符串“Options” + /// + public static string TrimSuffixOptions(this string me) + { + return TrimPrefix(me, "Options"); + } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj b/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj index a3cfa2b6..69faa155 100644 --- a/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj +++ b/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj @@ -15,7 +15,7 @@ - + diff --git a/src/backend/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs b/src/backend/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs index d3b3aefb..edc4f65c 100644 --- a/src/backend/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs +++ b/src/backend/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs @@ -15,7 +15,8 @@ public sealed class FreeSqlBuilder(DatabaseOptions databaseOptions) { var freeSql = new FreeSql.FreeSqlBuilder().UseConnectionString(databaseOptions.DbType, databaseOptions.ConnStr) .UseGenerateCommandParameterWithLambda(true) - .UseAutoSyncStructure(false) + .UseAutoSyncStructure( + initMethods.HasFlag(FreeSqlInitMethods.SyncStructure)) .Build(); _ = InitDbAsync(freeSql, initMethods); // 初始化数据库 ,异步 diff --git a/src/backend/NetAdmin.Infrastructure/Utils/XmlCommentReader.cs b/src/backend/NetAdmin.Infrastructure/Utils/XmlCommentReader.cs index d2ad990a..599c1ade 100644 --- a/src/backend/NetAdmin.Infrastructure/Utils/XmlCommentReader.cs +++ b/src/backend/NetAdmin.Infrastructure/Utils/XmlCommentReader.cs @@ -18,7 +18,7 @@ public sealed class XmlCommentReader : ISingleton { var xmlComments = specificationDocumentSettings.Value.XmlComments // ?? App.GetConfig( - nameof(SpecificationDocumentSettingsOptions).TrimEndOptions()) + nameof(SpecificationDocumentSettingsOptions).TrimSuffixOptions()) .XmlComments; foreach (var commentFile in xmlComments.Where(x => x.Contains(nameof(NetAdmin)))) { var xmlDoc = new XmlDocument(); diff --git a/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/ICacheModule.cs b/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/ICacheModule.cs index 1d95a7bc..642d072d 100644 --- a/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/ICacheModule.cs +++ b/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/ICacheModule.cs @@ -1,4 +1,3 @@ -using NetAdmin.Domain.Dto.Dependency; using NetAdmin.Domain.Dto.Sys.Cache; namespace NetAdmin.SysComponent.Application.Modules.Sys; @@ -16,5 +15,10 @@ public interface ICacheModule /// /// 获取所有缓存项 /// - Task> GetAllEntriesAsync(PagedQueryReq req); + Task> GetAllEntriesAsync(GetAllEntriesReq req); + + /// + /// 获取缓存项 + /// + Task GetEntryAsync(GetEntriesReq req); } \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/ILoginLogModule.cs b/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/ILoginLogModule.cs new file mode 100644 index 00000000..a88bba14 --- /dev/null +++ b/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/ILoginLogModule.cs @@ -0,0 +1,13 @@ +using NetAdmin.Application.Modules; +using NetAdmin.Domain.Dto.Dependency; +using NetAdmin.Domain.Dto.Sys.LoginLog; + +namespace NetAdmin.SysComponent.Application.Modules.Sys; + +/// +/// 登录日志模块 +/// +public interface ILoginLogModule : ICrudModule; \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/ApiService.cs b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/ApiService.cs index 46b08e4c..49078079 100644 --- a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/ApiService.cs +++ b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/ApiService.cs @@ -8,10 +8,11 @@ namespace NetAdmin.SysComponent.Application.Services.Sys; /// public sealed class ApiService( - BasicRepository rpo // - , XmlCommentReader xmlCommentReader // - , IActionDescriptorCollectionProvider actionDescriptorCollectionProvider) // - : RepositoryService(rpo), IApiService + BasicRepository rpo // + , XmlCommentReader xmlCommentReader // + , IActionDescriptorCollectionProvider actionDescriptorCollectionProvider + , RedLocker redLocker) // + : RedLockerService(rpo, redLocker), IApiService { /// public Task BulkDeleteAsync(BulkReq req) @@ -125,6 +126,7 @@ public sealed class ApiService( /// public async Task SyncAsync() { + await using var locker = await GetLockerOnceAsync(nameof(SyncAsync)).ConfigureAwait(false); _ = await Rpo.DeleteAsync(_ => true).ConfigureAwait(false); var list = ReflectionList(false); diff --git a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/CacheService.cs b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/CacheService.cs index f97f1e6c..7783f24b 100644 --- a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/CacheService.cs +++ b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/CacheService.cs @@ -1,5 +1,5 @@ +using System.Collections.Concurrent; using NetAdmin.Application.Services; -using NetAdmin.Domain.Dto.Dependency; using NetAdmin.Domain.Dto.Sys.Cache; using NetAdmin.SysComponent.Application.Services.Sys.Dependency; using StackExchange.Redis; @@ -31,23 +31,58 @@ public sealed class CacheService(IConnectionMultiplexer connectionMultiplexer) / } /// - public async Task> GetAllEntriesAsync(PagedQueryReq req) + public async Task> GetAllEntriesAsync(GetAllEntriesReq req) { req.ThrowIfInvalid(); + #pragma warning disable VSTHRD103 + var server = connectionMultiplexer.GetServers()[0]; + var database = connectionMultiplexer.GetDatabase(_redisInstance.Database); - var redisResults = (RedisResult[])await database - .ExecuteAsync("scan", (req.Page - 1) * req.PageSize, "count" - , req.PageSize) - .ConfigureAwait(false); + var keys = server.Keys(_redisInstance.Database, $"*{req.Keywords}*", Numbers.MAX_LIMIT_BULK_REQ) + .Take(Numbers.MAX_LIMIT_BULK_REQ) + .ToList(); + #pragma warning restore VSTHRD103 - var list = ((string[])redisResults![1])!.Where(x => database.KeyType(x) == RedisType.Hash) - .Select(x => database.HashGetAll(x) - .Append(new HashEntry("key", x)) - .ToArray() - .ToStringDictionary()) - .ToList() - .ConvertAll(x => x.Adapt()); + var dic = new ConcurrentDictionary(); - return new PagedQueryRsp(req.Page, req.PageSize, 10000, list); + await Parallel + .ForEachAsync( + keys + , async (key, _) => + dic.TryAdd( + key + , (DateTime.Now + await database.KeyTimeToLiveAsync(key).ConfigureAwait(false) + , await database.KeyTypeAsync(key).ConfigureAwait(false)))) + .ConfigureAwait(false); + return dic.Select(x => new GetEntryRsp { Key = x.Key, ExpireTime = x.Value.Item1, Type = x.Value.Item2 }); + } + + /// + public async Task GetEntryAsync(GetEntriesReq req) + { + var database = connectionMultiplexer.GetDatabase(_redisInstance.Database); + + var ret = new GetEntryRsp { + Type = await database.KeyTypeAsync(req.Key).ConfigureAwait(false) + , Key = req.Key + , ExpireTime = DateTime.Now + + await database.KeyTimeToLiveAsync(req.Key).ConfigureAwait(false) + }; + + #pragma warning disable IDE0072 + ret.Data = ret.Type switch + #pragma warning restore IDE0072 + { + RedisType.String => await database.StringGetAsync(req.Key).ConfigureAwait(false) + , RedisType.List => string.Join(", ", await database.ListRangeAsync(req.Key).ConfigureAwait(false)) + , RedisType.Set => string.Join(", ", await database.SetMembersAsync(req.Key).ConfigureAwait(false)) + , RedisType.SortedSet => + string.Join(", ", await database.SortedSetRangeByRankAsync(req.Key).ConfigureAwait(false)) + , RedisType.Hash => string.Join( + ", ", await database.HashGetAllAsync(req.Key).ConfigureAwait(false)) + , _ => "Unsupported key type" + }; + + return ret; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/Dependency/ILoginLogService.cs b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/Dependency/ILoginLogService.cs new file mode 100644 index 00000000..e9f3d4b3 --- /dev/null +++ b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/Dependency/ILoginLogService.cs @@ -0,0 +1,9 @@ +using NetAdmin.Application.Services; +using NetAdmin.SysComponent.Application.Modules.Sys; + +namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency; + +/// +/// 登录日志服务 +/// +public interface ILoginLogService : IService, ILoginLogModule; \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/LoginLogService.cs b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/LoginLogService.cs new file mode 100644 index 00000000..ad9d13c7 --- /dev/null +++ b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/LoginLogService.cs @@ -0,0 +1,150 @@ +using NetAdmin.Application.Repositories; +using NetAdmin.Application.Services; +using NetAdmin.Domain.Dto.Dependency; +using NetAdmin.Domain.Dto.Sys.LoginLog; +using NetAdmin.SysComponent.Application.Services.Sys.Dependency; + +namespace NetAdmin.SysComponent.Application.Services.Sys; + +/// +public sealed class LoginLogService(BasicRepository rpo) // + : RepositoryService(rpo), ILoginLogService +{ + /// + public async Task BulkDeleteAsync(BulkReq req) + { + req.ThrowIfInvalid(); + var ret = 0; + + // ReSharper disable once LoopCanBeConvertedToQuery + foreach (var item in req.Items) { + ret += await DeleteAsync(item).ConfigureAwait(false); + } + + return ret; + } + + /// + public Task CountAsync(QueryReq req) + { + req.ThrowIfInvalid(); + return QueryInternal(req) + #if DBTYPE_SQLSERVER + .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait) + #endif + .CountAsync(); + } + + /// + public async Task CreateAsync(CreateLoginLogReq req) + { + req.ThrowIfInvalid(); + var ret = await Rpo.InsertAsync(req).ConfigureAwait(false); + return ret.Adapt(); + } + + /// + public Task DeleteAsync(DelReq req) + { + req.ThrowIfInvalid(); + return Rpo.DeleteAsync(a => a.Id == req.Id); + } + + /// + public Task ExistAsync(QueryReq req) + { + req.ThrowIfInvalid(); + return QueryInternal(req) + #if DBTYPE_SQLSERVER + .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait) + #endif + .AnyAsync(); + } + + /// + public Task ExportAsync(QueryReq req) + { + req.ThrowIfInvalid(); + return ExportAsync(QueryInternal, req, Ln.登录日志导出); + } + + /// + public async Task GetAsync(QueryLoginLogReq req) + { + req.ThrowIfInvalid(); + var ret = await QueryInternal(new QueryReq { Filter = req }) + .ToOneAsync() + .ConfigureAwait(false); + return ret.Adapt(); + } + + /// + public async Task> PagedQueryAsync(PagedQueryReq req) + { + req.ThrowIfInvalid(); + var list = await QueryInternal(req) + .Include(a => a.Owner) + .Page(req.Page, req.PageSize) + #if DBTYPE_SQLSERVER + .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait) + #endif + .Count(out var total) + .ToListAsync(a => new { + a.CreatedClientIp + , a.CreatedTime + , a.CreatedUserAgent + , a.Duration + , a.ErrorCode + , a.HttpStatusCode + , a.Id + , a.LoginUserName + , Owner = new { a.Owner.Id, a.Owner.UserName } + , a.RequestUrl + , a.ServerIp + }) + .ConfigureAwait(false); + + return new PagedQueryRsp(req.Page, req.PageSize, total, list.Adapt>()); + } + + /// + public async Task> QueryAsync(QueryReq 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>(); + } + + private ISelect QueryInternal(QueryReq req) + { + var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter); + + if (req.Keywords?.Length > 0) { + ret = req.Keywords.IsIpV4() + ? ret.Where(a => a.CreatedClientIp == req.Keywords.IpV4ToInt32()) + : ret.Where(a => a.Id == req.Keywords.Int64Try(0) || a.OwnerId == req.Keywords.Int64Try(0) || + a.LoginUserName == req.Keywords); + } + + // 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; + } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/RequestLogService.cs b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/RequestLogService.cs index 1c323dab..416a5b0c 100644 --- a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/RequestLogService.cs +++ b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/RequestLogService.cs @@ -2,19 +2,16 @@ using NetAdmin.Application.Repositories; using NetAdmin.Application.Services; using NetAdmin.Domain.Dto.Dependency; using NetAdmin.Domain.Dto.Sys; +using NetAdmin.Domain.Dto.Sys.LoginLog; using NetAdmin.Domain.Dto.Sys.RequestLog; using NetAdmin.SysComponent.Application.Services.Sys.Dependency; namespace NetAdmin.SysComponent.Application.Services.Sys; /// -public sealed class RequestLogService( - BasicRepository rpo - , RequestLogDetailService requestLogDetailService) // +public sealed class RequestLogService(BasicRepository rpo, LoginLogService loginLogService) // : RepositoryService(rpo), IRequestLogService { - private static readonly Regex _regex = new(Chars.RGXL_IP_V4); - /// public async Task BulkDeleteAsync(BulkReq req) { @@ -45,7 +42,12 @@ public sealed class RequestLogService( { req.ThrowIfInvalid(); var ret = await Rpo.InsertAsync(req).ConfigureAwait(false); - _ = await requestLogDetailService.CreateAsync(req.Detail).ConfigureAwait(false); + + // 插入登录日志 + if (req.ApiPathCrc32 == Chars.FLG_PATH_API_SYS_USER_LOGIN_BY_PWD.Crc32()) { + _ = await loginLogService.CreateAsync(req.Adapt()).ConfigureAwait(false); + } + return ret.Adapt(); } @@ -88,7 +90,16 @@ public sealed class RequestLogService( public async Task GetAsync(QueryRequestLogReq req) { req.ThrowIfInvalid(); - var ret = await QueryInternal(new QueryReq { Filter = req }) + var df = new DynamicFilterInfo { + Field = nameof(QueryRequestLogReq.CreatedTime) + , Operator = DynamicFilterOperators.DateRange + , Value = new[] { + req.CreatedTime.AddHours(-1).yyyy_MM_dd_HH_mm_ss() + , req.CreatedTime.AddHours(1).yyyy_MM_dd_HH_mm_ss() + }.Json() + .Object() + }; + var ret = await QueryInternal(new QueryReq { Filter = req, DynamicFilter = df }) .Include(a => a.Detail) .ToOneAsync() .ConfigureAwait(false); @@ -155,43 +166,27 @@ public sealed class RequestLogService( public async Task> PagedQueryAsync(PagedQueryReq req) { req.ThrowIfInvalid(); - var select = QueryInternal(req) - .Page(req.Page, req.PageSize) - #if DBTYPE_SQLSERVER - .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait) - #endif - .Count(out var total); + var select = QueryInternal(req with { Order = Orders.None }, false); + var selectTemp = select.WithTempQuery(a => new { temp = a }); - 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); + if (req.Order == Orders.Random) { + selectTemp = selectTemp.OrderByRandom(); + } + else { + selectTemp = selectTemp.OrderBy( // + req.Prop?.Length > 0, $"{req.Prop} {(req.Order == Orders.Ascending ? "ASC" : "DESC")}"); + if (!req.Prop?.Equals(nameof(req.Filter.CreatedTime), StringComparison.OrdinalIgnoreCase) ?? true) { + selectTemp = selectTemp.OrderByDescending(a => a.temp.CreatedTime); + } + } + + var ret = await selectTemp.Page(req.Page, req.PageSize) + #if DBTYPE_SQLSERVER + .WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait) + #endif + .Count(out var total) + .ToListAsync(a => a.temp) + .ConfigureAwait(false); return new PagedQueryRsp(req.Page, req.PageSize, total , ret.Adapt>()); @@ -229,10 +224,9 @@ public sealed class RequestLogService( } if (req.Keywords?.Length > 0) { - ret = _regex.IsMatch(req.Keywords) + ret = req.Keywords.IsIpV4() ? ret.Where(a => a.CreatedClientIp == req.Keywords.IpV4ToInt32()) - : ret.Where(a => a.Id == req.Keywords.Int64Try(0) || a.OwnerId == req.Keywords.Int64Try(0) || - a.Owner.UserName == req.Keywords); + : ret.Where(a => a.Id == req.Keywords.Int64Try(0) || a.OwnerId == req.Keywords.Int64Try(0)); } // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault diff --git a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/ToolsService.cs b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/ToolsService.cs index 78a9b921..cd5f547b 100644 --- a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/ToolsService.cs +++ b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/ToolsService.cs @@ -18,14 +18,15 @@ public sealed class ToolsService : ServiceBase, IToolsService /// public Task> GetModulesAsync() { - return Task.FromResult>( // - AppDomain.CurrentDomain.GetAssemblies() - .Where(x => !x.FullName?.Contains('#') ?? false) - .Select(x => { - var asm = x.GetName(); - return new GetModulesRsp { Name = asm.Name, Version = asm.Version?.ToString() }; - }) - .OrderBy(x => x.Name)); + return Task.FromResult>(AppDomain.CurrentDomain.GetAssemblies() + .Select(x => { + var asm = x.GetName(); + return new GetModulesRsp { + Name = asm.Name + , Version = asm.Version?.ToString() + }; + }) + .OrderBy(x => x.Name)); } /// diff --git a/src/backend/NetAdmin.SysComponent.Cache/Sys/CacheCache.cs b/src/backend/NetAdmin.SysComponent.Cache/Sys/CacheCache.cs index 7db94658..5047cfce 100644 --- a/src/backend/NetAdmin.SysComponent.Cache/Sys/CacheCache.cs +++ b/src/backend/NetAdmin.SysComponent.Cache/Sys/CacheCache.cs @@ -1,5 +1,4 @@ using NetAdmin.Cache; -using NetAdmin.Domain.Dto.Dependency; using NetAdmin.Domain.Dto.Sys.Cache; using NetAdmin.SysComponent.Application.Services.Sys.Dependency; using NetAdmin.SysComponent.Cache.Sys.Dependency; @@ -22,8 +21,14 @@ public sealed class CacheCache(IDistributedCache cache, ICacheService service) / } /// - public Task> GetAllEntriesAsync(PagedQueryReq req) + public Task> GetAllEntriesAsync(GetAllEntriesReq req) { return Service.GetAllEntriesAsync(req); } + + /// + public Task GetEntryAsync(GetEntriesReq req) + { + return Service.GetEntryAsync(req); + } } \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Cache/Sys/Dependency/ILoginLogCache.cs b/src/backend/NetAdmin.SysComponent.Cache/Sys/Dependency/ILoginLogCache.cs new file mode 100644 index 00000000..3fb4400d --- /dev/null +++ b/src/backend/NetAdmin.SysComponent.Cache/Sys/Dependency/ILoginLogCache.cs @@ -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; + +/// +/// 登录日志缓存 +/// +public interface ILoginLogCache : ICache, ILoginLogModule; \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Cache/Sys/LoginLogCache.cs b/src/backend/NetAdmin.SysComponent.Cache/Sys/LoginLogCache.cs new file mode 100644 index 00000000..d5167d30 --- /dev/null +++ b/src/backend/NetAdmin.SysComponent.Cache/Sys/LoginLogCache.cs @@ -0,0 +1,66 @@ +using NetAdmin.Cache; +using NetAdmin.Domain.Dto.Dependency; +using NetAdmin.Domain.Dto.Sys.LoginLog; +using NetAdmin.SysComponent.Application.Services.Sys.Dependency; +using NetAdmin.SysComponent.Cache.Sys.Dependency; + +namespace NetAdmin.SysComponent.Cache.Sys; + +/// +public sealed class LoginLogCache(IDistributedCache cache, ILoginLogService service) + : DistributedCache(cache, service), IScoped, ILoginLogCache +{ + /// + public Task BulkDeleteAsync(BulkReq req) + { + return Service.BulkDeleteAsync(req); + } + + /// + public Task CountAsync(QueryReq req) + { + return Service.CountAsync(req); + } + + /// + public Task CreateAsync(CreateLoginLogReq req) + { + return Service.CreateAsync(req); + } + + /// + public Task DeleteAsync(DelReq req) + { + return Service.DeleteAsync(req); + } + + /// + public Task ExistAsync(QueryReq req) + { + return Service.ExistAsync(req); + } + + /// + public Task ExportAsync(QueryReq req) + { + return Service.ExportAsync(req); + } + + /// + public Task GetAsync(QueryLoginLogReq req) + { + return Service.GetAsync(req); + } + + /// + public Task> PagedQueryAsync(PagedQueryReq req) + { + return Service.PagedQueryAsync(req); + } + + /// + public Task> QueryAsync(QueryReq req) + { + return Service.QueryAsync(req); + } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/CacheController.cs b/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/CacheController.cs index 9b840309..dc65a052 100644 --- a/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/CacheController.cs +++ b/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/CacheController.cs @@ -1,4 +1,3 @@ -using NetAdmin.Domain.Dto.Dependency; using NetAdmin.Domain.Dto.Sys.Cache; using NetAdmin.Host.Controllers; using NetAdmin.SysComponent.Application.Modules.Sys; @@ -24,8 +23,16 @@ public sealed class CacheController(ICacheCache cache) : ControllerBase /// 获取所有缓存项 /// - public Task> GetAllEntriesAsync(PagedQueryReq req) + public Task> GetAllEntriesAsync(GetAllEntriesReq req) { return Cache.GetAllEntriesAsync(req); } + + /// + /// 获取缓存项 + /// + public Task GetEntryAsync(GetEntriesReq req) + { + return Cache.GetEntryAsync(req); + } } \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/LoginLogController.cs b/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/LoginLogController.cs new file mode 100644 index 00000000..819a0ed7 --- /dev/null +++ b/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/LoginLogController.cs @@ -0,0 +1,92 @@ +using NetAdmin.Domain.Dto.Dependency; +using NetAdmin.Domain.Dto.Sys.LoginLog; +using NetAdmin.Host.Attributes; +using NetAdmin.Host.Controllers; +using NetAdmin.SysComponent.Application.Modules.Sys; +using NetAdmin.SysComponent.Application.Services.Sys.Dependency; +using NetAdmin.SysComponent.Cache.Sys.Dependency; + +namespace NetAdmin.SysComponent.Host.Controllers.Sys; + +/// +/// 登录日志服务 +/// +[ApiDescriptionSettings(nameof(Sys), Module = nameof(Sys))] +public sealed class LoginLogController(ILoginLogCache cache) : ControllerBase(cache) + , ILoginLogModule +{ + /// + /// 批量删除登录日志 + /// + [Transaction] + public Task BulkDeleteAsync(BulkReq req) + { + return Cache.BulkDeleteAsync(req); + } + + /// + /// 登录日志计数 + /// + public Task CountAsync(QueryReq req) + { + return Cache.CountAsync(req); + } + + /// + /// 创建登录日志 + /// + [Transaction] + public Task CreateAsync(CreateLoginLogReq req) + { + return Cache.CreateAsync(req); + } + + /// + /// 删除登录日志 + /// + [Transaction] + public Task DeleteAsync(DelReq req) + { + return Cache.DeleteAsync(req); + } + + /// + /// 登录日志是否存在 + /// + public Task ExistAsync(QueryReq req) + { + return Cache.ExistAsync(req); + } + + /// + /// 导出登录日志 + /// + public Task ExportAsync(QueryReq req) + { + return Cache.ExportAsync(req); + } + + /// + /// 获取单个登录日志 + /// + public Task GetAsync(QueryLoginLogReq req) + { + return Cache.GetAsync(req); + } + + /// + /// 分页查询登录日志 + /// + public Task> PagedQueryAsync(PagedQueryReq req) + { + return Cache.PagedQueryAsync(req); + } + + /// + /// 查询登录日志 + /// + public Task> QueryAsync(QueryReq req) + { + return Cache.QueryAsync(req); + } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/LogController.cs b/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/RequestLogController.cs similarity index 94% rename from src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/LogController.cs rename to src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/RequestLogController.cs index 3649ecb1..85fa2b8d 100644 --- a/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/LogController.cs +++ b/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/RequestLogController.cs @@ -13,8 +13,8 @@ namespace NetAdmin.SysComponent.Host.Controllers.Sys; /// 请求日志服务 /// [ApiDescriptionSettings(nameof(Sys), Module = nameof(Sys))] -public sealed class LogController(IRequestLogCache cache) : ControllerBase(cache) - , IRequestLogModule +public sealed class RequestLogController(IRequestLogCache cache) + : ControllerBase(cache), IRequestLogModule { /// /// 批量删除请求日志 diff --git a/src/frontend/admin/src/api/sys/cache.js b/src/frontend/admin/src/api/sys/cache.js index 4cfa220b..ee433c0f 100644 --- a/src/frontend/admin/src/api/sys/cache.js +++ b/src/frontend/admin/src/api/sys/cache.js @@ -26,4 +26,15 @@ export default { return await http.post(this.url, data, config) }, }, + + /** + * 获取缓存项 + */ + getEntry: { + url: `${config.API_URL}/api/sys/cache/get.entry`, + name: `获取缓存项`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, } \ No newline at end of file diff --git a/src/frontend/admin/src/api/sys/loginlog.js b/src/frontend/admin/src/api/sys/loginlog.js new file mode 100644 index 00000000..fb82c38a --- /dev/null +++ b/src/frontend/admin/src/api/sys/loginlog.js @@ -0,0 +1,106 @@ +/** + * 登录日志服务 + * @module @/api/sys/login.log + */ +import config from '@/config' +import http from '@/utils/request' +export default { + /** + * 批量删除登录日志 + */ + bulkDelete: { + url: `${config.API_URL}/api/sys/login.log/bulk.delete`, + name: `批量删除登录日志`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, + + /** + * 登录日志计数 + */ + count: { + url: `${config.API_URL}/api/sys/login.log/count`, + name: `登录日志计数`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, + + /** + * 创建登录日志 + */ + create: { + url: `${config.API_URL}/api/sys/login.log/create`, + name: `创建登录日志`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, + + /** + * 删除登录日志 + */ + delete: { + url: `${config.API_URL}/api/sys/login.log/delete`, + name: `删除登录日志`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, + + /** + * 登录日志是否存在 + */ + exist: { + url: `${config.API_URL}/api/sys/login.log/exist`, + name: `登录日志是否存在`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, + + /** + * 导出登录日志 + */ + export: { + url: `${config.API_URL}/api/sys/login.log/export`, + name: `导出登录日志`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, + + /** + * 获取单个登录日志 + */ + get: { + url: `${config.API_URL}/api/sys/login.log/get`, + name: `获取单个登录日志`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, + + /** + * 分页查询登录日志 + */ + pagedQuery: { + url: `${config.API_URL}/api/sys/login.log/paged.query`, + name: `分页查询登录日志`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, + + /** + * 查询登录日志 + */ + query: { + url: `${config.API_URL}/api/sys/login.log/query`, + name: `查询登录日志`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, +} \ No newline at end of file diff --git a/src/frontend/admin/src/api/sys/log.js b/src/frontend/admin/src/api/sys/requestlog.js similarity index 77% rename from src/frontend/admin/src/api/sys/log.js rename to src/frontend/admin/src/api/sys/requestlog.js index cbd16aa3..3f1f5fc4 100644 --- a/src/frontend/admin/src/api/sys/log.js +++ b/src/frontend/admin/src/api/sys/requestlog.js @@ -1,6 +1,6 @@ /** * 请求日志服务 - * @module @/api/sys/log + * @module @/api/sys/request.log */ import config from '@/config' import http from '@/utils/request' @@ -9,7 +9,7 @@ export default { * 请求日志计数 */ count: { - url: `${config.API_URL}/api/sys/log/count`, + url: `${config.API_URL}/api/sys/request.log/count`, name: `请求日志计数`, post: async function (data = {}, config = {}) { return await http.post(this.url, data, config) @@ -20,7 +20,7 @@ export default { * 导出请求日志 */ export: { - url: `${config.API_URL}/api/sys/log/export`, + url: `${config.API_URL}/api/sys/request.log/export`, name: `导出请求日志`, post: async function (data = {}, config = {}) { return await http.post(this.url, data, config) @@ -31,7 +31,7 @@ export default { * 获取单个请求日志 */ get: { - url: `${config.API_URL}/api/sys/log/get`, + url: `${config.API_URL}/api/sys/request.log/get`, name: `获取单个请求日志`, post: async function (data = {}, config = {}) { return await http.post(this.url, data, config) @@ -42,7 +42,7 @@ export default { * 获取条形图数据 */ getBarChart: { - url: `${config.API_URL}/api/sys/log/get.bar.chart`, + url: `${config.API_URL}/api/sys/request.log/get.bar.chart`, name: `获取条形图数据`, post: async function (data = {}, config = {}) { return await http.post(this.url, data, config) @@ -53,7 +53,7 @@ export default { * 描述分组饼图数据 */ getPieChartByApiSummary: { - url: `${config.API_URL}/api/sys/log/get.pie.chart.by.api.summary`, + url: `${config.API_URL}/api/sys/request.log/get.pie.chart.by.api.summary`, name: `描述分组饼图数据`, post: async function (data = {}, config = {}) { return await http.post(this.url, data, config) @@ -64,7 +64,7 @@ export default { * 状态码分组饼图数据 */ getPieChartByHttpStatusCode: { - url: `${config.API_URL}/api/sys/log/get.pie.chart.by.http.status.code`, + url: `${config.API_URL}/api/sys/request.log/get.pie.chart.by.http.status.code`, name: `状态码分组饼图数据`, post: async function (data = {}, config = {}) { return await http.post(this.url, data, config) @@ -75,7 +75,7 @@ export default { * 分页查询请求日志 */ pagedQuery: { - url: `${config.API_URL}/api/sys/log/paged.query`, + url: `${config.API_URL}/api/sys/request.log/paged.query`, name: `分页查询请求日志`, post: async function (data = {}, config = {}) { return await http.post(this.url, data, config) @@ -86,7 +86,7 @@ export default { * 查询请求日志 */ query: { - url: `${config.API_URL}/api/sys/log/query`, + url: `${config.API_URL}/api/sys/request.log/query`, name: `查询请求日志`, post: async function (data = {}, config = {}) { return await http.post(this.url, data, config) diff --git a/src/frontend/admin/src/components/naColUser/index.vue b/src/frontend/admin/src/components/naColUser/index.vue index 49f92dbd..ed3755ad 100644 --- a/src/frontend/admin/src/components/naColUser/index.vue +++ b/src/frontend/admin/src/components/naColUser/index.vue @@ -4,7 +4,7 @@
+ class="el-table-column-avatar">

{{ $TOOL.getNestedProperty(row, $attrs.nestProp) }}

@@ -44,18 +44,4 @@ export default { watch: {}, } - \ No newline at end of file + \ No newline at end of file diff --git a/src/frontend/admin/src/components/naIp/index.vue b/src/frontend/admin/src/components/naIp/index.vue index aa6c6498..ee01e838 100644 --- a/src/frontend/admin/src/components/naIp/index.vue +++ b/src/frontend/admin/src/components/naIp/index.vue @@ -17,7 +17,7 @@ export default { created() { if (this.ip) { this.region = '...' - http.get(`http://ip.line92.com/?ip=${this.ip}`).then((x) => { + http.get(`http://ip.line92.xyz/?ip=${this.ip}`).then((x) => { this.region = x.region }) } diff --git a/src/frontend/admin/src/components/scTable/fieldFilter.vue b/src/frontend/admin/src/components/scTable/fieldFilter.vue new file mode 100644 index 00000000..ef77ca19 --- /dev/null +++ b/src/frontend/admin/src/components/scTable/fieldFilter.vue @@ -0,0 +1,51 @@ + + + \ No newline at end of file diff --git a/src/frontend/admin/src/components/scTable/index.vue b/src/frontend/admin/src/components/scTable/index.vue index 4381e531..83d9e684 100644 --- a/src/frontend/admin/src/components/scTable/index.vue +++ b/src/frontend/admin/src/components/scTable/index.vue @@ -200,12 +200,14 @@ + diff --git a/src/frontend/admin/src/views/sys/cache/index.vue b/src/frontend/admin/src/views/sys/cache/index.vue index 5687bc85..31698ef0 100644 --- a/src/frontend/admin/src/views/sys/cache/index.vue +++ b/src/frontend/admin/src/views/sys/cache/index.vue @@ -52,14 +52,34 @@
- - - - - - - + +
+
+
+
+ + + + + + + @@ -74,14 +94,14 @@ export default { }, data() { return { + loading: true, dialog: { info: false, }, query: { - filter: { - dbIndex: 1, - }, + keywords: '', }, + tableData: [], statistics: { keyspaceHits: 0, keyspaceMisses: 0, @@ -93,10 +113,32 @@ export default { } }, methods: { + reset() { + this.query.keywords = '' + this.search() + }, + search() { + this.getData() + }, async rowClick(row) { + this.loading = true + const res = await this.$API.sys_cache.getEntry.post({ key: row.key }) this.dialog.info = true await this.$nextTick() - this.$refs.info.open(this.$TOOL.sortProperties(row), this.$t('缓存详情')) + this.$refs.info.open(this.$TOOL.sortProperties(res.data), this.$t('缓存详情')) + this.loading = false + }, + async getData() { + this.loading = true + try { + const res = await this.$API.sys_cache.getAllEntries.post(this.query) + if (res.data) { + this.tableData = res.data + } + } catch { + // + } + this.loading = false }, async cacheStatistics() { try { @@ -109,15 +151,9 @@ export default { } }, }, - mounted() { + created() { this.cacheStatistics() - }, - watch: { - 'query.filter.dbIndex': { - handler() { - this.$refs.table.upData() - }, - }, + this.getData() }, } diff --git a/src/frontend/admin/src/views/sys/log/login/index.vue b/src/frontend/admin/src/views/sys/log/login/index.vue index 77cdf81d..cf3e3121 100644 --- a/src/frontend/admin/src/views/sys/log/login/index.vue +++ b/src/frontend/admin/src/views/sys/log/login/index.vue @@ -2,6 +2,7 @@
- + - - + + @@ -104,15 +109,29 @@ width="90"> - + width="170"> + +