From 6f890151989ad733e35653933b7597eec478cc3b Mon Sep 17 00:00:00 2001 From: nsnail Date: Sun, 18 Feb 2024 14:43:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20=E8=AE=A1=E5=88=92=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A=E6=89=A7=E8=A1=8C=E8=AE=B0=E5=BD=95=20(#89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 顶部通栏黑夜模式开关 计划作业快捷预览面板 --- Directory.Build.props | 2 +- NetAdmin.sln | 1 + assets/seed-data/Sys_Dept.json | 2 +- assets/seed-data/Sys_Role.json | 2 +- assets/seed-data/Sys_SiteMsg.json | 4 +- build/code.quality.props | 2 +- scripts/2.git.release.ps1 | 2 +- .../Services/RepositoryService.cs | 12 +- src/backend/NetAdmin.Cache/CacheBase.cs | 18 +- .../NetAdmin.Cache/DistributedCache.cs | 9 +- src/backend/NetAdmin.Cache/MemoryCache.cs | 12 +- .../NetAdmin.Domain/DataAbstraction.cs | 9 +- .../DbMaps/Dependency/VersionEntity.cs | 8 +- .../NetAdmin.Domain/DbMaps/Sys/Sys_Job.cs | 7 + .../DbMaps/Sys/Sys_JobRecord.cs | 20 +- .../DbMaps/Sys/Sys_RequestLog.cs | 2 +- .../NetAdmin.Domain/DbMaps/Sys/Sys_RoleApi.cs | 2 +- .../DbMaps/Sys/Sys_RoleDept.cs | 2 +- .../DbMaps/Sys/Sys_UserRole.cs | 2 +- .../Dto/Dependency/DynamicFilterInfo.cs | 2 +- .../Dto/Sys/Dept/QueryDeptRsp.cs | 4 +- .../Dto/Sys/Job/QueryJobRsp.cs | 24 +++ .../Dto/Sys/JobRecord/QueryJobRecordRsp.cs | 45 ++++ .../Dto/Sys/Tool/GetModulesRsp.cs | 2 +- .../Dto/Sys/User/CreateUserReq.cs | 2 +- .../Dto/Sys/User/LoginByPwdReq.cs | 2 +- .../Dto/Sys/User/LoginBySmsReq.cs | 2 +- .../NetAdmin.Domain/Dto/Sys/User/LoginRsp.cs | 2 +- .../Dto/Sys/User/RegisterUserReq.cs | 4 +- .../Dto/Sys/User/UserInfoRsp.cs | 2 +- .../Events/SqlCommandAfterEvent.cs | 2 +- .../BackgroundRunning/PollingWork.cs | 12 +- .../BackgroundRunning/WorkBase.cs | 2 +- .../Controllers/ControllerBase.cs | 12 +- .../NetAdmin.Host/Filters/ApiResultHandler.cs | 7 +- .../Constant/Numbers.cs | 1 + .../Exceptions/NetAdminValidateException.cs | 18 ++ .../Extensions/HttpRequestPartExtensions.cs | 12 +- .../Extensions/StringExtensions.cs | 13 +- .../NetAdmin.Infrastructure.csproj | 4 +- .../Modules/Sys/IJobModule.cs | 11 + .../Services/Sys/Dependency/IJobService.cs | 5 + .../Services/Sys/JobRecordService.cs | 3 + .../Services/Sys/JobService.cs | 28 ++- .../Sys/Dependency/IUserCache.cs | 2 +- .../Sys/JobCache.cs | 13 ++ .../Sys/UserCache.cs | 2 +- .../Controllers/Sys/JobController.cs | 17 ++ .../Extensions/ServiceCollectionExtensions.cs | 9 +- .../Jobs/FreeScheduledJob.cs | 42 ++++ .../Jobs/ScheduledJob.cs | 2 +- .../NetAdmin.Tests/NetAdmin.Tests.csproj | 4 +- src/frontend/admin/package.json | 27 +-- src/frontend/admin/src/api/sys/job.js | 22 ++ src/frontend/admin/src/assets/icons/Daily.vue | 10 + .../admin/src/assets/icons/Report.vue | 7 + src/frontend/admin/src/assets/icons/index.js | 4 +- .../admin/src/components/naColTags/index.vue | 2 +- .../admin/src/components/naColUser/index.vue | 50 +++++ src/frontend/admin/src/config/iconSelect.js | 2 +- src/frontend/admin/src/config/index.js | 2 +- .../admin/src/layout/components/tasks.vue | 98 ++++----- .../admin/src/layout/components/userbar.vue | 24 ++- .../admin/src/views/sys/job/index.vue | 23 +- .../admin/src/views/sys/job/record/index.vue | 200 ++++++++++++++++++ .../admin/src/views/sys/job/record/save.vue | 87 ++++++++ src/frontend/admin/src/views/sys/job/save.vue | 81 ++++--- .../admin/src/views/sys/log/login/index.vue | 1 + .../src/views/sys/log/operation/index.vue | 1 + .../admin/src/views/sys/msg/index.vue | 1 + .../admin/src/views/sys/user/index.vue | 1 + 71 files changed, 844 insertions(+), 229 deletions(-) create mode 100644 src/backend/NetAdmin.Infrastructure/Exceptions/NetAdminValidateException.cs create mode 100644 src/backend/NetAdmin.SysComponent.Host/Jobs/FreeScheduledJob.cs create mode 100644 src/frontend/admin/src/assets/icons/Daily.vue create mode 100644 src/frontend/admin/src/assets/icons/Report.vue create mode 100644 src/frontend/admin/src/components/naColUser/index.vue create mode 100644 src/frontend/admin/src/views/sys/job/record/index.vue create mode 100644 src/frontend/admin/src/views/sys/job/record/save.vue diff --git a/Directory.Build.props b/Directory.Build.props index ec9e23c7..786359c3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -17,7 +17,7 @@ preview beta v - CA1707;IDE0005;IDE0008;IDE0010;IDE0028;IDE0055;IDE0160;IDE0300;IDE0305;RCS1141;RCS1142;RCS1181;S101;S1121;S1135;S125;S2094;S3604;S4663;SYSLIB1045;SA1010 + CA1707;IDE0005;IDE0008;IDE0010;IDE0028;IDE0055;IDE0160;IDE0300;IDE0305;RCS1141;RCS1142;RCS1181;S101;S1121;S1135;S125;S2094;S3604;S4663;S6561;SYSLIB1045;SA1010 NetAdmin git https://github.com/nsnail/NetAdmin.git diff --git a/NetAdmin.sln b/NetAdmin.sln index 08c59085..d63f2c76 100644 --- a/NetAdmin.sln +++ b/NetAdmin.sln @@ -34,6 +34,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{BB0B clean.ln.csx = scripts/clean.ln.csx code.clean.csx = scripts/code.clean.csx code.clean.ps1 = scripts/code.clean.ps1 + find.unused.ln.csx = scripts/find.unused.ln.csx gen.cs.tt = scripts/gen.cs.tt gen.id.linq = scripts/gen.id.linq gen.ln.cmd = scripts/gen.ln.cmd diff --git a/assets/seed-data/Sys_Dept.json b/assets/seed-data/Sys_Dept.json index 37ba0225..9b2b4dd1 100644 --- a/assets/seed-data/Sys_Dept.json +++ b/assets/seed-data/Sys_Dept.json @@ -1,8 +1,8 @@ [ { + "Enabled": true, "Id": 372119301627909, "Name": "默认部门", - "Enabled": true, "Sort": 100 } ] \ No newline at end of file diff --git a/assets/seed-data/Sys_Role.json b/assets/seed-data/Sys_Role.json index 3fa98853..32e91bf3 100644 --- a/assets/seed-data/Sys_Role.json +++ b/assets/seed-data/Sys_Role.json @@ -1,10 +1,10 @@ [ { "DataScope": 1, + "DisplayDashboard": true, "Enabled": true, "Id": 370943613149253, "IgnorePermissionControl": true, - "DisplayDashboard": true, "Name": "超级管理员", "Sort": 100 }, diff --git a/assets/seed-data/Sys_SiteMsg.json b/assets/seed-data/Sys_SiteMsg.json index 4b1277d0..c00fea18 100644 --- a/assets/seed-data/Sys_SiteMsg.json +++ b/assets/seed-data/Sys_SiteMsg.json @@ -1,10 +1,10 @@ [ { "Content": "

尊敬的用户:

\n

欢迎您使用 NetAdmin 后台管理系统!NetAdmin 是一款通用后台权限管理系统和快速开发框架,它基于 C#12/.NET8、Vue3/Vite、Element Plus 等现代技术构建,具有十分整洁、优雅的编码规范。

\n

NetAdmin 致力于为企业提供高效、安全、易用的解决方案,帮助您快速构建出符合业务需求的应用程序。系统提供了丰富的功能模块,包括用户管理、权限管理、日志管理、文件上传等,可以满足您日常管理的需求。

\n

在使用 NetAdmin 的过程中,我们真诚地希望您能够遵守以下规定:

\n

1. 不得利用 NetAdmin 进行非法活动或者侵犯他人权益;

\n

2. 不得对 NetAdmin 系统进行恶意攻击或者破坏;

\n

3. 不得将 NetAdmin 系统的任何部分用于商业目的或者未经授权的访问。

\n

4. 为了更好地为您提供服务,NetAdmin 将不断进行优化和升级,同时也欢迎您提出宝贵的意见和建议。如果您在使用过程中遇到任何问题,可以通过官方网站或者技术支持团队进行咨询和解决。

\n

再次感谢您对 NetAdmin 的信任和支持!我们相信,在您的使用过程中,NetAdmin 一定会成为您的得力助手,为您的事业发展提供强有力的支持!

\n

NetAdmin 开发团队

", + "CreatedUserId": 370942943322181, + "CreatedUserName": "root", "MsgType": 2, "Summary": "尊敬的用户:\n欢迎您使用 NetAdmin 后台管理系统!NetAdmin 是一款通用后台权限管理系统和快速开发框架,它基于 C#12/.NET8、Vue3/Vite、Element Plus 等现代", "Title": "欢迎使用 NetAdmin 后台管理系统", - "CreatedUserId": 370942943322181, - "CreatedUserName": "root", } ] \ No newline at end of file diff --git a/build/code.quality.props b/build/code.quality.props index 87bbca52..24ca4991 100644 --- a/build/code.quality.props +++ b/build/code.quality.props @@ -15,7 +15,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/scripts/2.git.release.ps1 b/scripts/2.git.release.ps1 index d1442855..b2b01293 100644 --- a/scripts/2.git.release.ps1 +++ b/scripts/2.git.release.ps1 @@ -1,7 +1,7 @@ cd .. $types = @{ '1' = @('major', '主版本') - '2' = @('minor', '此版本') + '2' = @('minor', '次版本') '3' = @('patch', '修订版本') } $prefix = '' diff --git a/src/backend/NetAdmin.Application/Services/RepositoryService.cs b/src/backend/NetAdmin.Application/Services/RepositoryService.cs index eb5ce8ec..3a4a7256 100644 --- a/src/backend/NetAdmin.Application/Services/RepositoryService.cs +++ b/src/backend/NetAdmin.Application/Services/RepositoryService.cs @@ -8,21 +8,13 @@ namespace NetAdmin.Application.Services; /// /// 实体类型 /// 日志类型 -public abstract class RepositoryService : ServiceBase +public abstract class RepositoryService(DefaultRepository rpo) : ServiceBase where TEntity : EntityBase { - /// - /// Initializes a new instance of the class. - /// - protected RepositoryService(DefaultRepository rpo) // - { - Rpo = rpo; - } - /// /// 默认仓储 /// - protected DefaultRepository Rpo { get; } + protected DefaultRepository Rpo => rpo; /// /// 启用级联保存 diff --git a/src/backend/NetAdmin.Cache/CacheBase.cs b/src/backend/NetAdmin.Cache/CacheBase.cs index b4228527..33a206d5 100644 --- a/src/backend/NetAdmin.Cache/CacheBase.cs +++ b/src/backend/NetAdmin.Cache/CacheBase.cs @@ -5,21 +5,13 @@ namespace NetAdmin.Cache; /// /// 缓存基类 /// -public abstract class CacheBase : ICache +public abstract class CacheBase(TCacheContainer cache, TService service) + : ICache where TService : IService { - /// - /// Initializes a new instance of the class. - /// - protected CacheBase(TCacheContainer cache, TService service) - { - Cache = cache; - Service = service; - } + /// + public TCacheContainer Cache => cache; /// - public TCacheContainer Cache { get; } - - /// - public TService Service { get; } + public TService Service => service; } \ No newline at end of file diff --git a/src/backend/NetAdmin.Cache/DistributedCache.cs b/src/backend/NetAdmin.Cache/DistributedCache.cs index 828fbb38..d8ef1709 100644 --- a/src/backend/NetAdmin.Cache/DistributedCache.cs +++ b/src/backend/NetAdmin.Cache/DistributedCache.cs @@ -6,15 +6,10 @@ namespace NetAdmin.Cache; /// /// 分布式缓存 /// -public abstract class DistributedCache : CacheBase +public abstract class DistributedCache(IDistributedCache cache, TService service) + : CacheBase(cache, service) where TService : IService { - /// - /// Initializes a new instance of the class. - /// - protected DistributedCache(IDistributedCache cache, TService service) // - : base(cache, service) { } - /// /// 创建缓存 /// diff --git a/src/backend/NetAdmin.Cache/MemoryCache.cs b/src/backend/NetAdmin.Cache/MemoryCache.cs index a2c3cf95..390caf53 100644 --- a/src/backend/NetAdmin.Cache/MemoryCache.cs +++ b/src/backend/NetAdmin.Cache/MemoryCache.cs @@ -5,12 +5,6 @@ namespace NetAdmin.Cache; /// /// 内存缓存 /// -public abstract class MemoryCache : CacheBase - where TService : IService -{ - /// - /// Initializes a new instance of the class. - /// - protected MemoryCache(IMemoryCache cache, TService service) // - : base(cache, service) { } -} \ No newline at end of file +public abstract class MemoryCache(IMemoryCache cache, TService service) + : CacheBase(cache, service) + where TService : IService; \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/DataAbstraction.cs b/src/backend/NetAdmin.Domain/DataAbstraction.cs index efd33e13..db6836cd 100644 --- a/src/backend/NetAdmin.Domain/DataAbstraction.cs +++ b/src/backend/NetAdmin.Domain/DataAbstraction.cs @@ -8,11 +8,14 @@ public abstract record DataAbstraction /// /// 如果数据校验失败,抛出异常 /// - /// NetAdminInvalidInputException + /// NetAdminValidateException public void ThrowIfInvalid() { - if (!this.TryValidate().IsValid) { - throw new NetAdminInvalidInputException(Ln.无效输入); + var validationResult = this.TryValidate(); + if (!validationResult.IsValid) { + throw new NetAdminValidateException(validationResult.ValidationResults.ToDictionary( // + x => x.MemberNames.First() // + , x => new[] { x.ErrorMessage })); } } diff --git a/src/backend/NetAdmin.Domain/DbMaps/Dependency/VersionEntity.cs b/src/backend/NetAdmin.Domain/DbMaps/Dependency/VersionEntity.cs index 83840775..f9c724f5 100644 --- a/src/backend/NetAdmin.Domain/DbMaps/Dependency/VersionEntity.cs +++ b/src/backend/NetAdmin.Domain/DbMaps/Dependency/VersionEntity.cs @@ -20,12 +20,12 @@ public abstract record VersionEntity : LiteVersionEntity, IFieldModifiedUs /// [JsonIgnore] [Column(CanUpdate = false, Position = -1)] - public long? CreatedUserId { get; init; } + public virtual long? CreatedUserId { get; init; } /// [JsonIgnore] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanUpdate = false, Position = -1)] - public string CreatedUserName { get; init; } + public virtual string CreatedUserName { get; init; } /// [Column(IsIdentity = false, IsPrimary = true, Position = 1)] @@ -34,10 +34,10 @@ public abstract record VersionEntity : LiteVersionEntity, IFieldModifiedUs /// [JsonIgnore] [Column(CanInsert = false, Position = -1)] - public long? ModifiedUserId { get; init; } + public virtual long? ModifiedUserId { get; init; } /// [JsonIgnore] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanInsert = false, Position = -1)] - public string ModifiedUserName { get; init; } + public virtual string ModifiedUserName { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Job.cs b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Job.cs index e1c77b46..8c13c89f 100644 --- a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Job.cs +++ b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Job.cs @@ -98,6 +98,13 @@ public record Sys_Job : VersionEntity, IFieldEnabled, IFieldSummary [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] public virtual string Summary { get; init; } + /// + /// 执行用户 + /// + [Navigate(nameof(UserId))] + [JsonIgnore] + public Sys_User User { get; init; } + /// /// 执行用户编号 /// diff --git a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_JobRecord.cs b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_JobRecord.cs index c58f61e3..ebea51e3 100644 --- a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_JobRecord.cs +++ b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_JobRecord.cs @@ -15,68 +15,68 @@ public record Sys_JobRecord : LiteImmutableEntity /// [Column] [JsonIgnore] - public long Duration { get; init; } + public virtual long Duration { get; init; } /// /// 请求方法 /// [JsonIgnore] [Column] - public HttpMethods HttpMethod { get; init; } + public virtual HttpMethods HttpMethod { get; init; } /// /// HTTP 状态码 /// [Column] [JsonIgnore] - public HttpStatusCode HttpStatusCode { get; init; } + public virtual int HttpStatusCode { get; init; } /// /// 作业编号 /// [Column] [JsonIgnore] - public long JobId { get; init; } + public virtual long JobId { get; init; } /// /// 请求体 /// [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [JsonIgnore] - public string RequestBody { get; init; } + public virtual string RequestBody { get; init; } /// /// 请求头 /// [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [JsonIgnore] - public string RequestHeader { get; init; } + public virtual string RequestHeader { get; init; } /// /// 请求的网络地址 /// [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)] [JsonIgnore] - public string RequestUrl { get; init; } + public virtual string RequestUrl { get; init; } /// /// 响应体 /// [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [JsonIgnore] - public string ResponseBody { get; init; } + public virtual string ResponseBody { get; init; } /// /// 响应头 /// [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] [JsonIgnore] - public string ResponseHeader { get; init; } + public virtual string ResponseHeader { get; init; } /// /// 执行时间编号 /// [Column] [JsonIgnore] - public long TimeId { get; init; } + public virtual long TimeId { 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 5c164a8d..86118c79 100644 --- a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLog.cs +++ b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLog.cs @@ -28,7 +28,7 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient /// [Column(Position = -1)] [JsonIgnore] - public virtual int? CreatedClientIp { get; init; } + public int? CreatedClientIp { get; init; } /// /// 创建者来源地址 diff --git a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleApi.cs b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleApi.cs index 5582acdc..ce459f2c 100644 --- a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleApi.cs +++ b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleApi.cs @@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys; /// 角色-接口映射表 /// [Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleApi))] -public sealed record Sys_RoleApi : ImmutableEntity +public record Sys_RoleApi : ImmutableEntity { /// /// 关联的接口 diff --git a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleDept.cs b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleDept.cs index 2bfa7681..e8492bb7 100644 --- a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleDept.cs +++ b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleDept.cs @@ -7,7 +7,7 @@ namespace NetAdmin.Domain.DbMaps.Sys; /// [Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleDept))] [Index($"idx_{{tablename}}_{nameof(RoleId)}_{nameof(DeptId)}", $"{nameof(RoleId)},{nameof(DeptId)}", true)] -public sealed record Sys_RoleDept : ImmutableEntity +public record Sys_RoleDept : ImmutableEntity { /// /// 关联的部门 diff --git a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_UserRole.cs b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_UserRole.cs index 05f99f72..e5d83758 100644 --- a/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_UserRole.cs +++ b/src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_UserRole.cs @@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys; /// 用户-角色映射表 /// [Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_UserRole))] -public sealed record Sys_UserRole : VersionEntity +public record Sys_UserRole : VersionEntity { /// /// 关联的角色 diff --git a/src/backend/NetAdmin.Domain/Dto/Dependency/DynamicFilterInfo.cs b/src/backend/NetAdmin.Domain/Dto/Dependency/DynamicFilterInfo.cs index f95e0509..607f2ed0 100644 --- a/src/backend/NetAdmin.Domain/Dto/Dependency/DynamicFilterInfo.cs +++ b/src/backend/NetAdmin.Domain/Dto/Dependency/DynamicFilterInfo.cs @@ -5,7 +5,7 @@ namespace NetAdmin.Domain.Dto.Dependency; /// /// 动态过滤条件 /// -public record DynamicFilterInfo : DataAbstraction +public sealed record DynamicFilterInfo : DataAbstraction { /// /// 字段名 diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Dept/QueryDeptRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Dept/QueryDeptRsp.cs index c8c84c80..9f226df5 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Dept/QueryDeptRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Dept/QueryDeptRsp.cs @@ -6,10 +6,10 @@ namespace NetAdmin.Domain.Dto.Sys.Dept; /// /// 响应:查询部门 /// -public record QueryDeptRsp : Sys_Dept +public sealed record QueryDeptRsp : Sys_Dept { /// - public new virtual IEnumerable Children { get; init; } + public new IEnumerable Children { get; init; } /// [JsonIgnore(Condition = JsonIgnoreCondition.Never)] diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Job/QueryJobRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Job/QueryJobRsp.cs index a311be3d..265043a1 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Job/QueryJobRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Job/QueryJobRsp.cs @@ -1,5 +1,6 @@ using NetAdmin.Domain.DbMaps.Dependency.Fields; using NetAdmin.Domain.DbMaps.Sys; +using NetAdmin.Domain.Dto.Sys.User; using NetAdmin.Domain.Enums.Sys; using HttpMethods = NetAdmin.Domain.Enums.HttpMethods; @@ -14,6 +15,14 @@ public sealed record QueryJobRsp : Sys_Job [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public override DateTime CreatedTime { get; init; } + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override long? CreatedUserId { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string CreatedUserName { get; init; } + /// [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public override bool Enabled { get; init; } @@ -42,6 +51,18 @@ public sealed record QueryJobRsp : Sys_Job [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public override HttpStatusCode? LastStatusCode { get; init; } + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override DateTime? ModifiedTime { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override long? ModifiedUserId { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string ModifiedUserName { get; init; } + /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public override DateTime? NextExecTime { get; init; } @@ -70,6 +91,9 @@ public sealed record QueryJobRsp : Sys_Job [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public override string Summary { get; init; } + /// + public new QueryUserRsp User { get; init; } + /// [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public override long UserId { get; init; } diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/JobRecord/QueryJobRecordRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/JobRecord/QueryJobRecordRsp.cs index ac36085a..8af83639 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/JobRecord/QueryJobRecordRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/JobRecord/QueryJobRecordRsp.cs @@ -1,5 +1,6 @@ using NetAdmin.Domain.DbMaps.Dependency.Fields; using NetAdmin.Domain.DbMaps.Sys; +using HttpMethods = NetAdmin.Domain.Enums.HttpMethods; namespace NetAdmin.Domain.Dto.Sys.JobRecord; @@ -8,7 +9,51 @@ namespace NetAdmin.Domain.Dto.Sys.JobRecord; /// public sealed record QueryJobRecordRsp : Sys_JobRecord { + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override DateTime CreatedTime { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override long Duration { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override HttpMethods HttpMethod { 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.Never)] + public override long JobId { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string RequestBody { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string RequestHeader { 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 ResponseHeader { get; init; } + + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override long TimeId { get; init; } } \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Tool/GetModulesRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Tool/GetModulesRsp.cs index 8ec88611..094e751b 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Tool/GetModulesRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Tool/GetModulesRsp.cs @@ -3,7 +3,7 @@ namespace NetAdmin.Domain.Dto.Sys.Tool; /// /// 响应:获取模块信息 /// -public record GetModulesRsp : DataAbstraction +public sealed record GetModulesRsp : DataAbstraction { /// /// 模块名称 diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/User/CreateUserReq.cs b/src/backend/NetAdmin.Domain/Dto/Sys/User/CreateUserReq.cs index eba2e9fd..49a3bab3 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/User/CreateUserReq.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/User/CreateUserReq.cs @@ -6,7 +6,7 @@ namespace NetAdmin.Domain.Dto.Sys.User; /// /// 请求:创建用户 /// -public record CreateUserReq : CreateUpdateUserReq, IRegister +public sealed record CreateUserReq : CreateUpdateUserReq, IRegister { /// [Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.密码不能为空))] diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginByPwdReq.cs b/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginByPwdReq.cs index 086c9c47..e4980e9a 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginByPwdReq.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginByPwdReq.cs @@ -5,7 +5,7 @@ namespace NetAdmin.Domain.Dto.Sys.User; /// /// 请求:密码登录 /// -public record LoginByPwdReq : DataAbstraction +public sealed record LoginByPwdReq : DataAbstraction { /// /// 用户名、手机号、邮箱 diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginBySmsReq.cs b/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginBySmsReq.cs index f2b5e07e..66d04aea 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginBySmsReq.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginBySmsReq.cs @@ -5,4 +5,4 @@ namespace NetAdmin.Domain.Dto.Sys.User; /// /// 请求:短信登录 /// -public record LoginBySmsReq : VerifySmsCodeReq; \ No newline at end of file +public sealed record LoginBySmsReq : VerifySmsCodeReq; \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginRsp.cs index a74c40dc..6940e522 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/User/LoginRsp.cs @@ -3,7 +3,7 @@ namespace NetAdmin.Domain.Dto.Sys.User; /// /// 响应:密码登录 /// -public record LoginRsp : DataAbstraction +public sealed record LoginRsp : DataAbstraction { /// /// 访问令牌 diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/User/RegisterUserReq.cs b/src/backend/NetAdmin.Domain/Dto/Sys/User/RegisterUserReq.cs index 9e108128..ad02633c 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/User/RegisterUserReq.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/User/RegisterUserReq.cs @@ -7,7 +7,7 @@ namespace NetAdmin.Domain.Dto.Sys.User; /// /// 请求:注册用户 /// -public record RegisterUserReq : Sys_User +public sealed record RegisterUserReq : Sys_User { /// /// 密码 @@ -15,7 +15,7 @@ public record RegisterUserReq : Sys_User [Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.密码不能为空))] [Password] [JsonIgnore(Condition = JsonIgnoreCondition.Never)] - public virtual string PasswordText { get; init; } + public string PasswordText { get; init; } /// /// 角色编号列表 diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/User/UserInfoRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/User/UserInfoRsp.cs index e46d2e92..6ec53a48 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/User/UserInfoRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/User/UserInfoRsp.cs @@ -7,7 +7,7 @@ namespace NetAdmin.Domain.Dto.Sys.User; /// /// 响应:当前用户信息 /// -public record UserInfoRsp : QueryUserRsp, IRegister +public sealed record UserInfoRsp : QueryUserRsp, IRegister { /// public override QueryDeptRsp Dept { get; init; } diff --git a/src/backend/NetAdmin.Domain/Events/SqlCommandAfterEvent.cs b/src/backend/NetAdmin.Domain/Events/SqlCommandAfterEvent.cs index ce841ad7..9c26ffc5 100644 --- a/src/backend/NetAdmin.Domain/Events/SqlCommandAfterEvent.cs +++ b/src/backend/NetAdmin.Domain/Events/SqlCommandAfterEvent.cs @@ -18,7 +18,7 @@ public sealed record SqlCommandAfterEvent : SqlCommandBeforeEvent /// /// 耗时(单位:微秒) /// - public long ElapsedMicroseconds { get; set; } + public long ElapsedMicroseconds { get; init; } /// public override string ToString() diff --git a/src/backend/NetAdmin.Host/BackgroundRunning/PollingWork.cs b/src/backend/NetAdmin.Host/BackgroundRunning/PollingWork.cs index c2261dab..9b0f68c3 100644 --- a/src/backend/NetAdmin.Host/BackgroundRunning/PollingWork.cs +++ b/src/backend/NetAdmin.Host/BackgroundRunning/PollingWork.cs @@ -5,19 +5,11 @@ namespace NetAdmin.Host.BackgroundRunning; /// /// 轮询工作 /// -public abstract class PollingWork : WorkBase +public abstract class PollingWork(TWorkData workData) : WorkBase where TWorkData : DataAbstraction { - /// - /// Initializes a new instance of the class. - /// - protected PollingWork(TWorkData workData) - { - WorkData = workData; - } - /// /// 工作数据 /// - protected TWorkData WorkData { get; } + protected TWorkData WorkData => workData; } \ 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 0fddaeb2..3f67c9e4 100644 --- a/src/backend/NetAdmin.Host/BackgroundRunning/WorkBase.cs +++ b/src/backend/NetAdmin.Host/BackgroundRunning/WorkBase.cs @@ -54,7 +54,7 @@ public abstract class WorkBase /// 通用工作流 /// /// 加锁失败异常 - protected async ValueTask WorkflowAsync(bool singleInstance, CancellationToken cancelToken) + protected virtual async ValueTask WorkflowAsync(bool singleInstance, CancellationToken cancelToken) { if (singleInstance) { // 加锁 diff --git a/src/backend/NetAdmin.Host/Controllers/ControllerBase.cs b/src/backend/NetAdmin.Host/Controllers/ControllerBase.cs index a5f3dac8..c32cd34a 100644 --- a/src/backend/NetAdmin.Host/Controllers/ControllerBase.cs +++ b/src/backend/NetAdmin.Host/Controllers/ControllerBase.cs @@ -6,20 +6,12 @@ namespace NetAdmin.Host.Controllers; /// /// 控制器基类 /// -public abstract class ControllerBase : IDynamicApiController +public abstract class ControllerBase(TCache cache) : IDynamicApiController where TCache : ICache // where TService : IService { - /// - /// Initializes a new instance of the class. - /// - protected ControllerBase(TCache cache) - { - Cache = cache; - } - /// /// 关联的缓存 /// - protected TCache Cache { get; } + protected TCache Cache => cache; } \ No newline at end of file diff --git a/src/backend/NetAdmin.Host/Filters/ApiResultHandler.cs b/src/backend/NetAdmin.Host/Filters/ApiResultHandler.cs index fd090edf..aecf5a99 100644 --- a/src/backend/NetAdmin.Host/Filters/ApiResultHandler.cs +++ b/src/backend/NetAdmin.Host/Filters/ApiResultHandler.cs @@ -24,8 +24,11 @@ public abstract class ApiResultHandler public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata) { var lineException = context.Exception switch { NetAdminException ex => ex, _ => null }; - var errorCode = lineException?.Code ?? ErrorCodes.Unhandled; - var result = RestfulResult(errorCode, metadata.Data, lineException?.Message ?? errorCode.ResDesc()); + var errorCode = lineException?.Code ?? ErrorCodes.Unhandled; + var result = RestfulResult(errorCode, metadata.Data + , lineException is NetAdminValidateException vEx + ? vEx.ValidateResults + : lineException?.Message ?? errorCode.ResDesc()); SetErrorCodeToHeader(context.HttpContext, errorCode); diff --git a/src/backend/NetAdmin.Infrastructure/Constant/Numbers.cs b/src/backend/NetAdmin.Infrastructure/Constant/Numbers.cs index ef261438..02937ef2 100644 --- a/src/backend/NetAdmin.Infrastructure/Constant/Numbers.cs +++ b/src/backend/NetAdmin.Infrastructure/Constant/Numbers.cs @@ -16,6 +16,7 @@ public static class Numbers public const long DIC_CATALOG_ID_GEO_AREA = 379794295185413; // 字典目录编号-行政区划字典 public const int HEART_TIMEOUT_SECS = 600; // 心跳超时时间 public const int HTTP_STATUS_BIZ_FAIL = 900; // Http状态码-业务异常 + public const int JOB_TIMEOUT_SECS = 600; // 作业超时时间 public const int QUERY_DEF_PAGE_SIZE = 20; // 分页查询默认的页容量 public const int QUERY_LIMIT = 100; // 非分页查询允许返回的最大条数 public const int QUERY_MAX_PAGE_NO = 1000; // 分页查询允许最大的页码 diff --git a/src/backend/NetAdmin.Infrastructure/Exceptions/NetAdminValidateException.cs b/src/backend/NetAdmin.Infrastructure/Exceptions/NetAdminValidateException.cs new file mode 100644 index 00000000..e00e8ca1 --- /dev/null +++ b/src/backend/NetAdmin.Infrastructure/Exceptions/NetAdminValidateException.cs @@ -0,0 +1,18 @@ +namespace NetAdmin.Infrastructure.Exceptions; + +/// +/// 验证失败异常 +/// +/// +/// 手动调用模型验证方法抛出 +/// +#pragma warning disable RCS1194 +public sealed class NetAdminValidateException(Dictionary validateResults) + : NetAdminException(ErrorCodes.InvalidInput) +#pragma warning restore RCS1194 +{ + /// + /// 验证结果 + /// + public Dictionary ValidateResults { get; } = validateResults; +} \ No newline at end of file diff --git a/src/backend/NetAdmin.Infrastructure/Extensions/HttpRequestPartExtensions.cs b/src/backend/NetAdmin.Infrastructure/Extensions/HttpRequestPartExtensions.cs index fa131677..2419866d 100644 --- a/src/backend/NetAdmin.Infrastructure/Extensions/HttpRequestPartExtensions.cs +++ b/src/backend/NetAdmin.Infrastructure/Extensions/HttpRequestPartExtensions.cs @@ -13,25 +13,21 @@ public static class HttpRequestPartExtensions public static HttpRequestPart SetLog(this HttpRequestPart me, ILogger logger , Func bodyHandle = null) { - #pragma warning disable S1172 - - Task RequestHandle(HttpClient _, HttpRequestMessage req) + Task RequestHandleAsync(HttpClient _, HttpRequestMessage req) { return req.LogAsync(logger); } - Task ExceptionHandle(HttpClient _, HttpResponseMessage rsp, string errors) + Task ExceptionHandleAsync(HttpClient _, HttpResponseMessage rsp, string errors) { return rsp.LogExceptionAsync(errors, logger, bodyHandle); } - Task ResponseHandle(HttpClient _, HttpResponseMessage rsp) + Task ResponseHandleAsync(HttpClient _, HttpResponseMessage rsp) { return rsp.LogAsync(logger, bodyHandle); } - #pragma warning restore S1172 - - return me.OnRequesting(RequestHandle).OnResponsing(ResponseHandle).OnException(ExceptionHandle); + return me.OnRequesting(RequestHandleAsync).OnResponsing(ResponseHandleAsync).OnException(ExceptionHandleAsync); } } \ 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 936c6699..df0cae8c 100644 --- a/src/backend/NetAdmin.Infrastructure/Extensions/StringExtensions.cs +++ b/src/backend/NetAdmin.Infrastructure/Extensions/StringExtensions.cs @@ -5,7 +5,8 @@ namespace NetAdmin.Infrastructure.Extensions; /// public static class StringExtensions { - private static readonly Regex _regex = new("Options$"); + private static readonly Regex _regex = new("Options$"); + private static readonly Regex _regex2 = new("Async$"); /// /// object -> json @@ -23,6 +24,16 @@ 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 _regex2.Replace(me, string.Empty); + } + /// /// 去掉尾部字符串“Options” /// diff --git a/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj b/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj index e7a3c59a..d147538d 100644 --- a/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj +++ b/src/backend/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj @@ -6,14 +6,14 @@ - + - + diff --git a/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/IJobModule.cs b/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/IJobModule.cs index c77dc76d..8a334336 100644 --- a/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/IJobModule.cs +++ b/src/backend/NetAdmin.SysComponent.Application/Modules/Sys/IJobModule.cs @@ -1,6 +1,7 @@ using NetAdmin.Application.Modules; using NetAdmin.Domain.Dto.Dependency; using NetAdmin.Domain.Dto.Sys.Job; +using NetAdmin.Domain.Dto.Sys.JobRecord; namespace NetAdmin.SysComponent.Application.Modules.Sys; @@ -13,6 +14,16 @@ public interface IJobModule : ICrudModule { + /// + /// 获取单个作业记录 + /// + Task RecordGetAsync(QueryJobRecordReq req); + + /// + /// 分页查询作业记录 + /// + Task> RecordPagedQueryAsync(PagedQueryReq req); + /// /// 启用/禁用作业 /// diff --git a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IJobService.cs b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IJobService.cs index eb954cae..d6b877c5 100644 --- a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IJobService.cs +++ b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IJobService.cs @@ -18,4 +18,9 @@ public interface IJobService : IService, IJobModule /// 获取下一个要执行的计划作业 /// Task GetNextJobAsync(); + + /// + /// 释放卡死的任务 + /// + Task ReleaseStuckTaskAsync(); } \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/JobRecordService.cs b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/JobRecordService.cs index 07f6386f..bd3b803b 100644 --- a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/JobRecordService.cs +++ b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/JobRecordService.cs @@ -102,6 +102,9 @@ public sealed class JobRecordService(DefaultRepository rpo) // { var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter) .WhereDynamic(req.Filter) + .WhereIf( // + req.Keywords?.Length > 0 + , a => a.JobId == req.Keywords.Int64Try(0) || a.Id == req.Keywords.Int64Try(0)) .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); diff --git a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/JobService.cs b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/JobService.cs index 62289897..323c3489 100644 --- a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/JobService.cs +++ b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/JobService.cs @@ -4,6 +4,7 @@ using NetAdmin.Application.Services; using NetAdmin.Domain.DbMaps.Sys; using NetAdmin.Domain.Dto.Dependency; using NetAdmin.Domain.Dto.Sys.Job; +using NetAdmin.Domain.Dto.Sys.JobRecord; using NetAdmin.Domain.Enums.Sys; using NetAdmin.SysComponent.Application.Services.Sys.Dependency; using DataType = FreeSql.DataType; @@ -11,7 +12,7 @@ using DataType = FreeSql.DataType; namespace NetAdmin.SysComponent.Application.Services.Sys; /// -public sealed class JobService(DefaultRepository rpo) // +public sealed class JobService(DefaultRepository rpo, IJobRecordService jobRecordService) // : RepositoryService(rpo), IJobService { /// @@ -134,6 +135,28 @@ public sealed class JobService(DefaultRepository rpo) // return ret.Adapt>(); } + /// + public Task RecordGetAsync(QueryJobRecordReq req) + { + req.ThrowIfInvalid(); + return jobRecordService.GetAsync(req); + } + + /// + public Task> RecordPagedQueryAsync(PagedQueryReq req) + { + return jobRecordService.PagedQueryAsync(req); + } + + /// + public Task ReleaseStuckTaskAsync() + { + return Rpo.UpdateDiy.Set(a => a.Status == JobStatues.Idle) + .Where(a => a.Status == JobStatues.Running && + a.LastExecTime < DateTime.Now.AddSeconds(-Numbers.JOB_TIMEOUT_SECS)) + .ExecuteAffrowsAsync(); + } + /// public Task SetEnabledAsync(UpdateJobReq req) { @@ -162,7 +185,8 @@ public sealed class JobService(DefaultRepository rpo) // private ISelect QueryInternal(QueryReq req, bool orderByRandom = false) { - var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter) + var ret = Rpo.Select.Include(a => a.User) + .WhereDynamicFilter(req.DynamicFilter) .WhereDynamic(req.Filter) .WhereIf( // req.Keywords?.Length > 0 diff --git a/src/backend/NetAdmin.SysComponent.Cache/Sys/Dependency/IUserCache.cs b/src/backend/NetAdmin.SysComponent.Cache/Sys/Dependency/IUserCache.cs index fd41193e..5821ca05 100644 --- a/src/backend/NetAdmin.SysComponent.Cache/Sys/Dependency/IUserCache.cs +++ b/src/backend/NetAdmin.SysComponent.Cache/Sys/Dependency/IUserCache.cs @@ -40,7 +40,7 @@ public interface IUserCache : ICache, IUserModu /// /// 删除缓存 RegisterAsync /// - Task RemoveRegisterAsync(RegisterUserReq userReq); + Task RemoveRegisterAsync(RegisterUserReq req); /// /// 删除缓存 ResetPasswordAsync diff --git a/src/backend/NetAdmin.SysComponent.Cache/Sys/JobCache.cs b/src/backend/NetAdmin.SysComponent.Cache/Sys/JobCache.cs index e18999f6..88db9efd 100644 --- a/src/backend/NetAdmin.SysComponent.Cache/Sys/JobCache.cs +++ b/src/backend/NetAdmin.SysComponent.Cache/Sys/JobCache.cs @@ -1,6 +1,7 @@ using NetAdmin.Cache; using NetAdmin.Domain.Dto.Dependency; using NetAdmin.Domain.Dto.Sys.Job; +using NetAdmin.Domain.Dto.Sys.JobRecord; using NetAdmin.SysComponent.Application.Services.Sys.Dependency; using NetAdmin.SysComponent.Cache.Sys.Dependency; @@ -52,6 +53,18 @@ public sealed class JobCache(IDistributedCache cache, IJobService service) return Service.QueryAsync(req); } + /// + public Task RecordGetAsync(QueryJobRecordReq req) + { + return Service.RecordGetAsync(req); + } + + /// + public Task> RecordPagedQueryAsync(PagedQueryReq req) + { + return Service.RecordPagedQueryAsync(req); + } + /// public Task SetEnabledAsync(UpdateJobReq req) { diff --git a/src/backend/NetAdmin.SysComponent.Cache/Sys/UserCache.cs b/src/backend/NetAdmin.SysComponent.Cache/Sys/UserCache.cs index 7622bafd..eac95a04 100644 --- a/src/backend/NetAdmin.SysComponent.Cache/Sys/UserCache.cs +++ b/src/backend/NetAdmin.SysComponent.Cache/Sys/UserCache.cs @@ -120,7 +120,7 @@ public sealed class UserCache(IDistributedCache cache, IUserService service, IVe } /// - public Task RemoveRegisterAsync(RegisterUserReq userReq) + public Task RemoveRegisterAsync(RegisterUserReq req) { throw new NotImplementedException(); } diff --git a/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/JobController.cs b/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/JobController.cs index b08a6fd3..e8b33d82 100644 --- a/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/JobController.cs +++ b/src/backend/NetAdmin.SysComponent.Host/Controllers/Sys/JobController.cs @@ -1,5 +1,6 @@ using NetAdmin.Domain.Dto.Dependency; using NetAdmin.Domain.Dto.Sys.Job; +using NetAdmin.Domain.Dto.Sys.JobRecord; using NetAdmin.Host.Attributes; using NetAdmin.Host.Controllers; using NetAdmin.SysComponent.Application.Modules.Sys; @@ -73,6 +74,22 @@ public sealed class JobController(IJobCache cache) : ControllerBase + /// 获取单个作业记录 + /// + public Task RecordGetAsync(QueryJobRecordReq req) + { + return Cache.RecordGetAsync(req); + } + + /// + /// 分页查询作业记录 + /// + public Task> RecordPagedQueryAsync(PagedQueryReq req) + { + return Cache.RecordPagedQueryAsync(req); + } + /// /// 启用/禁用作业 /// diff --git a/src/backend/NetAdmin.SysComponent.Host/Extensions/ServiceCollectionExtensions.cs b/src/backend/NetAdmin.SysComponent.Host/Extensions/ServiceCollectionExtensions.cs index 0c792a78..7ce138f8 100644 --- a/src/backend/NetAdmin.SysComponent.Host/Extensions/ServiceCollectionExtensions.cs +++ b/src/backend/NetAdmin.SysComponent.Host/Extensions/ServiceCollectionExtensions.cs @@ -14,8 +14,11 @@ public static class ServiceCollectionExtensions /// public static IServiceCollection AddSchedules(this IServiceCollection me) { - return me.AddSchedule( // - builder => builder // - .AddJob(false, Triggers.PeriodSeconds(5).SetRunOnStart(true))); + return App.WebHostEnvironment.EnvironmentName != Environments.Production + ? me + : me.AddSchedule( // + builder => builder // + .AddJob(false, Triggers.PeriodSeconds(5).SetRunOnStart(true)) + .AddJob(false, Triggers.PeriodMinutes(1).SetRunOnStart(true))); } } \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Host/Jobs/FreeScheduledJob.cs b/src/backend/NetAdmin.SysComponent.Host/Jobs/FreeScheduledJob.cs new file mode 100644 index 00000000..851a8db3 --- /dev/null +++ b/src/backend/NetAdmin.SysComponent.Host/Jobs/FreeScheduledJob.cs @@ -0,0 +1,42 @@ +using Furion.Schedule; +using NetAdmin.Host.BackgroundRunning; +using NetAdmin.SysComponent.Application.Services.Sys.Dependency; + +namespace NetAdmin.SysComponent.Host.Jobs; + +/// +/// 释放计划作业 +/// +public sealed class FreeScheduledJob : WorkBase, IJob +{ + private readonly IJobService _jobService; + + /// + /// Initializes a new instance of the class. + /// + public FreeScheduledJob() + { + _jobService = ServiceProvider.GetService(); + } + + /// + /// 具体处理逻辑 + /// + /// 作业执行前上下文 + /// 取消任务 Token + /// 加锁失败异常 + public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) + { + await WorkflowAsync(true, stoppingToken).ConfigureAwait(false); + } + + /// + /// 通用工作流 + /// + /// NotImplementedException + /// ArgumentOutOfRangeException + protected override async ValueTask WorkflowAsync(CancellationToken cancelToken) + { + _ = await _jobService.ReleaseStuckTaskAsync().ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/backend/NetAdmin.SysComponent.Host/Jobs/ScheduledJob.cs b/src/backend/NetAdmin.SysComponent.Host/Jobs/ScheduledJob.cs index 3bb303c6..bb2b4b1a 100644 --- a/src/backend/NetAdmin.SysComponent.Host/Jobs/ScheduledJob.cs +++ b/src/backend/NetAdmin.SysComponent.Host/Jobs/ScheduledJob.cs @@ -87,7 +87,7 @@ public sealed class ScheduledJob : WorkBase, IJob { Duration = sw.ElapsedMilliseconds , HttpMethod = job.HttpMethod - , HttpStatusCode = rsp.StatusCode + , HttpStatusCode = (int)rsp.StatusCode , JobId = job.Id , RequestBody = job.RequestBody , RequestHeader = _requestHeader diff --git a/src/backend/NetAdmin.Tests/NetAdmin.Tests.csproj b/src/backend/NetAdmin.Tests/NetAdmin.Tests.csproj index 6970f715..d8b67fa9 100644 --- a/src/backend/NetAdmin.Tests/NetAdmin.Tests.csproj +++ b/src/backend/NetAdmin.Tests/NetAdmin.Tests.csproj @@ -3,9 +3,9 @@ - + - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/frontend/admin/package.json b/src/frontend/admin/package.json index ecb607bf..5b794e64 100644 --- a/src/frontend/admin/package.json +++ b/src/frontend/admin/package.json @@ -3,7 +3,8 @@ "private": true, "scripts": { "dev": "vite", - "build": "vite build", + "build": "vite build --mode production", + "build:test": "vite build --mode test", "preview": "vite preview", "prettier": "prettier --write ." }, @@ -12,34 +13,34 @@ "@tinymce/tinymce-vue": "^5.1.1", "axios": "^1.6.7", "clipboard": "^2.0.11", - "core-js": "^3.35.1", + "core-js": "^3.36.0", "cropperjs": "^1.6.1", "crypto-js": "^4.2.0", "echarts": "^5.4.3", - "element-plus": "^2.5.3", + "element-plus": "^2.5.5", "json-bigint": "^1.0.0", "json5-to-table": "^0.1.8", "nprogress": "^0.2.0", "pinyin-match": "^1.2.5", "qrcodejs2": "^0.0.2", "sortablejs": "^1.15.2", - "tinymce": "^6.8.2", - "vue": "^3.4.15", - "vue-i18n": "^9.9.0", + "tinymce": "^6.8.3", + "vue": "^3.4.19", + "vue-i18n": "^9.9.1", "vue-router": "^4.2.5", "vue3-json-viewer": "^2.2.2", "vuedraggable": "^4.0.3", "vuex": "^4.1.0", - "xgplayer": "^3.0.11", - "xgplayer-hls": "^3.0.11" + "xgplayer": "^3.0.12", + "xgplayer-hls": "^3.0.12" }, "devDependencies": { - "@vitejs/plugin-vue": "^5.0.3", - "prettier": "^3.2.4", + "@vitejs/plugin-vue": "^5.0.4", + "prettier": "^3.2.5", "prettier-plugin-organize-attributes": "^1.0.0", - "sass": "^1.70.0", - "terser": "^5.27.0", - "vite": "^5.0.12" + "sass": "^1.71.0", + "terser": "^5.27.1", + "vite": "^5.1.3" }, "browserslist": [ "> 1%", diff --git a/src/frontend/admin/src/api/sys/job.js b/src/frontend/admin/src/api/sys/job.js index 9a3a5c93..6ae3dec3 100644 --- a/src/frontend/admin/src/api/sys/job.js +++ b/src/frontend/admin/src/api/sys/job.js @@ -82,6 +82,28 @@ export default { }, }, + /** + * 获取单个作业记录 + */ + recordGet: { + url: `${config.API_URL}/api/sys/job/record.get`, + name: `获取单个作业记录`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, + + /** + * 分页查询作业记录 + */ + recordPagedQuery: { + url: `${config.API_URL}/api/sys/job/record.paged.query`, + name: `分页查询作业记录`, + post: async function (data = {}, config = {}) { + return await http.post(this.url, data, config) + }, + }, + /** * 启用/禁用作业 */ diff --git a/src/frontend/admin/src/assets/icons/Daily.vue b/src/frontend/admin/src/assets/icons/Daily.vue new file mode 100644 index 00000000..1af03344 --- /dev/null +++ b/src/frontend/admin/src/assets/icons/Daily.vue @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/src/frontend/admin/src/assets/icons/Report.vue b/src/frontend/admin/src/assets/icons/Report.vue new file mode 100644 index 00000000..d3eda860 --- /dev/null +++ b/src/frontend/admin/src/assets/icons/Report.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/src/frontend/admin/src/assets/icons/index.js b/src/frontend/admin/src/assets/icons/index.js index b66cd671..d8b47c56 100644 --- a/src/frontend/admin/src/assets/icons/index.js +++ b/src/frontend/admin/src/assets/icons/index.js @@ -53,4 +53,6 @@ export { default as Unlink } from './Unlink.vue' export { default as Upload } from './Upload.vue' export { default as Vue } from './Vue.vue' export { default as Warning } from './Warning.vue' -export { default as Wechat } from './Wechat.vue' \ No newline at end of file +export { default as Wechat } from './Wechat.vue' +export { default as Report } from './Report.vue' +export { default as Daily } from './Daily.vue' \ No newline at end of file diff --git a/src/frontend/admin/src/components/naColTags/index.vue b/src/frontend/admin/src/components/naColTags/index.vue index eaca1e53..c4ae3f34 100644 --- a/src/frontend/admin/src/components/naColTags/index.vue +++ b/src/frontend/admin/src/components/naColTags/index.vue @@ -3,7 +3,7 @@ diff --git a/src/frontend/admin/src/components/naColUser/index.vue b/src/frontend/admin/src/components/naColUser/index.vue new file mode 100644 index 00000000..b6259506 --- /dev/null +++ b/src/frontend/admin/src/components/naColUser/index.vue @@ -0,0 +1,50 @@ + + + \ No newline at end of file diff --git a/src/frontend/admin/src/config/iconSelect.js b/src/frontend/admin/src/config/iconSelect.js index 1698c6e6..24ac5bc9 100644 --- a/src/frontend/admin/src/config/iconSelect.js +++ b/src/frontend/admin/src/config/iconSelect.js @@ -1 +1 @@ -export default{"icons":[{"icons":["el-icon-add-location","el-icon-aim","el-icon-alarm-clock","el-icon-apple","el-icon-arrow-down","el-icon-arrow-down-bold","el-icon-arrow-left","el-icon-arrow-left-bold","el-icon-arrow-right","el-icon-arrow-right-bold","el-icon-arrow-up","el-icon-arrow-up-bold","el-icon-avatar","el-icon-back","el-icon-baseball","el-icon-basketball","el-icon-bell","el-icon-bell-filled","el-icon-bicycle","el-icon-bottom","el-icon-bottom-left","el-icon-bottom-right","el-icon-bowl","el-icon-box","el-icon-briefcase","el-icon-brush","el-icon-brush-filled","el-icon-burger","el-icon-calendar","el-icon-camera","el-icon-camera-filled","el-icon-caret-bottom","el-icon-caret-left","el-icon-caret-right","el-icon-caret-top","el-icon-cellphone","el-icon-chat-dot-round","el-icon-chat-dot-square","el-icon-chat-line-round","el-icon-chat-line-square","el-icon-chat-round","el-icon-chat-square","el-icon-check","el-icon-checked","el-icon-cherry","el-icon-chicken","el-icon-circle-check","el-icon-circle-check-filled","el-icon-circle-close","el-icon-circle-close-filled","el-icon-circle-plus","el-icon-circle-plus-filled","el-icon-clock","el-icon-close","el-icon-close-bold","el-icon-cloudy","el-icon-coffee","el-icon-coffee-cup","el-icon-coin","el-icon-cold-drink","el-icon-collection","el-icon-collection-tag","el-icon-comment","el-icon-compass","el-icon-connection","el-icon-coordinate","el-icon-copy-document","el-icon-cpu","el-icon-credit-card","el-icon-crop","el-icon-d-arrow-left","el-icon-d-arrow-right","el-icon-d-caret","el-icon-data-analysis","el-icon-data-board","el-icon-data-line","el-icon-delete","el-icon-delete-filled","el-icon-delete-location","el-icon-dessert","el-icon-discount","el-icon-dish","el-icon-dish-dot","el-icon-document","el-icon-document-add","el-icon-document-checked","el-icon-document-copy","el-icon-document-delete","el-icon-document-remove","el-icon-download","el-icon-drizzling","el-icon-edit","el-icon-edit-pen","el-icon-eleme","el-icon-eleme-filled","el-icon-element-plus","el-icon-expand","el-icon-failed","el-icon-female","el-icon-files","el-icon-film","el-icon-filter","el-icon-finished","el-icon-first-aid-kit","el-icon-flag","el-icon-fold","el-icon-folder","el-icon-folder-add","el-icon-folder-checked","el-icon-folder-delete","el-icon-folder-opened","el-icon-folder-remove","el-icon-food","el-icon-football","el-icon-fork-spoon","el-icon-fries","el-icon-full-screen","el-icon-goblet","el-icon-goblet-full","el-icon-goblet-square","el-icon-goblet-square-full","el-icon-goods","el-icon-goods-filled","el-icon-grape","el-icon-grid","el-icon-guide","el-icon-headset","el-icon-help","el-icon-help-filled","el-icon-hide","el-icon-histogram","el-icon-home-filled","el-icon-hot-water","el-icon-house","el-icon-ice-cream","el-icon-ice-cream-round","el-icon-ice-cream-square","el-icon-ice-drink","el-icon-ice-tea","el-icon-info-filled","el-icon-iphone","el-icon-key","el-icon-knife-fork","el-icon-lightning","el-icon-link","el-icon-list","el-icon-loading","el-icon-location","el-icon-location-filled","el-icon-location-information","el-icon-lock","el-icon-lollipop","el-icon-magic-stick","el-icon-magnet","el-icon-male","el-icon-management","el-icon-map-location","el-icon-medal","el-icon-menu","el-icon-message","el-icon-message-box","el-icon-mic","el-icon-microphone","el-icon-milk-tea","el-icon-minus","el-icon-money","el-icon-monitor","el-icon-moon","el-icon-moon-night","el-icon-more","el-icon-more-filled","el-icon-mostly-cloudy","el-icon-mouse","el-icon-mug","el-icon-mute","el-icon-mute-notification","el-icon-no-smoking","el-icon-notebook","el-icon-notification","el-icon-odometer","el-icon-office-building","el-icon-open","el-icon-operation","el-icon-opportunity","el-icon-orange","el-icon-paperclip","el-icon-partly-cloudy","el-icon-pear","el-icon-phone","el-icon-phone-filled","el-icon-picture","el-icon-picture-filled","el-icon-picture-rounded","el-icon-pie-chart","el-icon-place","el-icon-platform","el-icon-plus","el-icon-pointer","el-icon-position","el-icon-postcard","el-icon-pouring","el-icon-present","el-icon-price-tag","el-icon-printer","el-icon-promotion","el-icon-question-filled","el-icon-rank","el-icon-reading","el-icon-reading-lamp","el-icon-refresh","el-icon-refresh-left","el-icon-refresh-right","el-icon-refrigerator","el-icon-remove","el-icon-remove-filled","el-icon-right","el-icon-scale-to-original","el-icon-school","el-icon-scissor","el-icon-search","el-icon-select","el-icon-sell","el-icon-semi-select","el-icon-service","el-icon-set-up","el-icon-setting","el-icon-share","el-icon-ship","el-icon-shop","el-icon-shopping-bag","el-icon-shopping-cart","el-icon-shopping-cart-full","el-icon-smoking","el-icon-soccer","el-icon-sold-out","el-icon-sort","el-icon-sort-down","el-icon-sort-up","el-icon-stamp","el-icon-star","el-icon-star-filled","el-icon-stopwatch","el-icon-success-filled","el-icon-sugar","el-icon-suitcase","el-icon-sunny","el-icon-sunrise","el-icon-sunset","el-icon-switch","el-icon-switch-button","el-icon-takeaway-box","el-icon-ticket","el-icon-tickets","el-icon-timer","el-icon-toilet-paper","el-icon-tools","el-icon-top","el-icon-top-left","el-icon-top-right","el-icon-trend-charts","el-icon-trophy","el-icon-turn-off","el-icon-umbrella","el-icon-unlock","el-icon-upload","el-icon-upload-filled","el-icon-user","el-icon-user-filled","el-icon-van","el-icon-video-camera","el-icon-video-camera-filled","el-icon-video-pause","el-icon-video-play","el-icon-view","el-icon-wallet","el-icon-wallet-filled","el-icon-warning","el-icon-warning-filled","el-icon-watch","el-icon-watermelon","el-icon-wind-power","el-icon-zoom-in","el-icon-zoom-out"],"name":"默认"},{"icons":["sc-icon-Vue","sc-icon-Code","sc-icon-Wechat","sc-icon-BugFill","sc-icon-BugLine","sc-icon-FileWord","sc-icon-FileExcel","sc-icon-FilePpt","sc-icon-Organization","sc-icon-Upload","sc-icon-Download","sc-icon-Role","sc-icon-Dept","sc-icon-Js","sc-icon-Memory","sc-icon-Dashboard","sc-icon-Api","sc-icon-Code2","sc-icon-Csharp","sc-icon-Dic","sc-icon-Position","sc-icon-Tpl","sc-icon-Demo","sc-icon-Link","sc-icon-Unlink","sc-icon-Send","sc-icon-Smscode","sc-icon-Meter","sc-icon-Grafana","sc-icon-Elastic","sc-icon-Kibana","sc-icon-Kafka","sc-icon-Resource","sc-icon-Robot","sc-icon-Device","sc-icon-Business","sc-icon-App","sc-icon-App2","sc-icon-Sync","sc-icon-Drone","sc-icon-Gitea","sc-icon-Docker","sc-icon-Task","sc-icon-ProductCategory","sc-icon-Product","sc-icon-Error","sc-icon-Warning","sc-icon-Stats","sc-icon-Log","sc-icon-OperLog","sc-icon-LoginLog","sc-icon-ExLog","sc-icon-Key","sc-icon-OpenDoor","sc-icon-Alert","sc-icon-Device","sc-icon-Task","sc-icon-Resource"],"name":"扩展"}]} \ No newline at end of file +export default{"icons":[{"icons":["el-icon-add-location","el-icon-aim","el-icon-alarm-clock","el-icon-apple","el-icon-arrow-down","el-icon-arrow-down-bold","el-icon-arrow-left","el-icon-arrow-left-bold","el-icon-arrow-right","el-icon-arrow-right-bold","el-icon-arrow-up","el-icon-arrow-up-bold","el-icon-avatar","el-icon-back","el-icon-baseball","el-icon-basketball","el-icon-bell","el-icon-bell-filled","el-icon-bicycle","el-icon-bottom","el-icon-bottom-left","el-icon-bottom-right","el-icon-bowl","el-icon-box","el-icon-briefcase","el-icon-brush","el-icon-brush-filled","el-icon-burger","el-icon-calendar","el-icon-camera","el-icon-camera-filled","el-icon-caret-bottom","el-icon-caret-left","el-icon-caret-right","el-icon-caret-top","el-icon-cellphone","el-icon-chat-dot-round","el-icon-chat-dot-square","el-icon-chat-line-round","el-icon-chat-line-square","el-icon-chat-round","el-icon-chat-square","el-icon-check","el-icon-checked","el-icon-cherry","el-icon-chicken","el-icon-circle-check","el-icon-circle-check-filled","el-icon-circle-close","el-icon-circle-close-filled","el-icon-circle-plus","el-icon-circle-plus-filled","el-icon-clock","el-icon-close","el-icon-close-bold","el-icon-cloudy","el-icon-coffee","el-icon-coffee-cup","el-icon-coin","el-icon-cold-drink","el-icon-collection","el-icon-collection-tag","el-icon-comment","el-icon-compass","el-icon-connection","el-icon-coordinate","el-icon-copy-document","el-icon-cpu","el-icon-credit-card","el-icon-crop","el-icon-d-arrow-left","el-icon-d-arrow-right","el-icon-d-caret","el-icon-data-analysis","el-icon-data-board","el-icon-data-line","el-icon-delete","el-icon-delete-filled","el-icon-delete-location","el-icon-dessert","el-icon-discount","el-icon-dish","el-icon-dish-dot","el-icon-document","el-icon-document-add","el-icon-document-checked","el-icon-document-copy","el-icon-document-delete","el-icon-document-remove","el-icon-download","el-icon-drizzling","el-icon-edit","el-icon-edit-pen","el-icon-eleme","el-icon-eleme-filled","el-icon-element-plus","el-icon-expand","el-icon-failed","el-icon-female","el-icon-files","el-icon-film","el-icon-filter","el-icon-finished","el-icon-first-aid-kit","el-icon-flag","el-icon-fold","el-icon-folder","el-icon-folder-add","el-icon-folder-checked","el-icon-folder-delete","el-icon-folder-opened","el-icon-folder-remove","el-icon-food","el-icon-football","el-icon-fork-spoon","el-icon-fries","el-icon-full-screen","el-icon-goblet","el-icon-goblet-full","el-icon-goblet-square","el-icon-goblet-square-full","el-icon-goods","el-icon-goods-filled","el-icon-grape","el-icon-grid","el-icon-guide","el-icon-headset","el-icon-help","el-icon-help-filled","el-icon-hide","el-icon-histogram","el-icon-home-filled","el-icon-hot-water","el-icon-house","el-icon-ice-cream","el-icon-ice-cream-round","el-icon-ice-cream-square","el-icon-ice-drink","el-icon-ice-tea","el-icon-info-filled","el-icon-iphone","el-icon-key","el-icon-knife-fork","el-icon-lightning","el-icon-link","el-icon-list","el-icon-loading","el-icon-location","el-icon-location-filled","el-icon-location-information","el-icon-lock","el-icon-lollipop","el-icon-magic-stick","el-icon-magnet","el-icon-male","el-icon-management","el-icon-map-location","el-icon-medal","el-icon-menu","el-icon-message","el-icon-message-box","el-icon-mic","el-icon-microphone","el-icon-milk-tea","el-icon-minus","el-icon-money","el-icon-monitor","el-icon-moon","el-icon-moon-night","el-icon-more","el-icon-more-filled","el-icon-mostly-cloudy","el-icon-mouse","el-icon-mug","el-icon-mute","el-icon-mute-notification","el-icon-no-smoking","el-icon-notebook","el-icon-notification","el-icon-odometer","el-icon-office-building","el-icon-open","el-icon-operation","el-icon-opportunity","el-icon-orange","el-icon-paperclip","el-icon-partly-cloudy","el-icon-pear","el-icon-phone","el-icon-phone-filled","el-icon-picture","el-icon-picture-filled","el-icon-picture-rounded","el-icon-pie-chart","el-icon-place","el-icon-platform","el-icon-plus","el-icon-pointer","el-icon-position","el-icon-postcard","el-icon-pouring","el-icon-present","el-icon-price-tag","el-icon-printer","el-icon-promotion","el-icon-question-filled","el-icon-rank","el-icon-reading","el-icon-reading-lamp","el-icon-refresh","el-icon-refresh-left","el-icon-refresh-right","el-icon-refrigerator","el-icon-remove","el-icon-remove-filled","el-icon-right","el-icon-scale-to-original","el-icon-school","el-icon-scissor","el-icon-search","el-icon-select","el-icon-sell","el-icon-semi-select","el-icon-service","el-icon-set-up","el-icon-setting","el-icon-share","el-icon-ship","el-icon-shop","el-icon-shopping-bag","el-icon-shopping-cart","el-icon-shopping-cart-full","el-icon-smoking","el-icon-soccer","el-icon-sold-out","el-icon-sort","el-icon-sort-down","el-icon-sort-up","el-icon-stamp","el-icon-star","el-icon-star-filled","el-icon-stopwatch","el-icon-success-filled","el-icon-sugar","el-icon-suitcase","el-icon-sunny","el-icon-sunrise","el-icon-sunset","el-icon-switch","el-icon-switch-button","el-icon-takeaway-box","el-icon-ticket","el-icon-tickets","el-icon-timer","el-icon-toilet-paper","el-icon-tools","el-icon-top","el-icon-top-left","el-icon-top-right","el-icon-trend-charts","el-icon-trophy","el-icon-turn-off","el-icon-umbrella","el-icon-unlock","el-icon-upload","el-icon-upload-filled","el-icon-user","el-icon-user-filled","el-icon-van","el-icon-video-camera","el-icon-video-camera-filled","el-icon-video-pause","el-icon-video-play","el-icon-view","el-icon-wallet","el-icon-wallet-filled","el-icon-warning","el-icon-warning-filled","el-icon-watch","el-icon-watermelon","el-icon-wind-power","el-icon-zoom-in","el-icon-zoom-out"],"name":"默认"},{"icons":["sc-icon-Vue","sc-icon-Code","sc-icon-Wechat","sc-icon-BugFill","sc-icon-BugLine","sc-icon-FileWord","sc-icon-FileExcel","sc-icon-FilePpt","sc-icon-Organization","sc-icon-Upload","sc-icon-Download","sc-icon-Role","sc-icon-Dept","sc-icon-Js","sc-icon-Memory","sc-icon-Dashboard","sc-icon-Api","sc-icon-Code2","sc-icon-Csharp","sc-icon-Dic","sc-icon-Position","sc-icon-Tpl","sc-icon-Demo","sc-icon-Link","sc-icon-Unlink","sc-icon-Send","sc-icon-Smscode","sc-icon-Meter","sc-icon-Grafana","sc-icon-Elastic","sc-icon-Kibana","sc-icon-Kafka","sc-icon-Resource","sc-icon-Robot","sc-icon-Device","sc-icon-Business","sc-icon-App","sc-icon-App2","sc-icon-Sync","sc-icon-Drone","sc-icon-Gitea","sc-icon-Docker","sc-icon-Task","sc-icon-ProductCategory","sc-icon-Product","sc-icon-Error","sc-icon-Warning","sc-icon-Stats","sc-icon-Log","sc-icon-OperLog","sc-icon-LoginLog","sc-icon-ExLog","sc-icon-Key","sc-icon-OpenDoor","sc-icon-Alert","sc-icon-Device","sc-icon-Task","sc-icon-Resource","sc-icon-Report","sc-icon-Daily"],"name":"扩展"}]} \ No newline at end of file diff --git a/src/frontend/admin/src/config/index.js b/src/frontend/admin/src/config/index.js index b3f39968..8e49a925 100644 --- a/src/frontend/admin/src/config/index.js +++ b/src/frontend/admin/src/config/index.js @@ -75,7 +75,7 @@ Object.assign(DEFAULT_CONFIG, MY_CONFIG) // 如果生产模式,就合并动态的APP_CONFIG // public/config.js -if (import.meta.env.PROD) { +if (import.meta.env.MODE === 'production' || import.meta.env.MODE === 'test') { Object.assign(DEFAULT_CONFIG, APP_CONFIG) } diff --git a/src/frontend/admin/src/layout/components/tasks.vue b/src/frontend/admin/src/layout/components/tasks.vue index 0277a06e..6b1f4d1e 100644 --- a/src/frontend/admin/src/layout/components/tasks.vue +++ b/src/frontend/admin/src/layout/components/tasks.vue @@ -1,59 +1,60 @@ \ No newline at end of file diff --git a/src/frontend/admin/src/layout/components/userbar.vue b/src/frontend/admin/src/layout/components/userbar.vue index 7c320d15..5393b5fe 100644 --- a/src/frontend/admin/src/layout/components/userbar.vue +++ b/src/frontend/admin/src/layout/components/userbar.vue @@ -1,5 +1,10 @@ + + + + \ No newline at end of file diff --git a/src/frontend/admin/src/views/sys/job/record/save.vue b/src/frontend/admin/src/views/sys/job/record/save.vue new file mode 100644 index 00000000..86e4e529 --- /dev/null +++ b/src/frontend/admin/src/views/sys/job/record/save.vue @@ -0,0 +1,87 @@ + + + \ No newline at end of file diff --git a/src/frontend/admin/src/views/sys/job/save.vue b/src/frontend/admin/src/views/sys/job/save.vue index 797a3010..3bfc9995 100644 --- a/src/frontend/admin/src/views/sys/job/save.vue +++ b/src/frontend/admin/src/views/sys/job/save.vue @@ -1,15 +1,15 @@