mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-04-23 14:42:51 +08:00
parent
6f32acaacf
commit
6f89015198
@ -17,7 +17,7 @@
|
|||||||
<LangVersion>preview</LangVersion>
|
<LangVersion>preview</LangVersion>
|
||||||
<MinVerDefaultPreReleaseIdentifiers>beta</MinVerDefaultPreReleaseIdentifiers>
|
<MinVerDefaultPreReleaseIdentifiers>beta</MinVerDefaultPreReleaseIdentifiers>
|
||||||
<MinVerTagPrefix>v</MinVerTagPrefix>
|
<MinVerTagPrefix>v</MinVerTagPrefix>
|
||||||
<NoWarn>CA1707;IDE0005;IDE0008;IDE0010;IDE0028;IDE0055;IDE0160;IDE0300;IDE0305;RCS1141;RCS1142;RCS1181;S101;S1121;S1135;S125;S2094;S3604;S4663;SYSLIB1045;SA1010</NoWarn>
|
<NoWarn>CA1707;IDE0005;IDE0008;IDE0010;IDE0028;IDE0055;IDE0160;IDE0300;IDE0305;RCS1141;RCS1142;RCS1181;S101;S1121;S1135;S125;S2094;S3604;S4663;S6561;SYSLIB1045;SA1010</NoWarn>
|
||||||
<Product>NetAdmin</Product>
|
<Product>NetAdmin</Product>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<RepositoryUrl>https://github.com/nsnail/NetAdmin.git</RepositoryUrl>
|
<RepositoryUrl>https://github.com/nsnail/NetAdmin.git</RepositoryUrl>
|
||||||
|
@ -34,6 +34,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{BB0B
|
|||||||
clean.ln.csx = scripts/clean.ln.csx
|
clean.ln.csx = scripts/clean.ln.csx
|
||||||
code.clean.csx = scripts/code.clean.csx
|
code.clean.csx = scripts/code.clean.csx
|
||||||
code.clean.ps1 = scripts/code.clean.ps1
|
code.clean.ps1 = scripts/code.clean.ps1
|
||||||
|
find.unused.ln.csx = scripts/find.unused.ln.csx
|
||||||
gen.cs.tt = scripts/gen.cs.tt
|
gen.cs.tt = scripts/gen.cs.tt
|
||||||
gen.id.linq = scripts/gen.id.linq
|
gen.id.linq = scripts/gen.id.linq
|
||||||
gen.ln.cmd = scripts/gen.ln.cmd
|
gen.ln.cmd = scripts/gen.ln.cmd
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"Enabled": true,
|
||||||
"Id": 372119301627909,
|
"Id": 372119301627909,
|
||||||
"Name": "默认部门",
|
"Name": "默认部门",
|
||||||
"Enabled": true,
|
|
||||||
"Sort": 100
|
"Sort": 100
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -1,10 +1,10 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"DataScope": 1,
|
"DataScope": 1,
|
||||||
|
"DisplayDashboard": true,
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
"Id": 370943613149253,
|
"Id": 370943613149253,
|
||||||
"IgnorePermissionControl": true,
|
"IgnorePermissionControl": true,
|
||||||
"DisplayDashboard": true,
|
|
||||||
"Name": "超级管理员",
|
"Name": "超级管理员",
|
||||||
"Sort": 100
|
"Sort": 100
|
||||||
},
|
},
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Content": "<p>尊敬的用户:</p>\n<p style=\"padding-left: 40px;\">欢迎您使用 NetAdmin 后台管理系统!NetAdmin 是一款通用后台权限管理系统和快速开发框架,它基于 C#12/.NET8、Vue3/Vite、Element Plus 等现代技术构建,具有十分整洁、优雅的编码规范。</p>\n<p style=\"padding-left: 40px;\">NetAdmin 致力于为企业提供高效、安全、易用的解决方案,帮助您快速构建出符合业务需求的应用程序。系统提供了丰富的功能模块,包括用户管理、权限管理、日志管理、文件上传等,可以满足您日常管理的需求。</p>\n<p style=\"padding-left: 40px;\">在使用 NetAdmin 的过程中,我们真诚地希望您能够遵守以下规定:</p>\n<p style=\"padding-left: 80px;\">1. 不得利用 NetAdmin 进行非法活动或者侵犯他人权益;</p>\n<p style=\"padding-left: 80px;\">2. 不得对 NetAdmin 系统进行恶意攻击或者破坏;</p>\n<p style=\"padding-left: 80px;\">3. 不得将 NetAdmin 系统的任何部分用于商业目的或者未经授权的访问。</p>\n<p style=\"padding-left: 80px;\">4. 为了更好地为您提供服务,NetAdmin 将不断进行优化和升级,同时也欢迎您提出宝贵的意见和建议。如果您在使用过程中遇到任何问题,可以通过官方网站或者技术支持团队进行咨询和解决。</p>\n<p style=\"padding-left: 40px;\">再次感谢您对 NetAdmin 的信任和支持!我们相信,在您的使用过程中,NetAdmin 一定会成为您的得力助手,为您的事业发展提供强有力的支持!</p>\n<p style=\"text-align: right;\">NetAdmin 开发团队</p>",
|
"Content": "<p>尊敬的用户:</p>\n<p style=\"padding-left: 40px;\">欢迎您使用 NetAdmin 后台管理系统!NetAdmin 是一款通用后台权限管理系统和快速开发框架,它基于 C#12/.NET8、Vue3/Vite、Element Plus 等现代技术构建,具有十分整洁、优雅的编码规范。</p>\n<p style=\"padding-left: 40px;\">NetAdmin 致力于为企业提供高效、安全、易用的解决方案,帮助您快速构建出符合业务需求的应用程序。系统提供了丰富的功能模块,包括用户管理、权限管理、日志管理、文件上传等,可以满足您日常管理的需求。</p>\n<p style=\"padding-left: 40px;\">在使用 NetAdmin 的过程中,我们真诚地希望您能够遵守以下规定:</p>\n<p style=\"padding-left: 80px;\">1. 不得利用 NetAdmin 进行非法活动或者侵犯他人权益;</p>\n<p style=\"padding-left: 80px;\">2. 不得对 NetAdmin 系统进行恶意攻击或者破坏;</p>\n<p style=\"padding-left: 80px;\">3. 不得将 NetAdmin 系统的任何部分用于商业目的或者未经授权的访问。</p>\n<p style=\"padding-left: 80px;\">4. 为了更好地为您提供服务,NetAdmin 将不断进行优化和升级,同时也欢迎您提出宝贵的意见和建议。如果您在使用过程中遇到任何问题,可以通过官方网站或者技术支持团队进行咨询和解决。</p>\n<p style=\"padding-left: 40px;\">再次感谢您对 NetAdmin 的信任和支持!我们相信,在您的使用过程中,NetAdmin 一定会成为您的得力助手,为您的事业发展提供强有力的支持!</p>\n<p style=\"text-align: right;\">NetAdmin 开发团队</p>",
|
||||||
|
"CreatedUserId": 370942943322181,
|
||||||
|
"CreatedUserName": "root",
|
||||||
"MsgType": 2,
|
"MsgType": 2,
|
||||||
"Summary": "尊敬的用户:\n欢迎您使用 NetAdmin 后台管理系统!NetAdmin 是一款通用后台权限管理系统和快速开发框架,它基于 C#12/.NET8、Vue3/Vite、Element Plus 等现代",
|
"Summary": "尊敬的用户:\n欢迎您使用 NetAdmin 后台管理系统!NetAdmin 是一款通用后台权限管理系统和快速开发框架,它基于 C#12/.NET8、Vue3/Vite、Element Plus 等现代",
|
||||||
"Title": "欢迎使用 NetAdmin 后台管理系统",
|
"Title": "欢迎使用 NetAdmin 后台管理系统",
|
||||||
"CreatedUserId": 370942943322181,
|
|
||||||
"CreatedUserName": "root",
|
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -15,7 +15,7 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.9.1-alpha">
|
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.9.28">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
cd ..
|
cd ..
|
||||||
$types = @{
|
$types = @{
|
||||||
'1' = @('major', '主版本')
|
'1' = @('major', '主版本')
|
||||||
'2' = @('minor', '此版本')
|
'2' = @('minor', '次版本')
|
||||||
'3' = @('patch', '修订版本')
|
'3' = @('patch', '修订版本')
|
||||||
}
|
}
|
||||||
$prefix = ''
|
$prefix = ''
|
||||||
|
@ -8,21 +8,13 @@ namespace NetAdmin.Application.Services;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TEntity">实体类型</typeparam>
|
/// <typeparam name="TEntity">实体类型</typeparam>
|
||||||
/// <typeparam name="TLogger">日志类型</typeparam>
|
/// <typeparam name="TLogger">日志类型</typeparam>
|
||||||
public abstract class RepositoryService<TEntity, TLogger> : ServiceBase<TLogger>
|
public abstract class RepositoryService<TEntity, TLogger>(DefaultRepository<TEntity> rpo) : ServiceBase<TLogger>
|
||||||
where TEntity : EntityBase
|
where TEntity : EntityBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="RepositoryService{TEntity, TLogger}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
protected RepositoryService(DefaultRepository<TEntity> rpo) //
|
|
||||||
{
|
|
||||||
Rpo = rpo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 默认仓储
|
/// 默认仓储
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected DefaultRepository<TEntity> Rpo { get; }
|
protected DefaultRepository<TEntity> Rpo => rpo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 启用级联保存
|
/// 启用级联保存
|
||||||
|
@ -5,21 +5,13 @@ namespace NetAdmin.Cache;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缓存基类
|
/// 缓存基类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class CacheBase<TCacheContainer, TService> : ICache<TCacheContainer, TService>
|
public abstract class CacheBase<TCacheContainer, TService>(TCacheContainer cache, TService service)
|
||||||
|
: ICache<TCacheContainer, TService>
|
||||||
where TService : IService
|
where TService : IService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Initializes a new instance of the <see cref="CacheBase{TCacheLoad, TService}" /> class.
|
public TCacheContainer Cache => cache;
|
||||||
/// </summary>
|
|
||||||
protected CacheBase(TCacheContainer cache, TService service)
|
|
||||||
{
|
|
||||||
Cache = cache;
|
|
||||||
Service = service;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TCacheContainer Cache { get; }
|
public TService Service => service;
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public TService Service { get; }
|
|
||||||
}
|
}
|
@ -6,15 +6,10 @@ namespace NetAdmin.Cache;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 分布式缓存
|
/// 分布式缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class DistributedCache<TService> : CacheBase<IDistributedCache, TService>
|
public abstract class DistributedCache<TService>(IDistributedCache cache, TService service)
|
||||||
|
: CacheBase<IDistributedCache, TService>(cache, service)
|
||||||
where TService : IService
|
where TService : IService
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="DistributedCache{TService}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
protected DistributedCache(IDistributedCache cache, TService service) //
|
|
||||||
: base(cache, service) { }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建缓存
|
/// 创建缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -5,12 +5,6 @@ namespace NetAdmin.Cache;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 内存缓存
|
/// 内存缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class MemoryCache<TService> : CacheBase<IMemoryCache, TService>
|
public abstract class MemoryCache<TService>(IMemoryCache cache, TService service)
|
||||||
where TService : IService
|
: CacheBase<IMemoryCache, TService>(cache, service)
|
||||||
{
|
where TService : IService;
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="MemoryCache{TService}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
protected MemoryCache(IMemoryCache cache, TService service) //
|
|
||||||
: base(cache, service) { }
|
|
||||||
}
|
|
@ -8,11 +8,14 @@ public abstract record DataAbstraction
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 如果数据校验失败,抛出异常
|
/// 如果数据校验失败,抛出异常
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <exception cref="NetAdminInvalidInputException">NetAdminInvalidInputException</exception>
|
/// <exception cref="NetAdminValidateException">NetAdminValidateException</exception>
|
||||||
public void ThrowIfInvalid()
|
public void ThrowIfInvalid()
|
||||||
{
|
{
|
||||||
if (!this.TryValidate().IsValid) {
|
var validationResult = this.TryValidate();
|
||||||
throw new NetAdminInvalidInputException(Ln.无效输入);
|
if (!validationResult.IsValid) {
|
||||||
|
throw new NetAdminValidateException(validationResult.ValidationResults.ToDictionary( //
|
||||||
|
x => x.MemberNames.First() //
|
||||||
|
, x => new[] { x.ErrorMessage }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,12 @@ public abstract record VersionEntity<T> : LiteVersionEntity<T>, IFieldModifiedUs
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
[Column(CanUpdate = false, Position = -1)]
|
[Column(CanUpdate = false, Position = -1)]
|
||||||
public long? CreatedUserId { get; init; }
|
public virtual long? CreatedUserId { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanUpdate = false, Position = -1)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanUpdate = false, Position = -1)]
|
||||||
public string CreatedUserName { get; init; }
|
public virtual string CreatedUserName { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||||
@ -34,10 +34,10 @@ public abstract record VersionEntity<T> : LiteVersionEntity<T>, IFieldModifiedUs
|
|||||||
/// <inheritdoc cref="IFieldModifiedUser.ModifiedUserId" />
|
/// <inheritdoc cref="IFieldModifiedUser.ModifiedUserId" />
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
[Column(CanInsert = false, Position = -1)]
|
[Column(CanInsert = false, Position = -1)]
|
||||||
public long? ModifiedUserId { get; init; }
|
public virtual long? ModifiedUserId { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IFieldModifiedUser.ModifiedUserName" />
|
/// <inheritdoc cref="IFieldModifiedUser.ModifiedUserName" />
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanInsert = false, Position = -1)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanInsert = false, Position = -1)]
|
||||||
public string ModifiedUserName { get; init; }
|
public virtual string ModifiedUserName { get; init; }
|
||||||
}
|
}
|
@ -98,6 +98,13 @@ public record Sys_Job : VersionEntity, IFieldEnabled, IFieldSummary
|
|||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
public virtual string Summary { get; init; }
|
public virtual string Summary { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行用户
|
||||||
|
/// </summary>
|
||||||
|
[Navigate(nameof(UserId))]
|
||||||
|
[JsonIgnore]
|
||||||
|
public Sys_User User { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行用户编号
|
/// 执行用户编号
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,68 +15,68 @@ public record Sys_JobRecord : LiteImmutableEntity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Column]
|
[Column]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public long Duration { get; init; }
|
public virtual long Duration { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求方法
|
/// 请求方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
[Column]
|
[Column]
|
||||||
public HttpMethods HttpMethod { get; init; }
|
public virtual HttpMethods HttpMethod { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// HTTP 状态码
|
/// HTTP 状态码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column]
|
[Column]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public HttpStatusCode HttpStatusCode { get; init; }
|
public virtual int HttpStatusCode { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 作业编号
|
/// 作业编号
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column]
|
[Column]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public long JobId { get; init; }
|
public virtual long JobId { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求体
|
/// 请求体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string RequestBody { get; init; }
|
public virtual string RequestBody { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求头
|
/// 请求头
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string RequestHeader { get; init; }
|
public virtual string RequestHeader { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求的网络地址
|
/// 请求的网络地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string RequestUrl { get; init; }
|
public virtual string RequestUrl { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 响应体
|
/// 响应体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string ResponseBody { get; init; }
|
public virtual string ResponseBody { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 响应头
|
/// 响应头
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string ResponseHeader { get; init; }
|
public virtual string ResponseHeader { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行时间编号
|
/// 执行时间编号
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column]
|
[Column]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public long TimeId { get; init; }
|
public virtual long TimeId { get; init; }
|
||||||
}
|
}
|
@ -28,7 +28,7 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(Position = -1)]
|
[Column(Position = -1)]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual int? CreatedClientIp { get; init; }
|
public int? CreatedClientIp { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建者来源地址
|
/// 创建者来源地址
|
||||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
|||||||
/// 角色-接口映射表
|
/// 角色-接口映射表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleApi))]
|
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleApi))]
|
||||||
public sealed record Sys_RoleApi : ImmutableEntity
|
public record Sys_RoleApi : ImmutableEntity
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 关联的接口
|
/// 关联的接口
|
||||||
|
@ -7,7 +7,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleDept))]
|
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleDept))]
|
||||||
[Index($"idx_{{tablename}}_{nameof(RoleId)}_{nameof(DeptId)}", $"{nameof(RoleId)},{nameof(DeptId)}", true)]
|
[Index($"idx_{{tablename}}_{nameof(RoleId)}_{nameof(DeptId)}", $"{nameof(RoleId)},{nameof(DeptId)}", true)]
|
||||||
public sealed record Sys_RoleDept : ImmutableEntity
|
public record Sys_RoleDept : ImmutableEntity
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 关联的部门
|
/// 关联的部门
|
||||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
|||||||
/// 用户-角色映射表
|
/// 用户-角色映射表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_UserRole))]
|
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_UserRole))]
|
||||||
public sealed record Sys_UserRole : VersionEntity
|
public record Sys_UserRole : VersionEntity
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 关联的角色
|
/// 关联的角色
|
||||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.Dto.Dependency;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 动态过滤条件
|
/// 动态过滤条件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record DynamicFilterInfo : DataAbstraction
|
public sealed record DynamicFilterInfo : DataAbstraction
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 字段名
|
/// 字段名
|
||||||
|
@ -6,10 +6,10 @@ namespace NetAdmin.Domain.Dto.Sys.Dept;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 响应:查询部门
|
/// 响应:查询部门
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record QueryDeptRsp : Sys_Dept
|
public sealed record QueryDeptRsp : Sys_Dept
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="Sys_Dept.Children" />
|
/// <inheritdoc cref="Sys_Dept.Children" />
|
||||||
public new virtual IEnumerable<QueryDeptRsp> Children { get; init; }
|
public new IEnumerable<QueryDeptRsp> Children { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
|
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||||
using NetAdmin.Domain.DbMaps.Sys;
|
using NetAdmin.Domain.DbMaps.Sys;
|
||||||
|
using NetAdmin.Domain.Dto.Sys.User;
|
||||||
using NetAdmin.Domain.Enums.Sys;
|
using NetAdmin.Domain.Enums.Sys;
|
||||||
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
|
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
|
||||||
|
|
||||||
@ -14,6 +15,14 @@ public sealed record QueryJobRsp : Sys_Job
|
|||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
public override DateTime CreatedTime { get; init; }
|
public override DateTime CreatedTime { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFieldCreatedUser.CreatedUserId" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override long? CreatedUserId { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFieldCreatedUser.CreatedUserName" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override string CreatedUserName { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
public override bool Enabled { get; init; }
|
public override bool Enabled { get; init; }
|
||||||
@ -42,6 +51,18 @@ public sealed record QueryJobRsp : Sys_Job
|
|||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public override HttpStatusCode? LastStatusCode { get; init; }
|
public override HttpStatusCode? LastStatusCode { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFieldModifiedTime.ModifiedTime" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override DateTime? ModifiedTime { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFieldModifiedUser.ModifiedUserId" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override long? ModifiedUserId { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFieldModifiedUser.ModifiedUserName" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override string ModifiedUserName { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="Sys_Job.NextExecTime" />
|
/// <inheritdoc cref="Sys_Job.NextExecTime" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public override DateTime? NextExecTime { get; init; }
|
public override DateTime? NextExecTime { get; init; }
|
||||||
@ -70,6 +91,9 @@ public sealed record QueryJobRsp : Sys_Job
|
|||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public override string Summary { get; init; }
|
public override string Summary { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_Job.User" />
|
||||||
|
public new QueryUserRsp User { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="Sys_Job.UserId" />
|
/// <inheritdoc cref="Sys_Job.UserId" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
public override long UserId { get; init; }
|
public override long UserId { get; init; }
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||||
using NetAdmin.Domain.DbMaps.Sys;
|
using NetAdmin.Domain.DbMaps.Sys;
|
||||||
|
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
|
||||||
|
|
||||||
namespace NetAdmin.Domain.Dto.Sys.JobRecord;
|
namespace NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||||
|
|
||||||
@ -8,7 +9,51 @@ namespace NetAdmin.Domain.Dto.Sys.JobRecord;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record QueryJobRecordRsp : Sys_JobRecord
|
public sealed record QueryJobRecordRsp : Sys_JobRecord
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
|
public override DateTime CreatedTime { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.Duration" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
|
public override long Duration { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.HttpMethod" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
|
public override HttpMethods HttpMethod { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.HttpStatusCode" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
|
public override int HttpStatusCode { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
public override long Id { get; init; }
|
public override long Id { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.JobId" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
|
public override long JobId { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.RequestBody" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override string RequestBody { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.RequestHeader" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override string RequestHeader { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.RequestUrl" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override string RequestUrl { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.ResponseBody" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override string ResponseBody { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.ResponseHeader" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override string ResponseHeader { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.TimeId" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
|
public override long TimeId { get; init; }
|
||||||
}
|
}
|
@ -3,7 +3,7 @@ namespace NetAdmin.Domain.Dto.Sys.Tool;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 响应:获取模块信息
|
/// 响应:获取模块信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record GetModulesRsp : DataAbstraction
|
public sealed record GetModulesRsp : DataAbstraction
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 模块名称
|
/// 模块名称
|
||||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.Dto.Sys.User;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求:创建用户
|
/// 请求:创建用户
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record CreateUserReq : CreateUpdateUserReq, IRegister
|
public sealed record CreateUserReq : CreateUpdateUserReq, IRegister
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="CreateUpdateUserReq.PasswordText" />
|
/// <inheritdoc cref="CreateUpdateUserReq.PasswordText" />
|
||||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.密码不能为空))]
|
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.密码不能为空))]
|
||||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.Dto.Sys.User;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求:密码登录
|
/// 请求:密码登录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record LoginByPwdReq : DataAbstraction
|
public sealed record LoginByPwdReq : DataAbstraction
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户名、手机号、邮箱
|
/// 用户名、手机号、邮箱
|
||||||
|
@ -5,4 +5,4 @@ namespace NetAdmin.Domain.Dto.Sys.User;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求:短信登录
|
/// 请求:短信登录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record LoginBySmsReq : VerifySmsCodeReq;
|
public sealed record LoginBySmsReq : VerifySmsCodeReq;
|
@ -3,7 +3,7 @@ namespace NetAdmin.Domain.Dto.Sys.User;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 响应:密码登录
|
/// 响应:密码登录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record LoginRsp : DataAbstraction
|
public sealed record LoginRsp : DataAbstraction
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 访问令牌
|
/// 访问令牌
|
||||||
|
@ -7,7 +7,7 @@ namespace NetAdmin.Domain.Dto.Sys.User;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求:注册用户
|
/// 请求:注册用户
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record RegisterUserReq : Sys_User
|
public sealed record RegisterUserReq : Sys_User
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 密码
|
/// 密码
|
||||||
@ -15,7 +15,7 @@ public record RegisterUserReq : Sys_User
|
|||||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.密码不能为空))]
|
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.密码不能为空))]
|
||||||
[Password]
|
[Password]
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
public virtual string PasswordText { get; init; }
|
public string PasswordText { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色编号列表
|
/// 角色编号列表
|
||||||
|
@ -7,7 +7,7 @@ namespace NetAdmin.Domain.Dto.Sys.User;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 响应:当前用户信息
|
/// 响应:当前用户信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record UserInfoRsp : QueryUserRsp, IRegister
|
public sealed record UserInfoRsp : QueryUserRsp, IRegister
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="Sys_User.Dept" />
|
/// <inheritdoc cref="Sys_User.Dept" />
|
||||||
public override QueryDeptRsp Dept { get; init; }
|
public override QueryDeptRsp Dept { get; init; }
|
||||||
|
@ -18,7 +18,7 @@ public sealed record SqlCommandAfterEvent : SqlCommandBeforeEvent
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 耗时(单位:微秒)
|
/// 耗时(单位:微秒)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long ElapsedMicroseconds { get; set; }
|
public long ElapsedMicroseconds { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
@ -5,19 +5,11 @@ namespace NetAdmin.Host.BackgroundRunning;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 轮询工作
|
/// 轮询工作
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class PollingWork<TWorkData> : WorkBase<TWorkData>
|
public abstract class PollingWork<TWorkData>(TWorkData workData) : WorkBase<TWorkData>
|
||||||
where TWorkData : DataAbstraction
|
where TWorkData : DataAbstraction
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="PollingWork{TWorkData}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
protected PollingWork(TWorkData workData)
|
|
||||||
{
|
|
||||||
WorkData = workData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 工作数据
|
/// 工作数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected TWorkData WorkData { get; }
|
protected TWorkData WorkData => workData;
|
||||||
}
|
}
|
@ -54,7 +54,7 @@ public abstract class WorkBase<TLogger>
|
|||||||
/// 通用工作流
|
/// 通用工作流
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <exception cref="NetAdminGetLockerException">加锁失败异常</exception>
|
/// <exception cref="NetAdminGetLockerException">加锁失败异常</exception>
|
||||||
protected async ValueTask WorkflowAsync(bool singleInstance, CancellationToken cancelToken)
|
protected virtual async ValueTask WorkflowAsync(bool singleInstance, CancellationToken cancelToken)
|
||||||
{
|
{
|
||||||
if (singleInstance) {
|
if (singleInstance) {
|
||||||
// 加锁
|
// 加锁
|
||||||
|
@ -6,20 +6,12 @@ namespace NetAdmin.Host.Controllers;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 控制器基类
|
/// 控制器基类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ControllerBase<TCache, TService> : IDynamicApiController
|
public abstract class ControllerBase<TCache, TService>(TCache cache) : IDynamicApiController
|
||||||
where TCache : ICache<IDistributedCache, TService> //
|
where TCache : ICache<IDistributedCache, TService> //
|
||||||
where TService : IService
|
where TService : IService
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ControllerBase{TCache, TService}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
protected ControllerBase(TCache cache)
|
|
||||||
{
|
|
||||||
Cache = cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 关联的缓存
|
/// 关联的缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected TCache Cache { get; }
|
protected TCache Cache => cache;
|
||||||
}
|
}
|
@ -25,7 +25,10 @@ public abstract class ApiResultHandler<T>
|
|||||||
{
|
{
|
||||||
var lineException = context.Exception switch { NetAdminException ex => ex, _ => null };
|
var lineException = context.Exception switch { NetAdminException ex => ex, _ => null };
|
||||||
var errorCode = lineException?.Code ?? ErrorCodes.Unhandled;
|
var errorCode = lineException?.Code ?? ErrorCodes.Unhandled;
|
||||||
var result = RestfulResult(errorCode, metadata.Data, lineException?.Message ?? errorCode.ResDesc<ErrorCodes>());
|
var result = RestfulResult(errorCode, metadata.Data
|
||||||
|
, lineException is NetAdminValidateException vEx
|
||||||
|
? vEx.ValidateResults
|
||||||
|
: lineException?.Message ?? errorCode.ResDesc<ErrorCodes>());
|
||||||
|
|
||||||
SetErrorCodeToHeader(context.HttpContext, errorCode);
|
SetErrorCodeToHeader(context.HttpContext, errorCode);
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ public static class Numbers
|
|||||||
public const long DIC_CATALOG_ID_GEO_AREA = 379794295185413; // 字典目录编号-行政区划字典
|
public const long DIC_CATALOG_ID_GEO_AREA = 379794295185413; // 字典目录编号-行政区划字典
|
||||||
public const int HEART_TIMEOUT_SECS = 600; // 心跳超时时间
|
public const int HEART_TIMEOUT_SECS = 600; // 心跳超时时间
|
||||||
public const int HTTP_STATUS_BIZ_FAIL = 900; // Http状态码-业务异常
|
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_DEF_PAGE_SIZE = 20; // 分页查询默认的页容量
|
||||||
public const int QUERY_LIMIT = 100; // 非分页查询允许返回的最大条数
|
public const int QUERY_LIMIT = 100; // 非分页查询允许返回的最大条数
|
||||||
public const int QUERY_MAX_PAGE_NO = 1000; // 分页查询允许最大的页码
|
public const int QUERY_MAX_PAGE_NO = 1000; // 分页查询允许最大的页码
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
namespace NetAdmin.Infrastructure.Exceptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证失败异常
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 手动调用模型验证方法抛出
|
||||||
|
/// </remarks>
|
||||||
|
#pragma warning disable RCS1194
|
||||||
|
public sealed class NetAdminValidateException(Dictionary<string, string[]> validateResults)
|
||||||
|
: NetAdminException(ErrorCodes.InvalidInput)
|
||||||
|
#pragma warning restore RCS1194
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 验证结果
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, string[]> ValidateResults { get; } = validateResults;
|
||||||
|
}
|
@ -13,25 +13,21 @@ public static class HttpRequestPartExtensions
|
|||||||
public static HttpRequestPart SetLog<T>(this HttpRequestPart me, ILogger<T> logger
|
public static HttpRequestPart SetLog<T>(this HttpRequestPart me, ILogger<T> logger
|
||||||
, Func<string, string> bodyHandle = null)
|
, Func<string, string> bodyHandle = null)
|
||||||
{
|
{
|
||||||
#pragma warning disable S1172
|
Task RequestHandleAsync(HttpClient _, HttpRequestMessage req)
|
||||||
|
|
||||||
Task RequestHandle(HttpClient _, HttpRequestMessage req)
|
|
||||||
{
|
{
|
||||||
return req.LogAsync(logger);
|
return req.LogAsync(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task ExceptionHandle(HttpClient _, HttpResponseMessage rsp, string errors)
|
Task ExceptionHandleAsync(HttpClient _, HttpResponseMessage rsp, string errors)
|
||||||
{
|
{
|
||||||
return rsp.LogExceptionAsync(errors, logger, bodyHandle);
|
return rsp.LogExceptionAsync(errors, logger, bodyHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task ResponseHandle(HttpClient _, HttpResponseMessage rsp)
|
Task ResponseHandleAsync(HttpClient _, HttpResponseMessage rsp)
|
||||||
{
|
{
|
||||||
return rsp.LogAsync(logger, bodyHandle);
|
return rsp.LogAsync(logger, bodyHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning restore S1172
|
return me.OnRequesting(RequestHandleAsync).OnResponsing(ResponseHandleAsync).OnException(ExceptionHandleAsync);
|
||||||
|
|
||||||
return me.OnRequesting(RequestHandle).OnResponsing(ResponseHandle).OnException(ExceptionHandle);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,6 +6,7 @@ namespace NetAdmin.Infrastructure.Extensions;
|
|||||||
public static class StringExtensions
|
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$");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// object -> json
|
/// object -> json
|
||||||
@ -23,6 +24,16 @@ public static class StringExtensions
|
|||||||
return me.Object(toType, GlobalStatic.JsonSerializerOptions);
|
return me.Object(toType, GlobalStatic.JsonSerializerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 去掉尾部字符串“Async”
|
||||||
|
/// </summary>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 去掉尾部字符串“Options”
|
/// 去掉尾部字符串“Options”
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -6,14 +6,14 @@
|
|||||||
<Import Project="$(SolutionDir)/build/copy.pkg.xml.comment.files.targets"/>
|
<Import Project="$(SolutionDir)/build/copy.pkg.xml.comment.files.targets"/>
|
||||||
<Import Project="$(SolutionDir)/build/prebuild.targets"/>
|
<Import Project="$(SolutionDir)/build/prebuild.targets"/>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Cronos" Version="0.8.2"/>
|
<PackageReference Include="Cronos" Version="0.8.3"/>
|
||||||
<PackageReference Include="FreeSql.DbContext.NS" Version="3.2.810-preview20231229-ns1"/>
|
<PackageReference Include="FreeSql.DbContext.NS" Version="3.2.810-preview20231229-ns1"/>
|
||||||
<PackageReference Include="FreeSql.Provider.Sqlite.NS" Version="3.2.810-preview20231229-ns1"/>
|
<PackageReference Include="FreeSql.Provider.Sqlite.NS" Version="3.2.810-preview20231229-ns1"/>
|
||||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.1.24"/>
|
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.1.24"/>
|
||||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.1.24-ns1"/>
|
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.1.24-ns1"/>
|
||||||
<PackageReference Include="Furion.Pure.NS" Version="4.9.1.24-ns1"/>
|
<PackageReference Include="Furion.Pure.NS" Version="4.9.1.24-ns1"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.1"/>
|
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.1"/>
|
||||||
<PackageReference Include="Minio" Version="6.0.1"/>
|
<PackageReference Include="Minio" Version="6.0.2"/>
|
||||||
<PackageReference Include="NSExt" Version="2.0.11"/>
|
<PackageReference Include="NSExt" Version="2.0.11"/>
|
||||||
<PackageReference Include="RedLock.net" Version="2.3.2"/>
|
<PackageReference Include="RedLock.net" Version="2.3.2"/>
|
||||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0"/>
|
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0"/>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using NetAdmin.Application.Modules;
|
using NetAdmin.Application.Modules;
|
||||||
using NetAdmin.Domain.Dto.Dependency;
|
using NetAdmin.Domain.Dto.Dependency;
|
||||||
using NetAdmin.Domain.Dto.Sys.Job;
|
using NetAdmin.Domain.Dto.Sys.Job;
|
||||||
|
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||||
|
|
||||||
namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
||||||
|
|
||||||
@ -13,6 +14,16 @@ public interface IJobModule : ICrudModule<CreateJobReq, QueryJobRsp // 创建类
|
|||||||
, DelReq // 删除类型
|
, DelReq // 删除类型
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取单个作业记录
|
||||||
|
/// </summary>
|
||||||
|
Task<QueryJobRecordRsp> RecordGetAsync(QueryJobRecordReq req);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 分页查询作业记录
|
||||||
|
/// </summary>
|
||||||
|
Task<PagedQueryRsp<QueryJobRecordRsp>> RecordPagedQueryAsync(PagedQueryReq<QueryJobRecordReq> req);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 启用/禁用作业
|
/// 启用/禁用作业
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -18,4 +18,9 @@ public interface IJobService : IService, IJobModule
|
|||||||
/// 获取下一个要执行的计划作业
|
/// 获取下一个要执行的计划作业
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<QueryJobRsp> GetNextJobAsync();
|
Task<QueryJobRsp> GetNextJobAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 释放卡死的任务
|
||||||
|
/// </summary>
|
||||||
|
Task<int> ReleaseStuckTaskAsync();
|
||||||
}
|
}
|
@ -102,6 +102,9 @@ public sealed class JobRecordService(DefaultRepository<Sys_JobRecord> rpo) //
|
|||||||
{
|
{
|
||||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||||
.WhereDynamic(req.Filter)
|
.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);
|
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||||
ret = ret.OrderByDescending(a => a.Id);
|
ret = ret.OrderByDescending(a => a.Id);
|
||||||
|
@ -4,6 +4,7 @@ using NetAdmin.Application.Services;
|
|||||||
using NetAdmin.Domain.DbMaps.Sys;
|
using NetAdmin.Domain.DbMaps.Sys;
|
||||||
using NetAdmin.Domain.Dto.Dependency;
|
using NetAdmin.Domain.Dto.Dependency;
|
||||||
using NetAdmin.Domain.Dto.Sys.Job;
|
using NetAdmin.Domain.Dto.Sys.Job;
|
||||||
|
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||||
using NetAdmin.Domain.Enums.Sys;
|
using NetAdmin.Domain.Enums.Sys;
|
||||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||||
using DataType = FreeSql.DataType;
|
using DataType = FreeSql.DataType;
|
||||||
@ -11,7 +12,7 @@ using DataType = FreeSql.DataType;
|
|||||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||||
|
|
||||||
/// <inheritdoc cref="IJobService" />
|
/// <inheritdoc cref="IJobService" />
|
||||||
public sealed class JobService(DefaultRepository<Sys_Job> rpo) //
|
public sealed class JobService(DefaultRepository<Sys_Job> rpo, IJobRecordService jobRecordService) //
|
||||||
: RepositoryService<Sys_Job, IJobService>(rpo), IJobService
|
: RepositoryService<Sys_Job, IJobService>(rpo), IJobService
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -134,6 +135,28 @@ public sealed class JobService(DefaultRepository<Sys_Job> rpo) //
|
|||||||
return ret.Adapt<IEnumerable<QueryJobRsp>>();
|
return ret.Adapt<IEnumerable<QueryJobRsp>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<QueryJobRecordRsp> RecordGetAsync(QueryJobRecordReq req)
|
||||||
|
{
|
||||||
|
req.ThrowIfInvalid();
|
||||||
|
return jobRecordService.GetAsync(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<PagedQueryRsp<QueryJobRecordRsp>> RecordPagedQueryAsync(PagedQueryReq<QueryJobRecordReq> req)
|
||||||
|
{
|
||||||
|
return jobRecordService.PagedQueryAsync(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<int> 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();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task SetEnabledAsync(UpdateJobReq req)
|
public Task SetEnabledAsync(UpdateJobReq req)
|
||||||
{
|
{
|
||||||
@ -162,7 +185,8 @@ public sealed class JobService(DefaultRepository<Sys_Job> rpo) //
|
|||||||
|
|
||||||
private ISelect<Sys_Job> QueryInternal(QueryReq<QueryJobReq> req, bool orderByRandom = false)
|
private ISelect<Sys_Job> QueryInternal(QueryReq<QueryJobReq> 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)
|
.WhereDynamic(req.Filter)
|
||||||
.WhereIf( //
|
.WhereIf( //
|
||||||
req.Keywords?.Length > 0
|
req.Keywords?.Length > 0
|
||||||
|
@ -40,7 +40,7 @@ public interface IUserCache : ICache<IDistributedCache, IUserService>, IUserModu
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除缓存 RegisterAsync
|
/// 删除缓存 RegisterAsync
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task RemoveRegisterAsync(RegisterUserReq userReq);
|
Task RemoveRegisterAsync(RegisterUserReq req);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除缓存 ResetPasswordAsync
|
/// 删除缓存 ResetPasswordAsync
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using NetAdmin.Cache;
|
using NetAdmin.Cache;
|
||||||
using NetAdmin.Domain.Dto.Dependency;
|
using NetAdmin.Domain.Dto.Dependency;
|
||||||
using NetAdmin.Domain.Dto.Sys.Job;
|
using NetAdmin.Domain.Dto.Sys.Job;
|
||||||
|
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||||
using NetAdmin.SysComponent.Cache.Sys.Dependency;
|
using NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||||
|
|
||||||
@ -52,6 +53,18 @@ public sealed class JobCache(IDistributedCache cache, IJobService service)
|
|||||||
return Service.QueryAsync(req);
|
return Service.QueryAsync(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<QueryJobRecordRsp> RecordGetAsync(QueryJobRecordReq req)
|
||||||
|
{
|
||||||
|
return Service.RecordGetAsync(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<PagedQueryRsp<QueryJobRecordRsp>> RecordPagedQueryAsync(PagedQueryReq<QueryJobRecordReq> req)
|
||||||
|
{
|
||||||
|
return Service.RecordPagedQueryAsync(req);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task SetEnabledAsync(UpdateJobReq req)
|
public Task SetEnabledAsync(UpdateJobReq req)
|
||||||
{
|
{
|
||||||
|
@ -120,7 +120,7 @@ public sealed class UserCache(IDistributedCache cache, IUserService service, IVe
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task RemoveRegisterAsync(RegisterUserReq userReq)
|
public Task RemoveRegisterAsync(RegisterUserReq req)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using NetAdmin.Domain.Dto.Dependency;
|
using NetAdmin.Domain.Dto.Dependency;
|
||||||
using NetAdmin.Domain.Dto.Sys.Job;
|
using NetAdmin.Domain.Dto.Sys.Job;
|
||||||
|
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||||
using NetAdmin.Host.Attributes;
|
using NetAdmin.Host.Attributes;
|
||||||
using NetAdmin.Host.Controllers;
|
using NetAdmin.Host.Controllers;
|
||||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||||
@ -73,6 +74,22 @@ public sealed class JobController(IJobCache cache) : ControllerBase<IJobCache, I
|
|||||||
return Cache.QueryAsync(req);
|
return Cache.QueryAsync(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取单个作业记录
|
||||||
|
/// </summary>
|
||||||
|
public Task<QueryJobRecordRsp> RecordGetAsync(QueryJobRecordReq req)
|
||||||
|
{
|
||||||
|
return Cache.RecordGetAsync(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 分页查询作业记录
|
||||||
|
/// </summary>
|
||||||
|
public Task<PagedQueryRsp<QueryJobRecordRsp>> RecordPagedQueryAsync(PagedQueryReq<QueryJobRecordReq> req)
|
||||||
|
{
|
||||||
|
return Cache.RecordPagedQueryAsync(req);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 启用/禁用作业
|
/// 启用/禁用作业
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -14,8 +14,11 @@ public static class ServiceCollectionExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static IServiceCollection AddSchedules(this IServiceCollection me)
|
public static IServiceCollection AddSchedules(this IServiceCollection me)
|
||||||
{
|
{
|
||||||
return me.AddSchedule( //
|
return App.WebHostEnvironment.EnvironmentName != Environments.Production
|
||||||
|
? me
|
||||||
|
: me.AddSchedule( //
|
||||||
builder => builder //
|
builder => builder //
|
||||||
.AddJob<ScheduledJob>(false, Triggers.PeriodSeconds(5).SetRunOnStart(true)));
|
.AddJob<ScheduledJob>(false, Triggers.PeriodSeconds(5).SetRunOnStart(true))
|
||||||
|
.AddJob<FreeScheduledJob>(false, Triggers.PeriodMinutes(1).SetRunOnStart(true)));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
using Furion.Schedule;
|
||||||
|
using NetAdmin.Host.BackgroundRunning;
|
||||||
|
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||||
|
|
||||||
|
namespace NetAdmin.SysComponent.Host.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 释放计划作业
|
||||||
|
/// </summary>
|
||||||
|
public sealed class FreeScheduledJob : WorkBase<FreeScheduledJob>, IJob
|
||||||
|
{
|
||||||
|
private readonly IJobService _jobService;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="FreeScheduledJob" /> class.
|
||||||
|
/// </summary>
|
||||||
|
public FreeScheduledJob()
|
||||||
|
{
|
||||||
|
_jobService = ServiceProvider.GetService<IJobService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 具体处理逻辑
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">作业执行前上下文</param>
|
||||||
|
/// <param name="stoppingToken">取消任务 Token</param>
|
||||||
|
/// <exception cref="NetAdminGetLockerException">加锁失败异常</exception>
|
||||||
|
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
await WorkflowAsync(true, stoppingToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通用工作流
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="NotImplementedException">NotImplementedException</exception>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">ArgumentOutOfRangeException</exception>
|
||||||
|
protected override async ValueTask WorkflowAsync(CancellationToken cancelToken)
|
||||||
|
{
|
||||||
|
_ = await _jobService.ReleaseStuckTaskAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
@ -87,7 +87,7 @@ public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
|
|||||||
{
|
{
|
||||||
Duration = sw.ElapsedMilliseconds
|
Duration = sw.ElapsedMilliseconds
|
||||||
, HttpMethod = job.HttpMethod
|
, HttpMethod = job.HttpMethod
|
||||||
, HttpStatusCode = rsp.StatusCode
|
, HttpStatusCode = (int)rsp.StatusCode
|
||||||
, JobId = job.Id
|
, JobId = job.Id
|
||||||
, RequestBody = job.RequestBody
|
, RequestBody = job.RequestBody
|
||||||
, RequestHeader = _requestHeader
|
, RequestHeader = _requestHeader
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
<ProjectReference Include="../NetAdmin.Host/NetAdmin.Host.csproj"/>
|
<ProjectReference Include="../NetAdmin.Host/NetAdmin.Host.csproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="xunit" Version="2.6.6"/>
|
<PackageReference Include="xunit" Version="2.7.0"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.1"/>
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.1"/>
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.7">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build --mode production",
|
||||||
|
"build:test": "vite build --mode test",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"prettier": "prettier --write ."
|
"prettier": "prettier --write ."
|
||||||
},
|
},
|
||||||
@ -12,34 +13,34 @@
|
|||||||
"@tinymce/tinymce-vue": "^5.1.1",
|
"@tinymce/tinymce-vue": "^5.1.1",
|
||||||
"axios": "^1.6.7",
|
"axios": "^1.6.7",
|
||||||
"clipboard": "^2.0.11",
|
"clipboard": "^2.0.11",
|
||||||
"core-js": "^3.35.1",
|
"core-js": "^3.36.0",
|
||||||
"cropperjs": "^1.6.1",
|
"cropperjs": "^1.6.1",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"echarts": "^5.4.3",
|
"echarts": "^5.4.3",
|
||||||
"element-plus": "^2.5.3",
|
"element-plus": "^2.5.5",
|
||||||
"json-bigint": "^1.0.0",
|
"json-bigint": "^1.0.0",
|
||||||
"json5-to-table": "^0.1.8",
|
"json5-to-table": "^0.1.8",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinyin-match": "^1.2.5",
|
"pinyin-match": "^1.2.5",
|
||||||
"qrcodejs2": "^0.0.2",
|
"qrcodejs2": "^0.0.2",
|
||||||
"sortablejs": "^1.15.2",
|
"sortablejs": "^1.15.2",
|
||||||
"tinymce": "^6.8.2",
|
"tinymce": "^6.8.3",
|
||||||
"vue": "^3.4.15",
|
"vue": "^3.4.19",
|
||||||
"vue-i18n": "^9.9.0",
|
"vue-i18n": "^9.9.1",
|
||||||
"vue-router": "^4.2.5",
|
"vue-router": "^4.2.5",
|
||||||
"vue3-json-viewer": "^2.2.2",
|
"vue3-json-viewer": "^2.2.2",
|
||||||
"vuedraggable": "^4.0.3",
|
"vuedraggable": "^4.0.3",
|
||||||
"vuex": "^4.1.0",
|
"vuex": "^4.1.0",
|
||||||
"xgplayer": "^3.0.11",
|
"xgplayer": "^3.0.12",
|
||||||
"xgplayer-hls": "^3.0.11"
|
"xgplayer-hls": "^3.0.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.0.3",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
"prettier": "^3.2.4",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-organize-attributes": "^1.0.0",
|
"prettier-plugin-organize-attributes": "^1.0.0",
|
||||||
"sass": "^1.70.0",
|
"sass": "^1.71.0",
|
||||||
"terser": "^5.27.0",
|
"terser": "^5.27.1",
|
||||||
"vite": "^5.0.12"
|
"vite": "^5.1.3"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 1%",
|
"> 1%",
|
||||||
|
@ -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)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启用/禁用作业
|
* 启用/禁用作业
|
||||||
*/
|
*/
|
||||||
|
10
src/frontend/admin/src/assets/icons/Daily.vue
Normal file
10
src/frontend/admin/src/assets/icons/Daily.vue
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<template>
|
||||||
|
<svg class="icon" height="128" p-id="4304" t="1708217899083" version="1.1" viewBox="0 0 1024 1024" width="128" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M497.3 409.6c-1.6 3.7-4.8 7-9.6 10s-9.3 4.8-13.6 5.5c-4.2 0.7-9 1-14.3 0.8h-25.7v57.4h59.3V740h64.4V400.2L502 400l-4.7 9.6z"
|
||||||
|
p-id="4305"></path>
|
||||||
|
<path
|
||||||
|
d="M880 160H738v-56c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v56H350v-56c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v56H144c-17.7 0-32 14.3-32 32v688c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V192c0-17.7-14.3-32-32-32z m-32 680c0 4.4-3.6 8-8 8H184c-4.4 0-8-3.6-8-8V232c0-4.4 3.6-8 8-8h102v48c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-48h324v48c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-48h110v616z"
|
||||||
|
p-id="4306"></path>
|
||||||
|
</svg>
|
||||||
|
</template>
|
7
src/frontend/admin/src/assets/icons/Report.vue
Normal file
7
src/frontend/admin/src/assets/icons/Report.vue
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<svg class="icon" height="128" p-id="5158" t="1708217788265" version="1.1" viewBox="0 0 1024 1024" width="128" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M228.254587 913.306922 66.10251 913.306922l0-240.783948 162.152077 0L228.254587 913.306922zM471.464795 913.306922 309.318858 913.306922 309.318858 351.483166l162.145937 0L471.464795 913.306922zM714.681142 913.306922 552.540322 913.306922 552.540322 592.267115 714.681142 592.267115 714.681142 913.306922zM957.896466 913.306922 795.744389 913.306922 795.744389 110.693078l162.152077 0L957.896466 913.306922z"
|
||||||
|
p-id="5159"></path>
|
||||||
|
</svg>
|
||||||
|
</template>
|
@ -54,3 +54,5 @@ export { default as Upload } from './Upload.vue'
|
|||||||
export { default as Vue } from './Vue.vue'
|
export { default as Vue } from './Vue.vue'
|
||||||
export { default as Warning } from './Warning.vue'
|
export { default as Warning } from './Warning.vue'
|
||||||
export { default as Wechat } from './Wechat.vue'
|
export { default as Wechat } from './Wechat.vue'
|
||||||
|
export { default as Report } from './Report.vue'
|
||||||
|
export { default as Daily } from './Daily.vue'
|
@ -3,7 +3,7 @@
|
|||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template v-for="(item, i) in Array.isArray(scope.row[prop]) ? scope.row[prop] : [scope.row[prop]]" :key="i">
|
<template v-for="(item, i) in Array.isArray(scope.row[prop]) ? scope.row[prop] : [scope.row[prop]]" :key="i">
|
||||||
<el-tag v-if="item" @click="$emit('click', item)">
|
<el-tag v-if="item" @click="$emit('click', item)">
|
||||||
{{ item ? item[field] : console.error(scope.row) }}
|
{{ item ? item[field] : '' }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
50
src/frontend/admin/src/components/naColUser/index.vue
Normal file
50
src/frontend/admin/src/components/naColUser/index.vue
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<el-table-column v-bind="$attrs">
|
||||||
|
<template #default="scope">
|
||||||
|
<div @click="click(tool.getNestedProperty(scope.row, $attrs.prop))" class="avatar" style="cursor: pointer">
|
||||||
|
<el-avatar :src="getAvatar(scope)" size="small"></el-avatar>
|
||||||
|
<el-text tag="ins">{{ tool.getNestedProperty(scope.row, $attrs.nestProp) }}</el-text>
|
||||||
|
</div>
|
||||||
|
<save-dialog v-if="dialog.save" @closed="dialog.save = false" ref="saveDialog"></save-dialog>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.avatar {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
import saveDialog from '@/views/sys/user/save.vue'
|
||||||
|
import tool from '@/utils/tool'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
emits: ['click'],
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialog: { save: false },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
created() {},
|
||||||
|
components: { saveDialog },
|
||||||
|
computed: {
|
||||||
|
tool() {
|
||||||
|
return tool
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async click(id) {
|
||||||
|
this.dialog.save = true
|
||||||
|
await this.$nextTick()
|
||||||
|
await this.$refs.saveDialog.open('view', { id: id })
|
||||||
|
},
|
||||||
|
//获取头像
|
||||||
|
getAvatar(scope) {
|
||||||
|
return scope.row.avatar ? scope.row.avatar : this.$CONFIG.DEFAULT_AVATAR
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
File diff suppressed because one or more lines are too long
@ -75,7 +75,7 @@ Object.assign(DEFAULT_CONFIG, MY_CONFIG)
|
|||||||
|
|
||||||
// 如果生产模式,就合并动态的APP_CONFIG
|
// 如果生产模式,就合并动态的APP_CONFIG
|
||||||
// public/config.js
|
// 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)
|
Object.assign(DEFAULT_CONFIG, APP_CONFIG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,59 +1,60 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-container v-loading="loading">
|
<el-container v-loading="loading">
|
||||||
<el-main>
|
<el-main>
|
||||||
<el-empty v-if="tasks.length === 0" :image-size="120">
|
<el-empty v-if="jobs.length === 0" :image-size="120">
|
||||||
<template #description>
|
<template #description>
|
||||||
<h2>没有正在执行的任务</h2>
|
<h2>没有正在执行的任务</h2>
|
||||||
</template>
|
</template>
|
||||||
<p style="font-size: 14px; color: #999; line-height: 1.5; margin: 0 40px">
|
<p style="color: #999; line-height: 1.5; margin: 0 3rem">
|
||||||
在处理耗时过久的任务时为了不阻碍正在处理的工作,可在任务中心进行异步执行。
|
在处理耗时过久的任务时为了不阻碍正在处理的工作,可在任务中心进行异步执行。
|
||||||
</p>
|
</p>
|
||||||
</el-empty>
|
</el-empty>
|
||||||
<el-card v-for="task in tasks" :key="task.id" class="user-bar-tasks-item" shadow="hover">
|
<el-card v-for="job in jobs" :key="job.id" class="user-bar-jobs-item" shadow="hover">
|
||||||
<div class="user-bar-tasks-item-body">
|
<div class="user-bar-jobs-item-body">
|
||||||
<div class="taskIcon">
|
<div class="jobIcon">
|
||||||
<el-icon v-if="task.type === 'export'" :size="20">
|
{{ job.lastStatusCode }}
|
||||||
<el-icon-paperclip />
|
|
||||||
</el-icon>
|
|
||||||
<el-icon v-if="task.type === 'report'" :size="20">
|
|
||||||
<el-icon-dataAnalysis />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="taskMain">
|
<div class="jobMain">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<h2>{{ task.taskName }}</h2>
|
<h2>{{ job.jobName }}</h2>
|
||||||
<p><span v-time.tip="task.createDate"></span> 创建</p>
|
<p>上次执行:<span v-time.tip="job.lastExecTime"></span></p>
|
||||||
|
<p>
|
||||||
|
下次执行:<span>{{ job.nextExecTime }}</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom">
|
<div class="bottom">
|
||||||
<div class="state">
|
<div class="status">
|
||||||
<el-tag v-if="task.state === '0'" type="info">执行中</el-tag>
|
<el-tag v-if="job.status === 'running'" type="info">执行中</el-tag>
|
||||||
<el-tag v-if="task.state === '1'">完成</el-tag>
|
<el-tag v-if="job.status === 'idle'">空闲</el-tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="handler">
|
<div class="handler">
|
||||||
<el-button
|
<el-button v-if="job.status === 'idle'" @click="view(job)" circle icon="el-icon-view" type="primary"></el-button>
|
||||||
v-if="task.state === '1'"
|
|
||||||
@click="download(task)"
|
|
||||||
circle
|
|
||||||
icon="el-icon-download"
|
|
||||||
type="primary"></el-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-main>
|
</el-main>
|
||||||
<el-footer style="padding: 10px; text-align: right">
|
<el-footer style="text-align: right">
|
||||||
<el-button @click="refresh" circle icon="el-icon-refresh"></el-button>
|
<el-button @click="refresh" circle icon="el-icon-refresh"></el-button>
|
||||||
</el-footer>
|
</el-footer>
|
||||||
</el-container>
|
</el-container>
|
||||||
|
<save-dialog v-if="dialog.save" @closed="dialog.save = false" ref="saveDialog"></save-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import saveDialog from '@/views/sys/job/save.vue'
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
saveDialog,
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
dialog: {
|
||||||
|
save: false,
|
||||||
|
},
|
||||||
loading: false,
|
loading: false,
|
||||||
tasks: [],
|
jobs: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -62,69 +63,64 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
async getData() {
|
async getData() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
var res = await this.$API.system.tasks.list.get()
|
const res = await this.$API.sys_job.query.post({ prop: 'lastExecTime', order: 'descending' })
|
||||||
this.tasks = res.data
|
this.jobs = res.data
|
||||||
this.loading = false
|
this.loading = false
|
||||||
},
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.getData()
|
this.getData()
|
||||||
},
|
},
|
||||||
download(row) {
|
async view(job) {
|
||||||
let a = document.createElement('a')
|
this.dialog.save = true
|
||||||
a.style = 'display: none'
|
await this.$nextTick()
|
||||||
a.target = '_blank'
|
await this.$refs.saveDialog.open('view', { id: job.id })
|
||||||
a.href = row.result
|
|
||||||
document.body.appendChild(a)
|
|
||||||
a.click()
|
|
||||||
document.body.removeChild(a)
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.user-bar-tasks-item {
|
.user-bar-jobs-item {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-bar-tasks-item:hover {
|
.user-bar-jobs-item:hover {
|
||||||
border-color: var(--el-color-primary);
|
border-color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-bar-tasks-item-body {
|
.user-bar-jobs-item-body {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-bar-tasks-item-body .taskIcon {
|
.user-bar-jobs-item-body .jobIcon {
|
||||||
width: 45px;
|
width: 3rem;
|
||||||
height: 45px;
|
height: 3rem;
|
||||||
background: var(--el-color-primary-light-9);
|
background: var(--el-color-primary-light-9);
|
||||||
margin-right: 20px;
|
margin-right: 2rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: var(--el-color-primary);
|
color: var(--el-color-primary);
|
||||||
border-radius: 20px;
|
border-radius: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-bar-tasks-item-body .taskMain {
|
.user-bar-jobs-item-body .jobMain {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-bar-tasks-item-body .title h2 {
|
.user-bar-jobs-item-body .title h2 {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-bar-tasks-item-body .title p {
|
.user-bar-jobs-item-body .title p {
|
||||||
font-size: 12px;
|
font-size: 1rem;
|
||||||
color: #999;
|
color: #999;
|
||||||
margin-top: 5px;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-bar-tasks-item-body .bottom {
|
.user-bar-jobs-item-body .bottom {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-top: 20px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -1,5 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="user-bar">
|
<div class="user-bar">
|
||||||
|
<div @click="configDark" class="tasks panel-item">
|
||||||
|
<el-icon>
|
||||||
|
<component :is="config.dark ? 'el-icon-sunny' : 'el-icon-moon'" />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
<div @click="search" class="panel-item hidden-sm-and-down">
|
<div @click="search" class="panel-item hidden-sm-and-down">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<el-icon-search />
|
<el-icon-search />
|
||||||
@ -12,7 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div @click="tasks" class="tasks panel-item">
|
<div @click="tasks" class="tasks panel-item">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<el-icon-sort />
|
<sc-icon-ScheduledJob />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
<div @click="showMsg" class="msg panel-item">
|
<div @click="showMsg" class="msg panel-item">
|
||||||
@ -69,8 +74,22 @@ export default {
|
|||||||
tasks,
|
tasks,
|
||||||
message,
|
message,
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
'config.dark'(val) {
|
||||||
|
if (val) {
|
||||||
|
document.documentElement.classList.add('dark')
|
||||||
|
this.$TOOL.data.set('APP_DARK', val)
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark')
|
||||||
|
this.$TOOL.data.remove('APP_DARK')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
config: {
|
||||||
|
dark: this.$TOOL.data.get('APP_DARK') || false,
|
||||||
|
},
|
||||||
user: {},
|
user: {},
|
||||||
userName: '',
|
userName: '',
|
||||||
userNameF: '',
|
userNameF: '',
|
||||||
@ -86,6 +105,9 @@ export default {
|
|||||||
this.unreadCnt = res.data
|
this.unreadCnt = res.data
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
configDark() {
|
||||||
|
this.config.dark = !this.config.dark
|
||||||
|
},
|
||||||
gotoMsgCenter() {
|
gotoMsgCenter() {
|
||||||
this.$router.push({ path: '/profile/message' })
|
this.$router.push({ path: '/profile/message' })
|
||||||
this.msg = false
|
this.msg = false
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
return { value: x[0], label: x[1][1] }
|
return { value: x[0], label: x[1][1] }
|
||||||
}),
|
}),
|
||||||
placeholder: $t('作业状态'),
|
placeholder: $t('作业状态'),
|
||||||
style: 'width:15rem',
|
style: 'width:10rem',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
@ -26,7 +26,7 @@
|
|||||||
return { value: x[0], label: x[1][1] }
|
return { value: x[0], label: x[1][1] }
|
||||||
}),
|
}),
|
||||||
placeholder: $t('请求方式'),
|
placeholder: $t('请求方式'),
|
||||||
style: 'width:15rem',
|
style: 'width:10rem',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
@ -36,7 +36,7 @@
|
|||||||
{ label: '禁用', value: false },
|
{ label: '禁用', value: false },
|
||||||
],
|
],
|
||||||
placeholder: '状态',
|
placeholder: '状态',
|
||||||
style: 'width:15rem',
|
style: 'width:10rem',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
:vue="this"
|
:vue="this"
|
||||||
@ -51,7 +51,7 @@
|
|||||||
<sc-table
|
<sc-table
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
:apiObj="$API.sys_job.pagedQuery"
|
:apiObj="$API.sys_job.pagedQuery"
|
||||||
:default-sort="{ prop: 'createdTime', order: 'descending' }"
|
:default-sort="{ prop: 'lastExecTime', order: 'descending' }"
|
||||||
:params="query"
|
:params="query"
|
||||||
@selection-change="
|
@selection-change="
|
||||||
(items) => {
|
(items) => {
|
||||||
@ -61,6 +61,7 @@
|
|||||||
ref="table"
|
ref="table"
|
||||||
remote-filter
|
remote-filter
|
||||||
remote-sort
|
remote-sort
|
||||||
|
row-key="id"
|
||||||
stripe>
|
stripe>
|
||||||
<el-table-column type="selection"></el-table-column>
|
<el-table-column type="selection"></el-table-column>
|
||||||
<el-table-column :label="$t('作业编号')" prop="id" width="150" />
|
<el-table-column :label="$t('作业编号')" prop="id" width="150" />
|
||||||
@ -80,16 +81,17 @@
|
|||||||
return { value: x[0], text: x[1][1] }
|
return { value: x[0], text: x[1][1] }
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
prop="httpMethod" />
|
prop="httpMethod"
|
||||||
<el-table-column :label="$t('上次执行时间')" prop="lastExecTime" sortable="custom" />
|
width="100" />
|
||||||
<el-table-column :label="$t('上次执行状态')" prop="lastStatusCode" sortable="custom" />
|
<el-table-column :label="$t('上次执行时间')" prop="lastExecTime" sortable="custom" width="170" />
|
||||||
<el-table-column :label="$t('下次执行时间')" prop="nextExecTime" sortable="custom" />
|
<el-table-column :label="$t('上次执行状态')" prop="lastStatusCode" sortable="custom" width="150" />
|
||||||
<el-table-column :label="$t('创建时间')" prop="createdTime" sortable="custom" />
|
<el-table-column :label="$t('下次执行时间')" prop="nextExecTime" sortable="custom" width="170" />
|
||||||
<el-table-column :label="$t('启用')" prop="enabled">
|
<el-table-column :label="$t('启用')" prop="enabled" sortable="custom" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch v-model="scope.row.enabled" @change="changeSwitch($event, scope.row)"></el-switch>
|
<el-switch v-model="scope.row.enabled" @change="changeSwitch($event, scope.row)"></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('创建时间')" prop="createdTime" sortable="custom" width="170" />
|
||||||
<na-col-operation
|
<na-col-operation
|
||||||
:buttons="
|
:buttons="
|
||||||
naColOperation.buttons.concat({
|
naColOperation.buttons.concat({
|
||||||
@ -128,6 +130,7 @@ export default {
|
|||||||
filters: [],
|
filters: [],
|
||||||
},
|
},
|
||||||
filter: {},
|
filter: {},
|
||||||
|
prop: 'lastExecTime',
|
||||||
},
|
},
|
||||||
dialog: {
|
dialog: {
|
||||||
save: false,
|
save: false,
|
||||||
|
200
src/frontend/admin/src/views/sys/job/record/index.vue
Normal file
200
src/frontend/admin/src/views/sys/job/record/index.vue
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
<template>
|
||||||
|
<el-container>
|
||||||
|
<el-header>
|
||||||
|
<div class="left-panel">
|
||||||
|
<na-search
|
||||||
|
:controls="[
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: ['root', 'keywords'],
|
||||||
|
placeholder: $t('作业编号 / 执行编号'),
|
||||||
|
style: 'width:20rem',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: ['dy', 'httpMethod'],
|
||||||
|
options: Object.entries(this.$GLOBAL.enums.httpMethods).map((x) => {
|
||||||
|
return { value: x[0], label: x[1][1] }
|
||||||
|
}),
|
||||||
|
placeholder: $t('请求方式'),
|
||||||
|
style: 'width:10rem',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
multiple: true,
|
||||||
|
type: 'select',
|
||||||
|
field: ['dy', 'httpStatusCode'],
|
||||||
|
options: [
|
||||||
|
{ label: '20x', value: '200,299' },
|
||||||
|
{ label: '30x', value: '300,399' },
|
||||||
|
{ label: '40x', value: '400,499' },
|
||||||
|
{ label: '50x', value: '500,599' },
|
||||||
|
{ label: '90x', value: '900,999' },
|
||||||
|
],
|
||||||
|
placeholder: '状态码',
|
||||||
|
style: 'width:20rem',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
:vue="this"
|
||||||
|
@search="onSearch"
|
||||||
|
ref="search" />
|
||||||
|
</div>
|
||||||
|
<div class="right-panel"></div>
|
||||||
|
</el-header>
|
||||||
|
<el-main class="nopadding">
|
||||||
|
<sc-table
|
||||||
|
v-loading="loading"
|
||||||
|
:apiObj="$API.sys_job.recordPagedQuery"
|
||||||
|
:default-sort="{ prop: 'createdTime', order: 'descending' }"
|
||||||
|
:params="query"
|
||||||
|
@selection-change="
|
||||||
|
(items) => {
|
||||||
|
selection = items
|
||||||
|
}
|
||||||
|
"
|
||||||
|
ref="table"
|
||||||
|
remote-filter
|
||||||
|
remote-sort
|
||||||
|
row-key="id"
|
||||||
|
stripe>
|
||||||
|
<el-table-column :label="$t('唯一编码')" prop="id" sortable="custom" width="150" />
|
||||||
|
<el-table-column :label="$t('执行耗时(毫秒)')" align="right" prop="duration" sortable="custom" width="150" />
|
||||||
|
<el-table-column :label="$t('请求方法')" prop="httpMethod" sortable="custom" width="100" />
|
||||||
|
<el-table-column :label="$t('HTTP 状态码')" align="right" prop="httpStatusCode" sortable="custom" width="150" />
|
||||||
|
<el-table-column :label="$t('请求的网络地址')" prop="requestUrl" sortable="custom" />
|
||||||
|
<el-table-column :label="$t('创建时间')" prop="createdTime" sortable="custom" width="170" />
|
||||||
|
<na-col-operation :buttons="[naColOperation.buttons[0]]" :vue="this" width="100" />
|
||||||
|
</sc-table>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
|
||||||
|
<save-dialog
|
||||||
|
v-if="dialog.save"
|
||||||
|
@closed="dialog.save = false"
|
||||||
|
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||||
|
ref="saveDialog"></save-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import saveDialog from './save'
|
||||||
|
import table from '@/config/table'
|
||||||
|
import naColOperation from '@/config/naColOperation'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['keywords'],
|
||||||
|
components: {
|
||||||
|
saveDialog,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
query: {
|
||||||
|
dynamicFilter: {
|
||||||
|
filters: [],
|
||||||
|
},
|
||||||
|
filter: {},
|
||||||
|
},
|
||||||
|
dialog: {
|
||||||
|
save: false,
|
||||||
|
},
|
||||||
|
selection: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {},
|
||||||
|
computed: {
|
||||||
|
naColOperation() {
|
||||||
|
return naColOperation
|
||||||
|
},
|
||||||
|
table() {
|
||||||
|
return table
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.keywords) {
|
||||||
|
this.$refs.search.form.root.keywords = this.keywords
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (this.keywords) {
|
||||||
|
this.query.keywords = this.keywords
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//表格内开关事件
|
||||||
|
async changeSwitch(event, row) {
|
||||||
|
try {
|
||||||
|
await this.$API.sys_job.setEnabled.post(row)
|
||||||
|
this.$message.success(`操作成功`)
|
||||||
|
} catch {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
this.$refs.table.refresh()
|
||||||
|
},
|
||||||
|
//删除
|
||||||
|
async rowDel(row) {
|
||||||
|
try {
|
||||||
|
const res = await this.$API.sys_job.delete.post({ id: row.id })
|
||||||
|
this.$refs.table.refresh()
|
||||||
|
this.$message.success(`删除 ${res.data} 项`)
|
||||||
|
} catch {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//批量删除
|
||||||
|
async batchDel() {
|
||||||
|
let loading
|
||||||
|
try {
|
||||||
|
await this.$confirm(`确定删除选中的 ${this.selection.length} 项吗?`, '提示', {
|
||||||
|
type: 'warning',
|
||||||
|
})
|
||||||
|
loading = this.$loading()
|
||||||
|
const res = await this.$API.sys_job.bulkDelete.post({
|
||||||
|
items: this.selection,
|
||||||
|
})
|
||||||
|
this.$refs.table.refresh()
|
||||||
|
this.$message.success(`删除 ${res.data} 项`)
|
||||||
|
} catch {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
loading?.close()
|
||||||
|
},
|
||||||
|
|
||||||
|
//搜索
|
||||||
|
onSearch(form) {
|
||||||
|
if (Array.isArray(form.dy.createdTime)) {
|
||||||
|
this.query.dynamicFilter.filters.push({
|
||||||
|
field: 'createdTime',
|
||||||
|
operator: 'dateRange',
|
||||||
|
value: form.dy.createdTime,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof form.dy.httpMethod === 'string' && form.dy.httpMethod.trim() !== '') {
|
||||||
|
this.query.dynamicFilter.filters.push({
|
||||||
|
field: 'httpMethod',
|
||||||
|
operator: 'eq',
|
||||||
|
value: form.dy.httpMethod,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(form.dy.httpStatusCode) && form.dy.httpStatusCode.length !== 0) {
|
||||||
|
const filters = []
|
||||||
|
for (const code of form.dy.httpStatusCode) {
|
||||||
|
filters.push({
|
||||||
|
field: 'httpStatusCode',
|
||||||
|
operator: 'range',
|
||||||
|
value: code,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.query.dynamicFilter.filters.push({
|
||||||
|
logic: 'or',
|
||||||
|
filters: filters,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$refs.table.upData()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
87
src/frontend/admin/src/views/sys/job/record/save.vue
Normal file
87
src/frontend/admin/src/views/sys/job/record/save.vue
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<template>
|
||||||
|
<sc-dialog v-model="visible" :title="titleMap[mode]" :width="800" @closed="$emit('closed')" destroy-on-close full-screen>
|
||||||
|
<el-form
|
||||||
|
v-loading="loading"
|
||||||
|
:disabled="mode === 'view'"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
label-position="right"
|
||||||
|
label-width="150px"
|
||||||
|
ref="dialogForm">
|
||||||
|
<el-tabs tab-position="top">
|
||||||
|
<el-tab-pane :label="$t('基本信息')">
|
||||||
|
<el-form-item :label="$t('唯一编码')" prop="id"><el-input v-model="form.id" clearable /></el-form-item
|
||||||
|
><el-form-item :label="$t('执行耗时(毫秒)')" prop="duration"><el-input v-model="form.duration" clearable /></el-form-item
|
||||||
|
><el-form-item :label="$t('请求方法')" prop="httpMethod"><el-input v-model="form.httpMethod" clearable /></el-form-item
|
||||||
|
><el-form-item :label="$t('HTTP 状态码')" prop="httpStatusCode"><el-input v-model="form.httpStatusCode" clearable /></el-form-item
|
||||||
|
><el-form-item :label="$t('作业编号')" prop="jobId"><el-input v-model="form.jobId" clearable /></el-form-item
|
||||||
|
><el-form-item :label="$t('请求体')" prop="requestBody"
|
||||||
|
><el-input v-model="form.requestBody" clearable rows="5" type="textarea" /></el-form-item
|
||||||
|
><el-form-item :label="$t('请求头')" prop="requestHeader">
|
||||||
|
<el-input v-model="form.requestHeader" clearable rows="5" type="textarea" /></el-form-item
|
||||||
|
><el-form-item :label="$t('请求的网络地址')" prop="requestUrl"><el-input v-model="form.requestUrl" clearable /></el-form-item
|
||||||
|
><el-form-item :label="$t('响应体')" prop="responseBody"
|
||||||
|
><el-input v-model="form.responseBody" clearable rows="5" type="textarea" /></el-form-item
|
||||||
|
><el-form-item :label="$t('响应头')" prop="responseHeader">
|
||||||
|
<el-input v-model="form.responseHeader" clearable rows="5" type="textarea" /></el-form-item
|
||||||
|
><el-form-item :label="$t('执行时间编号')" prop="timeId"><el-input v-model="form.timeId" clearable /></el-form-item
|
||||||
|
><el-form-item :label="$t('创建时间')" prop="createdTime"><el-input v-model="form.createdTime" clearable /></el-form-item>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane v-if="mode === 'view'" :label="$t('原始数据')">
|
||||||
|
<json-viewer
|
||||||
|
:expand-depth="5"
|
||||||
|
:expanded="true"
|
||||||
|
:theme="this.$TOOL.data.get('APP_DARK') ? 'dark' : 'light'"
|
||||||
|
:value="form"
|
||||||
|
copyable
|
||||||
|
sort></json-viewer>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
</template>
|
||||||
|
</sc-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import scEditor from '@/components/scEditor/index.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
scEditor,
|
||||||
|
},
|
||||||
|
emits: ['success', 'closed'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
mode: 'add',
|
||||||
|
titleMap: {
|
||||||
|
view: this.$t('查看作业记录'),
|
||||||
|
add: this.$t('新增作业记录'),
|
||||||
|
edit: this.$t('编辑作业记录'),
|
||||||
|
},
|
||||||
|
visible: false,
|
||||||
|
loading: false,
|
||||||
|
//表单数据
|
||||||
|
form: {},
|
||||||
|
//验证规则
|
||||||
|
rules: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
methods: {
|
||||||
|
//显示
|
||||||
|
async open(mode = 'add', data) {
|
||||||
|
this.visible = true
|
||||||
|
this.loading = true
|
||||||
|
this.mode = mode
|
||||||
|
if (data) {
|
||||||
|
const res = await this.$API.sys_job.recordGet.post({ id: data.id })
|
||||||
|
Object.assign(this.form, res.data)
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<sc-dialog v-model="visible" :title="titleMap[mode]" :width="800" @closed="$emit('closed')" destroy-on-close full-screen>
|
<sc-dialog v-model="visible" :title="titleMap[mode]" :width="800" @closed="$emit('closed')" destroy-on-close full-screen>
|
||||||
|
<el-tabs v-model="tabIndex" tab-position="top">
|
||||||
|
<el-tab-pane :label="$t('基本信息')" :name="0">
|
||||||
<el-form
|
<el-form
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
:disabled="mode === 'view'"
|
:disabled="mode === 'view'"
|
||||||
@ -8,8 +10,6 @@
|
|||||||
label-position="right"
|
label-position="right"
|
||||||
label-width="150px"
|
label-width="150px"
|
||||||
ref="dialogForm">
|
ref="dialogForm">
|
||||||
<el-tabs tab-position="top">
|
|
||||||
<el-tab-pane :label="$t('基本信息')">
|
|
||||||
<el-form-item v-if="mode === 'view'" :label="$t('作业编号')" prop="id">
|
<el-form-item v-if="mode === 'view'" :label="$t('作业编号')" prop="id">
|
||||||
<el-input v-model="form.id" clearable />
|
<el-input v-model="form.id" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -48,8 +48,8 @@
|
|||||||
<el-form-item v-if="mode === 'view'" :label="$t('执行用户编号')" prop="userId">
|
<el-form-item v-if="mode === 'view'" :label="$t('执行用户编号')" prop="userId">
|
||||||
<el-input v-model="form.userId" clearable />
|
<el-input v-model="form.userId" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-else :label="$t('执行用户')" prop="userId">
|
<el-form-item v-else :label="$t('执行用户')" prop="user">
|
||||||
<na-user-select v-model="form.userId"></na-user-select>
|
<na-user-select v-model="form.user"></na-user-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="mode === 'view'" :label="$t('创建时间')" prop="createdTime">
|
<el-form-item v-if="mode === 'view'" :label="$t('创建时间')" prop="createdTime">
|
||||||
<el-input v-model="form.createdTime" clearable />
|
<el-input v-model="form.createdTime" clearable />
|
||||||
@ -72,8 +72,12 @@
|
|||||||
<el-form-item v-if="mode === 'view'" :label="$t('修改者用户名')" prop="modifiedUserName">
|
<el-form-item v-if="mode === 'view'" :label="$t('修改者用户名')" prop="modifiedUserName">
|
||||||
<el-input v-model="form.modifiedUserName" clearable />
|
<el-input v-model="form.modifiedUserName" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane v-if="mode === 'view'" :label="$t('原始数据')">
|
<el-tab-pane v-if="mode === 'view'" :label="$t('执行记录')" :name="1">
|
||||||
|
<record v-if="tabIndex === 1" :keywords="form.id" />
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane v-if="mode === 'view'" :label="$t('原始数据')" :name="2">
|
||||||
<json-viewer
|
<json-viewer
|
||||||
:expand-depth="5"
|
:expand-depth="5"
|
||||||
:expanded="true"
|
:expanded="true"
|
||||||
@ -83,7 +87,7 @@
|
|||||||
sort></json-viewer>
|
sort></json-viewer>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="visible = false">取 消</el-button>
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
<el-button v-if="mode !== 'view'" :loading="loading" @click="submit" type="primary">保 存</el-button>
|
<el-button v-if="mode !== 'view'" :loading="loading" @click="submit" type="primary">保 存</el-button>
|
||||||
@ -93,14 +97,17 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import scEditor from '@/components/scEditor/index.vue'
|
import scEditor from '@/components/scEditor/index.vue'
|
||||||
|
import Record from '@/views/sys/job/record/index.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
Record,
|
||||||
scEditor,
|
scEditor,
|
||||||
},
|
},
|
||||||
emits: ['success', 'closed'],
|
emits: ['success', 'closed'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
tabIndex: 0,
|
||||||
mode: 'add',
|
mode: 'add',
|
||||||
titleMap: {
|
titleMap: {
|
||||||
view: this.$t('查看作业'),
|
view: this.$t('查看作业'),
|
||||||
@ -110,7 +117,12 @@ export default {
|
|||||||
visible: false,
|
visible: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
//表单数据
|
//表单数据
|
||||||
form: {},
|
form: {
|
||||||
|
executionCron: '* * * * *',
|
||||||
|
httpMethod: 'Post',
|
||||||
|
requestHeader: `{ "Content-Type": "application/json" }`,
|
||||||
|
requestBody: '{}',
|
||||||
|
},
|
||||||
//验证规则
|
//验证规则
|
||||||
rules: {
|
rules: {
|
||||||
executionCron: [
|
executionCron: [
|
||||||
@ -132,6 +144,19 @@ export default {
|
|||||||
message: this.$t('作业名称不能为空'),
|
message: this.$t('作业名称不能为空'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
requestHeader: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (!value) return callback()
|
||||||
|
try {
|
||||||
|
JSON.parse(value)
|
||||||
|
} catch {
|
||||||
|
return callback(this.$t('请求头不正确'))
|
||||||
|
}
|
||||||
|
return callback()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
requestUrl: [
|
requestUrl: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@ -139,7 +164,7 @@ export default {
|
|||||||
message: this.$t('请求的网络地址不正确'),
|
message: this.$t('请求的网络地址不正确'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
userId: [
|
user: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
@ -178,7 +203,9 @@ export default {
|
|||||||
try {
|
try {
|
||||||
const method = this.mode === 'add' ? this.$API.sys_job.create : this.$API.sys_job.update
|
const method = this.mode === 'add' ? this.$API.sys_job.create : this.$API.sys_job.update
|
||||||
this.loading = true
|
this.loading = true
|
||||||
const res = await method.post(Object.assign({}, this.form, { userId: this.form.userId.id }))
|
const res = await method.post(
|
||||||
|
Object.assign({}, this.form, { userId: this.form.user.id, requestHeaders: JSON.parse(this.form.requestHeader) }),
|
||||||
|
)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.$emit('success', res.data, this.mode)
|
this.$emit('success', res.data, this.mode)
|
||||||
this.visible = false
|
this.visible = false
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
ref="table"
|
ref="table"
|
||||||
remoteFilter
|
remoteFilter
|
||||||
remoteSort
|
remoteSort
|
||||||
|
row-key="id"
|
||||||
stripe>
|
stripe>
|
||||||
<el-table-column :label="$t('日志编号')" prop="id" sortable="custom"></el-table-column>
|
<el-table-column :label="$t('日志编号')" prop="id" sortable="custom"></el-table-column>
|
||||||
<el-table-column :label="$t('日志时间')" prop="createdTime" sortable="custom"></el-table-column>
|
<el-table-column :label="$t('日志时间')" prop="createdTime" sortable="custom"></el-table-column>
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
ref="table"
|
ref="table"
|
||||||
remoteFilter
|
remoteFilter
|
||||||
remoteSort
|
remoteSort
|
||||||
|
row-key="id"
|
||||||
stripe>
|
stripe>
|
||||||
<el-table-column :label="$t('日志编号')" prop="id" sortable="custom" width="150"></el-table-column>
|
<el-table-column :label="$t('日志编号')" prop="id" sortable="custom" width="150"></el-table-column>
|
||||||
<el-table-column :label="$t('日志时间')" prop="createdTime" sortable="custom" width="170"></el-table-column>
|
<el-table-column :label="$t('日志时间')" prop="createdTime" sortable="custom" width="170"></el-table-column>
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
ref="table"
|
ref="table"
|
||||||
remote-filter
|
remote-filter
|
||||||
remote-sort
|
remote-sort
|
||||||
|
row-key="id"
|
||||||
stripe>
|
stripe>
|
||||||
<el-table-column type="selection"></el-table-column>
|
<el-table-column type="selection"></el-table-column>
|
||||||
<el-table-column :label="$t('消息编号')" prop="id" width="150" />
|
<el-table-column :label="$t('消息编号')" prop="id" width="150" />
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
ref="table"
|
ref="table"
|
||||||
remote-filter
|
remote-filter
|
||||||
remote-sort
|
remote-sort
|
||||||
|
row-key="id"
|
||||||
stripe>
|
stripe>
|
||||||
<el-table-column type="selection"></el-table-column>
|
<el-table-column type="selection"></el-table-column>
|
||||||
<el-table-column :label="$t('用户编号')" prop="id" sortable="custom" width="150"></el-table-column>
|
<el-table-column :label="$t('用户编号')" prop="id" sortable="custom" width="150"></el-table-column>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user