mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-04-24 07:02:51 +08:00
feat: ✨ 计划作业 (#87)
This commit is contained in:
parent
473b0c26f2
commit
8293ec0297
@ -65,6 +65,7 @@
|
||||
硕士
|
||||
离异
|
||||
私信
|
||||
空闲
|
||||
等于
|
||||
等待发送
|
||||
系统模块
|
||||
@ -79,6 +80,7 @@
|
||||
调试
|
||||
跟踪
|
||||
身份证
|
||||
运行
|
||||
重设密码
|
||||
链接
|
||||
错误
|
||||
|
@ -7,6 +7,7 @@ XML注释文件不存在
|
||||
事务已提交
|
||||
人机校验请求不能为空
|
||||
人机验证未通过
|
||||
作业名称不能为空
|
||||
允许的文件大小
|
||||
允许的文件格式
|
||||
区号电话号码分机号
|
||||
@ -23,6 +24,7 @@ XML注释文件不存在
|
||||
开始事务
|
||||
手机号码不正确
|
||||
手机号码不能为空
|
||||
接口编码不存在
|
||||
支付宝账号
|
||||
数据库同步开始
|
||||
数据库服务器时钟偏移
|
||||
@ -39,7 +41,10 @@ XML注释文件不存在
|
||||
旧手机号码不正确
|
||||
旧手机号码验证码不正确
|
||||
时间戳缺失或误差过大
|
||||
时间表达式
|
||||
时间计划不能为空
|
||||
未指定部门
|
||||
未获取到待执行任务
|
||||
模块名称不能为空
|
||||
模块说明不能为空
|
||||
消息主题不能为空
|
||||
@ -52,6 +57,7 @@ XML注释文件不存在
|
||||
用户名长度4位以上
|
||||
用户头像不能为空
|
||||
用户档案不能为空
|
||||
用户编号不存在
|
||||
目标设备不能为空
|
||||
短信验证请求不能为空
|
||||
站内信不存在
|
||||
@ -68,7 +74,9 @@ XML注释文件不存在
|
||||
该角色下存在用户
|
||||
该部门下存在子部门
|
||||
该部门下存在用户
|
||||
请求地址不能为空
|
||||
请求对象不能为空
|
||||
请求方法不正确
|
||||
请联系管理员激活账号
|
||||
读取用户令牌出错
|
||||
账号不能为空
|
||||
|
13
assets/seed-data/Sys_Job.json
Normal file
13
assets/seed-data/Sys_Job.json
Normal file
@ -0,0 +1,13 @@
|
||||
[
|
||||
{
|
||||
"Enabled": true,
|
||||
"ExecutionCron": "* * * * *",
|
||||
"HttpMethod": 3,
|
||||
"JobName": "HTTP 请求测试",
|
||||
"NextExecTime": "2020/9/13 12:26:40",
|
||||
"NextTimeId": 1600000000,
|
||||
"RequestUrl": "https://httpbin.org/ip",
|
||||
"Status": 1,
|
||||
"UserId": 370942943322181,
|
||||
}
|
||||
]
|
@ -85,6 +85,17 @@
|
||||
"Title": "系统设置",
|
||||
"Type": 1
|
||||
},
|
||||
{
|
||||
"Component": "sys/job",
|
||||
"Icon": "sc-icon-ScheduledJob",
|
||||
"Id": 510067557638158,
|
||||
"Name": "sys-job",
|
||||
"ParentId": 485278637670422,
|
||||
"Path": "/sys/job",
|
||||
"Sort": 99,
|
||||
"Title": "计划作业",
|
||||
"Type": 1
|
||||
},
|
||||
{
|
||||
"Component": "sys/dic",
|
||||
"Icon": "sc-icon-dic",
|
||||
@ -92,7 +103,7 @@
|
||||
"Name": "sys-dic",
|
||||
"ParentId": 485278637670422,
|
||||
"Path": "/sys/dic",
|
||||
"Sort": 99,
|
||||
"Sort": 98,
|
||||
"Title": "字典管理",
|
||||
"Type": 1
|
||||
},
|
||||
@ -103,7 +114,7 @@
|
||||
"Name": "sys-msg",
|
||||
"ParentId": 485278637670422,
|
||||
"Path": "/sys/msg",
|
||||
"Sort": 98,
|
||||
"Sort": 97,
|
||||
"Title": "消息管理",
|
||||
"Type": 1,
|
||||
},
|
||||
@ -114,7 +125,7 @@
|
||||
"Name": "sys-api",
|
||||
"ParentId": 485278637670422,
|
||||
"Path": "/sys/api",
|
||||
"Sort": 97,
|
||||
"Sort": 96,
|
||||
"Title": "接口管理",
|
||||
"Type": 1
|
||||
},
|
||||
@ -125,7 +136,7 @@
|
||||
"Name": "sys-cache",
|
||||
"ParentId": 485278637670422,
|
||||
"Path": "/sys/cache",
|
||||
"Sort": 96,
|
||||
"Sort": 95,
|
||||
"Title": "缓存管理",
|
||||
"Type": 1
|
||||
},
|
||||
@ -136,7 +147,7 @@
|
||||
"Name": "sys-about",
|
||||
"ParentId": 485278637670422,
|
||||
"Path": "/sys/about",
|
||||
"Sort": 95,
|
||||
"Sort": 94,
|
||||
"Title": "版本信息",
|
||||
"Type": 1,
|
||||
},
|
||||
|
@ -19,11 +19,11 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Roslynator.Analyzers" Version="4.9.0">
|
||||
<PackageReference Include="Roslynator.Analyzers" Version="4.10.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.17.0.82934">
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.19.0.84025">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
@ -15,7 +15,7 @@
|
||||
]
|
||||
},
|
||||
"jetbrains.resharper.globaltools": {
|
||||
"version": "2023.3.2",
|
||||
"version": "2023.3.3",
|
||||
"commands": [
|
||||
"jb"
|
||||
]
|
||||
|
15
scripts/find.unused.ln.csx
Normal file
15
scripts/find.unused.ln.csx
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
Console.WriteLine(string.Join(Environment.NewLine
|
||||
, Regex
|
||||
.Matches(File.ReadAllText(@"../assets/res/Ln.resx")
|
||||
, "data name=\"(.*?)\"")
|
||||
.Select(x => x.Groups[1].Value)
|
||||
.Where(x => !Directory
|
||||
.GetFiles(@"../src/backend/", "*.cs"
|
||||
, new EnumerationOptions {
|
||||
RecurseSubdirectories = true
|
||||
})
|
||||
.Select(File.ReadAllText)
|
||||
.Any(y => y.Contains(x)))));
|
||||
Console.ReadKey();
|
@ -2,6 +2,7 @@ using NetAdmin.BizServer.Host;
|
||||
using NetAdmin.BizServer.Host.Extensions;
|
||||
using NetAdmin.Host.Extensions;
|
||||
using NetAdmin.Host.Middlewares;
|
||||
using NetAdmin.SysComponent.Host.Extensions;
|
||||
using Spectre.Console.Cli;
|
||||
using ValidationResult = Spectre.Console.ValidationResult;
|
||||
#if !DEBUG
|
||||
@ -62,6 +63,7 @@ namespace NetAdmin.BizServer.Host
|
||||
.AddCorsAccessor() // 添加支持跨域访问
|
||||
.AddContextUser() // 添加上下文用户
|
||||
.AddRedisCache() // 添加 Redis 缓存
|
||||
.AddSchedules() // 添加计划任务
|
||||
|
||||
// IMvcBuilder
|
||||
.AddControllers() // 添加控制器
|
||||
|
@ -4,6 +4,6 @@
|
||||
<ProjectReference Include="../NetAdmin.BizServer.Host/NetAdmin.BizServer.Host.csproj"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0-release-23619-01"/>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0-preview-24080-01"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,24 @@
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Api;
|
||||
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 接口编码验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class ApiIdAttribute : ValidationAttribute
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
|
||||
{
|
||||
var service = App.GetService(App.EffectiveTypes.Single(
|
||||
x => x.FullName == "NetAdmin.SysComponent.Cache.Sys.Dependency.IApiCache"));
|
||||
|
||||
var req = new QueryReq<QueryApiReq> { Filter = new QueryApiReq { Id = value as string } };
|
||||
|
||||
var method = service.GetType().GetMethod("ExistAsync");
|
||||
var exist = ((Task<bool>)method!.Invoke(service, [req]))!.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
return !exist ? new ValidationResult(Ln.接口编码不存在) : ValidationResult.Success;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 时间表达式验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class CronAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CronAttribute" /> class.
|
||||
/// </summary>
|
||||
public CronAttribute() //
|
||||
: base(Chars.RGX_CRON)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.时间表达式);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 用户编号验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class UserIdAttribute : ValidationAttribute
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
|
||||
{
|
||||
var service = App.GetService(App.EffectiveTypes.Single(
|
||||
x => x.FullName == "NetAdmin.SysComponent.Cache.Sys.Dependency.IUserCache"));
|
||||
|
||||
var req = new QueryReq<QueryUserReq> { Filter = new QueryUserReq { Id = (long)value! } };
|
||||
|
||||
var method = service.GetType().GetMethod("ExistAsync");
|
||||
var exist = ((Task<bool>)method!.Invoke(service, [req]))!.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
return !exist ? new ValidationResult(Ln.用户编号不存在) : ValidationResult.Success;
|
||||
}
|
||||
}
|
@ -5,6 +5,17 @@ namespace NetAdmin.Domain;
|
||||
/// </summary>
|
||||
public abstract record DataAbstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// 如果数据校验失败,抛出异常
|
||||
/// </summary>
|
||||
/// <exception cref="NetAdminInvalidInputException">NetAdminInvalidInputException</exception>
|
||||
public void ThrowIfInvalid()
|
||||
{
|
||||
if (!this.TryValidate().IsValid) {
|
||||
throw new NetAdminInvalidInputException(Ln.无效输入);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
|
107
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Job.cs
Normal file
107
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Job.cs
Normal file
@ -0,0 +1,107 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Job))]
|
||||
public record Sys_Job : VersionEntity, IFieldEnabled, IFieldSummary
|
||||
{
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool Enabled { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行时间计划
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string ExecutionCron { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求方法
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual HttpMethods HttpMethod { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 作业名称
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
public virtual string JobName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 上次执行时间
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual DateTime? LastExecTime { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 上次执行状态
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual HttpStatusCode? LastStatusCode { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 下次执行时间
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual DateTime? NextExecTime { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 下次执行时间编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long? NextTimeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求体
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
public virtual string RequestBody { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求头
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
public virtual string RequestHeader { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求的网络地址
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
public virtual string RequestUrl { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 作业状态
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual JobStatues Status { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
public virtual string Summary { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行用户编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long UserId { get; init; }
|
||||
}
|
82
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_JobRecord.cs
Normal file
82
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_JobRecord.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业执行记录表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_JobRecord))]
|
||||
[Index($"idx_{{tablename}}_{nameof(JobId)}_{nameof(TimeId)}", $"{nameof(JobId)},{nameof(TimeId)}", true)]
|
||||
public record Sys_JobRecord : LiteImmutableEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行耗时(毫秒)
|
||||
/// </summary>
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public virtual long Duration { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求方法
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual HttpMethods HttpMethod { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 状态码
|
||||
/// </summary>
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public virtual HttpStatusCode HttpStatusCode { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 作业编号
|
||||
/// </summary>
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public long JobId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求体
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string RequestBody { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求头
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string RequestHeader { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求的网络地址
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
[JsonIgnore]
|
||||
public virtual string RequestUrl { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 响应体
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string ResponseBody { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 响应头
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string ResponseHeader { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行时间编号
|
||||
/// </summary>
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public long TimeId { get; set; }
|
||||
}
|
65
src/backend/NetAdmin.Domain/Dto/Sys/Job/CreateJobReq.cs
Normal file
65
src/backend/NetAdmin.Domain/Dto/Sys/Job/CreateJobReq.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using NetAdmin.Domain.Attributes.DataValidation;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Job;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:创建计划作业
|
||||
/// </summary>
|
||||
public record CreateJobReq : Sys_Job
|
||||
{
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override bool Enabled { get; init; } = true;
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.ExecutionCron" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[Cron]
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.时间计划不能为空))]
|
||||
public override string ExecutionCron { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.HttpMethod" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
[EnumDataType(typeof(HttpMethods), ErrorMessageResourceType = typeof(Ln)
|
||||
, ErrorMessageResourceName = nameof(Ln.请求方法不正确))]
|
||||
public override HttpMethods HttpMethod { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.JobName" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.作业名称不能为空))]
|
||||
public override string JobName { get; init; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override long? NextTimeId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.RequestBody" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string RequestBody { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求头
|
||||
/// </summary>
|
||||
public Dictionary<string, string> RequestHeaders { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.RequestUrl" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.请求地址不能为空))]
|
||||
[Url(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.网络地址不正确))]
|
||||
public override string RequestUrl { get; init; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override JobStatues Status { get; init; } = JobStatues.Idle;
|
||||
|
||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Summary { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.UserId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
[Range(1, long.MaxValue, ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.用户编号不存在))]
|
||||
[UserId]
|
||||
public override long UserId { get; init; }
|
||||
}
|
14
src/backend/NetAdmin.Domain/Dto/Sys/Job/QueryJobReq.cs
Normal file
14
src/backend/NetAdmin.Domain/Dto/Sys/Job/QueryJobReq.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Job;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:查询计划作业
|
||||
/// </summary>
|
||||
public sealed record QueryJobReq : Sys_Job
|
||||
{
|
||||
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
}
|
80
src/backend/NetAdmin.Domain/Dto/Sys/Job/QueryJobRsp.cs
Normal file
80
src/backend/NetAdmin.Domain/Dto/Sys/Job/QueryJobRsp.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
using HttpMethods = NetAdmin.Domain.Enums.HttpMethods;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Job;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:查询计划作业
|
||||
/// </summary>
|
||||
public sealed record QueryJobRsp : Sys_Job
|
||||
{
|
||||
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override DateTime CreatedTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override bool Enabled { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.ExecutionCron" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string ExecutionCron { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.HttpMethod" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override HttpMethods HttpMethod { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.JobName" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string JobName { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.LastExecTime" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override DateTime? LastExecTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.LastStatusCode" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override HttpStatusCode? LastStatusCode { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.NextExecTime" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override DateTime? NextExecTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.NextTimeId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override long? NextTimeId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.RequestBody" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string RequestBody { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.RequestHeader" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string RequestHeader { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.RequestUrl" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string RequestUrl { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.Status" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override JobStatues Status { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Summary { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Job.UserId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long UserId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
}
|
13
src/backend/NetAdmin.Domain/Dto/Sys/Job/UpdateJobReq.cs
Normal file
13
src/backend/NetAdmin.Domain/Dto/Sys/Job/UpdateJobReq.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Job;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:更新计划作业
|
||||
/// </summary>
|
||||
public sealed record UpdateJobReq : CreateJobReq
|
||||
{
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:创建计划作业执行记录
|
||||
/// </summary>
|
||||
public record CreateJobRecordReq : Sys_JobRecord;
|
@ -0,0 +1,14 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:查询计划作业执行记录
|
||||
/// </summary>
|
||||
public sealed record QueryJobRecordReq : Sys_JobRecord
|
||||
{
|
||||
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:查询计划作业执行记录
|
||||
/// </summary>
|
||||
public sealed record QueryJobRecordRsp : Sys_JobRecord
|
||||
{
|
||||
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:更新计划作业执行记录
|
||||
/// </summary>
|
||||
public sealed record UpdateJobRecordReq : CreateJobRecordReq { }
|
69
src/backend/NetAdmin.Domain/Enums/HttpMethods.cs
Normal file
69
src/backend/NetAdmin.Domain/Enums/HttpMethods.cs
Normal file
@ -0,0 +1,69 @@
|
||||
namespace NetAdmin.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 请求方法
|
||||
/// </summary>
|
||||
[Export]
|
||||
public enum HttpMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// Connect
|
||||
/// </summary>
|
||||
Connect = 1
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// Delete
|
||||
/// </summary>
|
||||
Delete = 2
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// Get
|
||||
/// </summary>
|
||||
Get = 3
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// Head
|
||||
/// </summary>
|
||||
Head = 4
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// Options
|
||||
/// </summary>
|
||||
Options = 5
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// Patch
|
||||
/// </summary>
|
||||
Patch = 6
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// Post
|
||||
/// </summary>
|
||||
Post = 7
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// Put
|
||||
/// </summary>
|
||||
Put = 8
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// Trace
|
||||
/// </summary>
|
||||
Trace = 9
|
||||
}
|
22
src/backend/NetAdmin.Domain/Enums/Sys/JobStatues.cs
Normal file
22
src/backend/NetAdmin.Domain/Enums/Sys/JobStatues.cs
Normal file
@ -0,0 +1,22 @@
|
||||
namespace NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业状态
|
||||
/// </summary>
|
||||
[Export]
|
||||
public enum JobStatues
|
||||
{
|
||||
/// <summary>
|
||||
/// 空闲
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.空闲))]
|
||||
Idle = 1
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// 运行
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.运行))]
|
||||
Running = 2
|
||||
}
|
@ -11,7 +11,9 @@ namespace NetAdmin.Infrastructure.Constant;
|
||||
public static class Chars
|
||||
{
|
||||
public const string FLG_ACCESS_TOKEN = "ACCESS-TOKEN";
|
||||
public const string FLG_ACCESS_TOKEN_HEADER_KEY = "Authorization";
|
||||
public const string FLG_APPLICATION_JSON = "application/json";
|
||||
public const string FLG_AUTH_SCHEMA = "Bearer";
|
||||
public const string FLG_CONSUL_REG_HOSTNAME = "CONSUL_REG_HOSTNAME";
|
||||
public const string FLG_CONSUL_REG_PORT = "CONSUL_REG_PORT";
|
||||
public const string FLG_CONTEXT_MEMBER_INFO = nameof(FLG_CONTEXT_MEMBER_INFO);
|
||||
@ -67,12 +69,16 @@ public static class Chars
|
||||
= """!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~""";
|
||||
|
||||
public const string FLG_X_ACCESS_TOKEN = "X-ACCESS-TOKEN";
|
||||
public const string FLG_X_ACCESS_TOKEN_HEADER_KEY = "X-Authorization";
|
||||
|
||||
public const string RGX_CERTIFICATE = "^[a-zA-Z0-9-_]+$";
|
||||
|
||||
public const string RGX_CHINESE_NAME
|
||||
= """^(?:赵|钱|孙|李|周|吴|郑|王|冯|陈|褚|卫|蒋|沈|韩|杨|朱|秦|尤|许|何|吕|施|张|孔|曹|严|华|金|魏|陶|姜|戚|谢|邹|喻|柏|水|窦|章|云|苏|潘|葛|奚|范|彭|郎|鲁|韦|昌|马|苗|凤|花|方|俞|任|袁|柳|酆|鲍|史|唐|费|廉|岑|薛|雷|贺|倪|汤|滕|殷|罗|毕|郝|邬|安|常|乐|于|时|傅|皮|卞|齐|康|伍|余|元|卜|顾|孟|平|黄|和|穆|萧|尹|姚|邵|湛|汪|祁|毛|禹|狄|米|贝|明|臧|计|伏|成|戴|谈|宋|茅|庞|熊|纪|舒|屈|项|祝|董|梁|杜|阮|蓝|闵|席|季|麻|强|贾|路|娄|危|江|童|颜|郭|梅|盛|林|刁|钟|徐|邱|骆|高|夏|蔡|田|樊|胡|凌|霍|虞|万|支|柯|昝|管|卢|莫|经|房|裘|缪|干|解|应|宗|丁|宣|贲|邓|郁|单|杭|洪|包|诸|左|石|崔|吉|钮|龚|程|嵇|邢|滑|裴|陆|荣|翁|荀|羊|於|惠|甄|曲|家|封|芮|羿|储|靳|汲|邴|糜|松|井|段|富|巫|乌|焦|巴|弓|牧|隗|山|谷|车|侯|宓|蓬|全|郗|班|仰|秋|仲|伊|宫|宁|仇|栾|暴|甘|钭|厉|戎|祖|武|符|刘|景|詹|束|龙|叶|幸|司|韶|郜|黎|蓟|薄|印|宿|白|怀|蒲|邰|从|鄂|索|咸|籍|赖|卓|蔺|屠|蒙|池|乔|阴|胥|能|苍|双|闻|莘|党|翟|谭|贡|劳|逄|姬|申|扶|堵|冉|宰|郦|雍|郤|璩|桑|桂|濮|牛|寿|通|边|扈|燕|冀|郏|浦|尚|农|温|别|庄|晏|柴|瞿|阎|充|慕|连|茹|习|宦|艾|鱼|容|向|古|易|慎|戈|廖|庾|终|暨|居|衡|步|都|耿|满|弘|匡|国|文|寇|广|禄|阙|东|欧|殳|沃|利|蔚|越|夔|隆|师|巩|厍|聂|晁|勾|敖|融|冷|訾|辛|阚|那|简|饶|空|曾|毋|沙|乜|养|鞠|须|丰|巢|关|蒯|相|查|後|荆|红|游|竺|权|逯|盖|益|桓|公|万俟|司马|上官|欧阳|夏侯|诸葛|闻人|东方|赫连|皇甫|尉迟|公羊|澹台|公冶|宗政|濮阳|淳于|单于|太叔|申屠|公孙|仲孙|轩辕|令狐|钟离|宇文|长孙|慕容|鲜于|闾丘|司徒|司空|亓官|司寇|仉|督|子车|颛孙|端木|巫马|公西|漆雕|乐正|壤驷|公良|拓跋|夹谷|宰父|谷梁|晋|楚|闫|法|汝|鄢|涂|钦|段干|百里|东郭|南门|呼延|归|海|羊舌|微生|岳|帅|缑|亢|况|后|有|琴|梁丘|左丘|东门|西门|商|牟|佘|佴|伯|赏|南宫|墨|哈|谯|笪|年|爱|阳|佟|第五|言|福)[\u4e00-\u9fa5]{1,3}$""";
|
||||
|
||||
public const string RGX_CRON
|
||||
= """^(?:[0-5]?[0-9]|[0-9]|[1-5]?[0-9](?:,[0-5]?[0-9])?|\*|\*/[0-5]?[0-9])\s+(?:[01]?[0-9]|2[0-3]|\*)\s+(?:[0-2]?[0-9]|3[01]|\*)\s+(?:0?[0-9]|1[0-1]|\*)\s+(?:[0-6]|\*)$""";
|
||||
|
||||
public const string RGX_EMAIL
|
||||
= """^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$""";
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
using DataType = FreeSql.DataType;
|
||||
|
||||
namespace NetAdmin.Infrastructure;
|
||||
|
||||
/// <summary>
|
||||
@ -27,6 +29,41 @@ public static class GlobalStatic
|
||||
/// </summary>
|
||||
public static string SecretKey => "{6C4922D3-499A-46db-BFC4-0B51A9C4395F}";
|
||||
|
||||
/// <summary>
|
||||
/// SQL 随机排序语法
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException">NotImplementedException</exception>
|
||||
public static string SqlRandomSorting =>
|
||||
App.GetOptions<DatabaseOptions>().DbType switch {
|
||||
DataType.MySql => "RAND()"
|
||||
, DataType.SqlServer => "NEWID()"
|
||||
, DataType.PostgreSQL => "RANDOM()"
|
||||
, DataType.Oracle => "DBMS_RANDOM.value"
|
||||
, DataType.Sqlite => "RANDOM()"
|
||||
, DataType.OdbcOracle => throw new NotImplementedException()
|
||||
, DataType.OdbcSqlServer => throw new NotImplementedException()
|
||||
, DataType.OdbcMySql => throw new NotImplementedException()
|
||||
, DataType.OdbcPostgreSQL => throw new NotImplementedException()
|
||||
, DataType.Odbc => throw new NotImplementedException()
|
||||
, DataType.OdbcDameng => throw new NotImplementedException()
|
||||
, DataType.MsAccess => throw new NotImplementedException()
|
||||
, DataType.Dameng => throw new NotImplementedException()
|
||||
, DataType.OdbcKingbaseES => throw new NotImplementedException()
|
||||
, DataType.ShenTong => throw new NotImplementedException()
|
||||
, DataType.KingbaseES => throw new NotImplementedException()
|
||||
, DataType.Firebird => throw new NotImplementedException()
|
||||
, DataType.Custom => throw new NotImplementedException()
|
||||
, DataType.ClickHouse => throw new NotImplementedException()
|
||||
, DataType.GBase => throw new NotImplementedException()
|
||||
, DataType.QuestDb => throw new NotImplementedException()
|
||||
, DataType.Xugu => throw new NotImplementedException()
|
||||
, DataType.CustomOracle => throw new NotImplementedException()
|
||||
, DataType.CustomSqlServer => throw new NotImplementedException()
|
||||
, DataType.CustomMySql => throw new NotImplementedException()
|
||||
, DataType.CustomPostgreSQL => throw new NotImplementedException()
|
||||
, _ => throw new NotImplementedException()
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Json序列化选项
|
||||
/// </summary>
|
||||
|
@ -6,16 +6,17 @@
|
||||
<Import Project="$(SolutionDir)/build/copy.pkg.xml.comment.files.targets"/>
|
||||
<Import Project="$(SolutionDir)/build/prebuild.targets"/>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Cronos" Version="0.8.2"/>
|
||||
<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="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.Pure.NS" Version="4.9.1.24-ns1"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.1"/>
|
||||
<PackageReference Include="Minio" Version="6.0.1"/>
|
||||
<PackageReference Include="NSExt" Version="2.0.11"/>
|
||||
<PackageReference Include="RedLock.net" Version="2.3.2"/>
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0"/>
|
||||
<PackageReference Include="Minio" Version="6.0.1"/>
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -0,0 +1,20 @@
|
||||
using NetAdmin.Application.Modules;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Job;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业模块
|
||||
/// </summary>
|
||||
public interface IJobModule : ICrudModule<CreateJobReq, QueryJobRsp // 创建类型
|
||||
, QueryJobReq, QueryJobRsp // 查询类型
|
||||
, UpdateJobReq, QueryJobRsp // 修改类型
|
||||
, DelReq // 删除类型
|
||||
>
|
||||
{
|
||||
/// <summary>
|
||||
/// 启用/禁用作业
|
||||
/// </summary>
|
||||
Task SetEnabledAsync(UpdateJobReq req);
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using NetAdmin.Application.Modules;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业执行记录模块
|
||||
/// </summary>
|
||||
public interface IJobRecordModule : ICrudModule<CreateJobRecordReq, QueryJobRecordRsp // 创建类型
|
||||
, QueryJobRecordReq, QueryJobRecordRsp // 查询类型
|
||||
, UpdateJobRecordReq, QueryJobRecordRsp // 修改类型
|
||||
, DelReq // 删除类型
|
||||
>;
|
@ -17,42 +17,49 @@ public sealed class ApiService(
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryApiRsp> CreateAsync(CreateApiReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryApiRsp> GetAsync(QueryApiReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryApiRsp>> PagedQueryAsync(PagedQueryReq<QueryApiReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryApiRsp>> QueryAsync(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.ToTreeListAsync()
|
||||
@ -108,6 +115,7 @@ public sealed class ApiService(
|
||||
/// <inheritdoc />
|
||||
public Task<NopReq> UpdateAsync(NopReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@ -129,4 +137,17 @@ public sealed class ApiService(
|
||||
?.HttpMethods.First()
|
||||
});
|
||||
}
|
||||
|
||||
private ISelect<Sys_Api> QueryInternal(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.CreatedTime), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.CreatedTime);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ public sealed class CacheService(IConnectionMultiplexer connectionMultiplexer) /
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<GetAllEntriesRsp>> GetAllEntriesAsync(PagedQueryReq<GetAllEntriesReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var database = connectionMultiplexer.GetDatabase((int?)req.Filter?.DbIndex ?? 0);
|
||||
var redisResults = (RedisResult[])await database
|
||||
.ExecuteAsync("scan", (req.Page - 1) * req.PageSize, "count"
|
||||
|
@ -37,6 +37,7 @@ public sealed class CaptchaService : ServiceBase<ICaptchaService>, ICaptchaServi
|
||||
/// <inheritdoc />
|
||||
public Task<bool> VerifyCaptchaAsync(VerifyCaptchaReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (req.SawOffsetX == null) {
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public sealed class ConfigService(DefaultRepository<Sys_Config> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -26,6 +27,7 @@ public sealed class ConfigService(DefaultRepository<Sys_Config> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryConfigRsp> CreateAsync(CreateConfigReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QueryConfigRsp>();
|
||||
}
|
||||
@ -33,18 +35,21 @@ public sealed class ConfigService(DefaultRepository<Sys_Config> rpo) //
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryConfigReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryConfigRsp> GetAsync(QueryConfigReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryConfigReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<QueryConfigRsp>();
|
||||
}
|
||||
@ -61,6 +66,7 @@ public sealed class ConfigService(DefaultRepository<Sys_Config> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryConfigRsp>> PagedQueryAsync(PagedQueryReq<QueryConfigReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -74,6 +80,7 @@ public sealed class ConfigService(DefaultRepository<Sys_Config> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryConfigRsp>> QueryAsync(QueryReq<QueryConfigReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryConfigRsp>>();
|
||||
}
|
||||
@ -81,6 +88,7 @@ public sealed class ConfigService(DefaultRepository<Sys_Config> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryConfigRsp> UpdateAsync(UpdateConfigReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||
return await UpdateForSqliteAsync(req).ConfigureAwait(false) as QueryConfigRsp;
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
using NetAdmin.Application.Services;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业执行记录服务
|
||||
/// </summary>
|
||||
public interface IJobRecordService : IService, IJobRecordModule;
|
@ -0,0 +1,21 @@
|
||||
using NetAdmin.Application.Services;
|
||||
using NetAdmin.Domain.Dto.Sys.Job;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业服务
|
||||
/// </summary>
|
||||
public interface IJobService : IService, IJobModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 完成计划作业
|
||||
/// </summary>
|
||||
Task FinishJobAsync(UpdateJobReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 获取下一个要执行的计划作业
|
||||
/// </summary>
|
||||
Task<QueryJobRsp> GetNextJobAsync();
|
||||
}
|
@ -14,6 +14,11 @@ public interface IUserService : IService, IUserModule
|
||||
/// </summary>
|
||||
Task<QueryUserRsp> GetForUpdateAsync(QueryUserReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 用户编号登录
|
||||
/// </summary>
|
||||
Task<LoginRsp> LoginByUserIdAsync(long userId);
|
||||
|
||||
/// <summary>
|
||||
/// 单体更新
|
||||
/// </summary>
|
||||
|
@ -14,6 +14,7 @@ public sealed class DeptService(DefaultRepository<Sys_Dept> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -26,6 +27,7 @@ public sealed class DeptService(DefaultRepository<Sys_Dept> rpo) //
|
||||
/// <exception cref="NetAdminInvalidOperationException">Parent_department_does_not_exist</exception>
|
||||
public async Task<QueryDeptRsp> CreateAsync(CreateDeptReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (req.ParentId != 0 && !await Rpo.Select.AnyAsync(a => a.Id == req.ParentId).ConfigureAwait(false)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.父节点不存在);
|
||||
}
|
||||
@ -40,6 +42,7 @@ public sealed class DeptService(DefaultRepository<Sys_Dept> rpo) //
|
||||
/// <exception cref="NetAdminInvalidOperationException">该部门下存在子部门</exception>
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (await Rpo.Orm.Select<Sys_User>().AnyAsync(a => a.DeptId == req.Id).ConfigureAwait(false)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.该部门下存在用户);
|
||||
}
|
||||
@ -56,12 +59,14 @@ public sealed class DeptService(DefaultRepository<Sys_Dept> rpo) //
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryDeptReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryDeptRsp> GetAsync(QueryDeptReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryDeptReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<QueryDeptRsp>();
|
||||
}
|
||||
@ -69,12 +74,14 @@ public sealed class DeptService(DefaultRepository<Sys_Dept> rpo) //
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryDeptRsp>> PagedQueryAsync(PagedQueryReq<QueryDeptReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryDeptRsp>> QueryAsync(QueryReq<QueryDeptReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return (await QueryInternal(req).ToTreeListAsync().ConfigureAwait(false)).Adapt<IEnumerable<QueryDeptRsp>>();
|
||||
}
|
||||
|
||||
@ -82,6 +89,7 @@ public sealed class DeptService(DefaultRepository<Sys_Dept> rpo) //
|
||||
/// <exception cref="NetAdminUnexpectedException">NetAdminUnexpectedException</exception>
|
||||
public async Task<QueryDeptRsp> UpdateAsync(UpdateDeptReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return await Rpo.UpdateDiy.SetSource(req).ExecuteAffrowsAsync().ConfigureAwait(false) <= 0
|
||||
? throw new NetAdminUnexpectedException()
|
||||
: (await QueryInternal(new QueryReq<QueryDeptReq> { Filter = new QueryDeptReq { Id = req.Id } }, true)
|
||||
|
@ -22,6 +22,8 @@ public sealed class DevService(IApiService apiService) : ServiceBase<DevService>
|
||||
/// <inheritdoc />
|
||||
public async Task GenerateCsCodeAsync(GenerateCsCodeReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
|
||||
// 模块类型(Sys、Biz、等)
|
||||
var moduleType = Enum.GetName(req.Type)!;
|
||||
|
||||
@ -111,6 +113,7 @@ public sealed class DevService(IApiService apiService) : ServiceBase<DevService>
|
||||
/// <inheritdoc />
|
||||
public async Task GenerateIconCodeAsync(GenerateIconCodeReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var tplSvg = await File.ReadAllTextAsync(
|
||||
Path.Combine(_clientProjectPath, "src", "assets", "icons", "tpl", "Svg.vue"))
|
||||
.ConfigureAwait(false);
|
||||
|
@ -14,6 +14,7 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -26,6 +27,7 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
/// <exception cref="NetAdminInvalidOperationException">The_parent_node_does_not_exist</exception>
|
||||
public async Task<QueryDicCatalogRsp> CreateAsync(CreateDicCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (req.ParentId != 0 &&
|
||||
!await Rpo.Where(a => a.Id == req.ParentId).ForUpdate().AnyAsync().ConfigureAwait(false)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.父节点不存在);
|
||||
@ -38,6 +40,7 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.DeleteCascadeByDatabaseAsync(a => a.Id == req.Id).ConfigureAwait(false);
|
||||
return ret.Count;
|
||||
}
|
||||
@ -45,12 +48,14 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryDicCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryDicCatalogRsp> GetAsync(QueryDicCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryDicCatalogReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -60,6 +65,7 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryDicCatalogRsp>> PagedQueryAsync(PagedQueryReq<QueryDicCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -73,6 +79,7 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryDicCatalogRsp>> QueryAsync(QueryReq<QueryDicCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).ToTreeListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryDicCatalogRsp>>();
|
||||
}
|
||||
@ -82,6 +89,7 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
/// <exception cref="NetAdminUnexpectedException">NetAdminUnexpectedException</exception>
|
||||
public async Task<QueryDicCatalogRsp> UpdateAsync(UpdateDicCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (req.ParentId != 0 &&
|
||||
!await Rpo.Where(a => a.Id == req.ParentId).ForUpdate().AnyAsync().ConfigureAwait(false)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.父节点不存在);
|
||||
|
@ -14,6 +14,7 @@ public sealed class DicContentService(DefaultRepository<Sys_DicContent> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -26,6 +27,7 @@ public sealed class DicContentService(DefaultRepository<Sys_DicContent> rpo) //
|
||||
/// <exception cref="NetAdminInvalidOperationException">Dictionary_directory_does_not_exist</exception>
|
||||
public async Task<QueryDicContentRsp> CreateAsync(CreateDicContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (!await Rpo.Orm.Select<Sys_DicCatalog>()
|
||||
.Where(a => a.Id == req.CatalogId)
|
||||
.ForUpdate()
|
||||
@ -41,18 +43,21 @@ public sealed class DicContentService(DefaultRepository<Sys_DicContent> rpo) //
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryDicContentRsp> GetAsync(QueryDicContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryDicContentReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -62,6 +67,7 @@ public sealed class DicContentService(DefaultRepository<Sys_DicContent> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryDicContentRsp>> PagedQueryAsync(PagedQueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -75,6 +81,7 @@ public sealed class DicContentService(DefaultRepository<Sys_DicContent> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryDicContentRsp>> QueryAsync(QueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryDicContentRsp>>();
|
||||
}
|
||||
@ -84,6 +91,7 @@ public sealed class DicContentService(DefaultRepository<Sys_DicContent> rpo) //
|
||||
/// <exception cref="NetAdminUnexpectedException">NetAdminUnexpectedException</exception>
|
||||
public async Task<QueryDicContentRsp> UpdateAsync(UpdateDicContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (!await Rpo.Orm.Select<Sys_DicCatalog>()
|
||||
.Where(a => a.Id == req.CatalogId)
|
||||
.ForUpdate()
|
||||
|
@ -13,84 +13,98 @@ public sealed class DicService(IDicCatalogService catalogService, IDicContentSer
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteCatalogAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteContentAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDicCatalogRsp> CreateCatalogAsync(CreateDicCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDicContentRsp> CreateContentAsync(CreateDicContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteCatalogAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteContentAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDicCatalogRsp> GetCatalogAsync(QueryDicCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDicContentRsp> GetContentAsync(QueryDicContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryDicCatalogRsp>> PagedQueryCatalogAsync(PagedQueryReq<QueryDicCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryDicContentRsp>> PagedQueryContentAsync(PagedQueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryDicCatalogRsp>> QueryCatalogAsync(QueryReq<QueryDicCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryDicContentRsp>> QueryContentAsync(QueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDicCatalogRsp> UpdateCatalogAsync(UpdateDicCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.UpdateAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDicContentRsp> UpdateContentAsync(UpdateDicContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.UpdateAsync(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
using NetAdmin.Application.Repositories;
|
||||
using NetAdmin.Application.Services;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
using DataType = FreeSql.DataType;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
|
||||
/// <inheritdoc cref="IJobRecordService" />
|
||||
public sealed class JobRecordService(DefaultRepository<Sys_JobRecord> rpo) //
|
||||
: RepositoryService<Sys_JobRecord, IJobRecordService>(rpo), IJobRecordService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryJobRecordRsp> CreateAsync(CreateJobRecordReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QueryJobRecordRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryJobRecordRsp> GetAsync(QueryJobRecordReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryJobRecordReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryJobRecordRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryJobRecordRsp>> PagedQueryAsync(PagedQueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return new PagedQueryRsp<QueryJobRecordRsp>(req.Page, req.PageSize, total
|
||||
, list.Adapt<IEnumerable<QueryJobRecordRsp>>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryJobRecordRsp>> QueryAsync(QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryJobRecordRsp>>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryJobRecordRsp> UpdateAsync(UpdateJobRecordReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||
return await UpdateForSqliteAsync(req).ConfigureAwait(false) as QueryJobRecordRsp;
|
||||
}
|
||||
|
||||
var ret = await Rpo.UpdateDiy.SetSource(req).ExecuteUpdatedAsync().ConfigureAwait(false);
|
||||
return ret.FirstOrDefault()?.Adapt<QueryJobRecordRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<Sys_JobRecord> UpdateForSqliteAsync(Sys_JobRecord req)
|
||||
{
|
||||
return await Rpo.UpdateDiy.SetSource(req).ExecuteAffrowsAsync().ConfigureAwait(false) <= 0
|
||||
? null
|
||||
: await GetAsync(new QueryJobRecordReq { Id = req.Id }).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private ISelect<Sys_JobRecord> QueryInternal(QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
using Cronos;
|
||||
using NetAdmin.Application.Repositories;
|
||||
using NetAdmin.Application.Services;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Job;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
using DataType = FreeSql.DataType;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
|
||||
/// <inheritdoc cref="IJobService" />
|
||||
public sealed class JobService(DefaultRepository<Sys_Job> rpo) //
|
||||
: RepositoryService<Sys_Job, IJobService>(rpo), IJobService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryJobRsp> CreateAsync(CreateJobReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var nextExecTime = CronExpression.Parse(req.ExecutionCron).GetNextOccurrence(DateTime.UtcNow, TimeZoneInfo.Utc);
|
||||
var ret = await Rpo.InsertAsync(req with {
|
||||
NextExecTime = nextExecTime
|
||||
, NextTimeId = nextExecTime?.TimeUnixUtc()
|
||||
, RequestHeader = req.RequestHeaders?.Json()
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryJobRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.DeleteCascadeByDatabaseAsync(a => a.Id == req.Id).ConfigureAwait(false);
|
||||
return ret.Count;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task FinishJobAsync(UpdateJobReq req)
|
||||
{
|
||||
var nextExecTime = CronExpression.Parse(req.ExecutionCron).GetNextOccurrence(DateTime.UtcNow, TimeZoneInfo.Utc);
|
||||
_ = await UpdateAsync(req with {
|
||||
Status = JobStatues.Idle
|
||||
, NextExecTime = nextExecTime
|
||||
, NextTimeId = nextExecTime?.TimeUnixUtc()
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryJobRsp> GetAsync(QueryJobReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryJobReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<QueryJobRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryJobRsp> GetNextJobAsync()
|
||||
{
|
||||
var df = new DynamicFilterInfo {
|
||||
Filters = [
|
||||
new DynamicFilterInfo {
|
||||
Field = nameof(QueryJobReq.NextExecTime)
|
||||
, Value = DateTime.UtcNow
|
||||
, Operator = DynamicFilterOperators.LessThan
|
||||
}
|
||||
, new DynamicFilterInfo {
|
||||
Field = nameof(QueryJobReq.Status)
|
||||
, Value = JobStatues.Idle
|
||||
, Operator = DynamicFilterOperators.Eq
|
||||
}
|
||||
, new DynamicFilterInfo {
|
||||
Field = nameof(QueryJobReq.Enabled)
|
||||
, Value = true
|
||||
, Operator = DynamicFilterOperators.Eq
|
||||
}
|
||||
]
|
||||
};
|
||||
var job = await QueryInternal(new QueryReq<QueryJobReq> { DynamicFilter = df, Count = 1 }, true)
|
||||
.Where(a => !Rpo.Orm.Select<Sys_JobRecord>()
|
||||
.As("b")
|
||||
.Where(b => b.JobId == a.Id && b.TimeId == a.NextTimeId)
|
||||
.Any())
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return job == null
|
||||
? null
|
||||
: await UpdateAsync(job.Adapt<UpdateJobReq>() with {
|
||||
Status = JobStatues.Running
|
||||
, LastExecTime = DateTime.UtcNow
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryJobRsp>> PagedQueryAsync(PagedQueryReq<QueryJobReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return new PagedQueryRsp<QueryJobRsp>(req.Page, req.PageSize, total, list.Adapt<IEnumerable<QueryJobRsp>>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryJobRsp>> QueryAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryJobRsp>>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SetEnabledAsync(UpdateJobReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.UpdateDiy.Set(a => a.Enabled == req.Enabled).Where(a => a.Id == req.Id).ExecuteAffrowsAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryJobRsp> UpdateAsync(UpdateJobReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||
return (await UpdateForSqliteAsync(req).ConfigureAwait(false)).Adapt<QueryJobRsp>();
|
||||
}
|
||||
|
||||
_ = await Rpo.UpdateAsync(req).ConfigureAwait(false);
|
||||
return req.Adapt<QueryJobRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<Sys_Job> UpdateForSqliteAsync(Sys_Job req)
|
||||
{
|
||||
_ = await Rpo.UpdateAsync(req).ConfigureAwait(false);
|
||||
return req;
|
||||
}
|
||||
|
||||
private ISelect<Sys_Job> QueryInternal(QueryReq<QueryJobReq> req, bool orderByRandom = false)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.WhereIf( //
|
||||
req.Keywords?.Length > 0
|
||||
, a => a.Id == req.Keywords.Int64Try(0) || a.JobName.Contains(req.Keywords))
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
return !orderByRandom && (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true)
|
||||
? ret.OrderByDescending(a => a.Id)
|
||||
: ret.OrderByRandom();
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ public sealed class MenuService(DefaultRepository<Sys_Menu> rpo, IUserService us
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -25,6 +26,7 @@ public sealed class MenuService(DefaultRepository<Sys_Menu> rpo, IUserService us
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryMenuRsp> CreateAsync(CreateMenuReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QueryMenuRsp>();
|
||||
}
|
||||
@ -32,18 +34,21 @@ public sealed class MenuService(DefaultRepository<Sys_Menu> rpo, IUserService us
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryMenuReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryMenuRsp> GetAsync(QueryMenuReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryMenuReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<QueryMenuRsp>();
|
||||
}
|
||||
@ -51,12 +56,14 @@ public sealed class MenuService(DefaultRepository<Sys_Menu> rpo, IUserService us
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryMenuRsp>> PagedQueryAsync(PagedQueryReq<QueryMenuReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryMenuRsp>> QueryAsync(QueryReq<QueryMenuReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).ToTreeListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryMenuRsp>>();
|
||||
}
|
||||
@ -65,6 +72,7 @@ public sealed class MenuService(DefaultRepository<Sys_Menu> rpo, IUserService us
|
||||
/// <exception cref="NetAdminUnexpectedException">NetAdminUnexpectedException</exception>
|
||||
public async Task<QueryMenuRsp> UpdateAsync(UpdateMenuReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (await Rpo.UpdateDiy.SetSource(req).ExecuteAffrowsAsync().ConfigureAwait(false) <= 0) {
|
||||
throw new NetAdminUnexpectedException();
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ public sealed class RequestLogService(DefaultRepository<Sys_RequestLog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -25,6 +26,7 @@ public sealed class RequestLogService(DefaultRepository<Sys_RequestLog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryRequestLogRsp> CreateAsync(CreateRequestLogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QueryRequestLogRsp>();
|
||||
}
|
||||
@ -32,18 +34,21 @@ public sealed class RequestLogService(DefaultRepository<Sys_RequestLog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryRequestLogRsp> GetAsync(QueryRequestLogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryRequestLogReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -53,6 +58,7 @@ public sealed class RequestLogService(DefaultRepository<Sys_RequestLog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryRequestLogRsp>> PagedQueryAsync(PagedQueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -78,6 +84,7 @@ public sealed class RequestLogService(DefaultRepository<Sys_RequestLog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryRequestLogRsp>> QueryAsync(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryRequestLogRsp>>();
|
||||
}
|
||||
@ -85,6 +92,7 @@ public sealed class RequestLogService(DefaultRepository<Sys_RequestLog> rpo) //
|
||||
/// <inheritdoc />
|
||||
public Task<NopReq> UpdateAsync(NopReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ public sealed class RoleService(DefaultRepository<Sys_Role> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -25,6 +26,7 @@ public sealed class RoleService(DefaultRepository<Sys_Role> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryRoleRsp> CreateAsync(CreateRoleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var entity = req.Adapt<Sys_Role>();
|
||||
var ret = await Rpo.InsertAsync(entity).ConfigureAwait(false);
|
||||
|
||||
@ -40,6 +42,7 @@ public sealed class RoleService(DefaultRepository<Sys_Role> rpo) //
|
||||
/// <exception cref="NetAdminInvalidOperationException">Users_exist_under_this_role_and_deletion_is_not_allowed</exception>
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return await Rpo.Orm.Select<Sys_UserRole>().ForUpdate().AnyAsync(a => a.RoleId == req.Id).ConfigureAwait(false)
|
||||
? throw new NetAdminInvalidOperationException(Ln.该角色下存在用户)
|
||||
: await Rpo.DeleteAsync(a => a.Id == req.Id).ConfigureAwait(false);
|
||||
@ -48,12 +51,14 @@ public sealed class RoleService(DefaultRepository<Sys_Role> rpo) //
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryRoleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryRoleRsp> GetAsync(QueryRoleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryRoleReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<QueryRoleRsp>();
|
||||
}
|
||||
@ -61,6 +66,7 @@ public sealed class RoleService(DefaultRepository<Sys_Role> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryRoleRsp>> PagedQueryAsync(PagedQueryReq<QueryRoleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -73,6 +79,7 @@ public sealed class RoleService(DefaultRepository<Sys_Role> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryRoleRsp>> QueryAsync(QueryReq<QueryRoleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryRoleRsp>>();
|
||||
}
|
||||
@ -80,6 +87,7 @@ public sealed class RoleService(DefaultRepository<Sys_Role> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryRoleRsp> UpdateAsync(UpdateRoleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var entity = req.Adapt<Sys_Role>();
|
||||
_ = await Rpo.UpdateAsync(entity).ConfigureAwait(false);
|
||||
await Rpo.SaveManyAsync(entity, nameof(entity.Depts)).ConfigureAwait(false);
|
||||
|
@ -15,6 +15,7 @@ public sealed class SiteMsgDeptService(DefaultRepository<Sys_SiteMsgDept> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -26,6 +27,7 @@ public sealed class SiteMsgDeptService(DefaultRepository<Sys_SiteMsgDept> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgDeptRsp> CreateAsync(CreateSiteMsgDeptReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QuerySiteMsgDeptRsp>();
|
||||
}
|
||||
@ -33,18 +35,21 @@ public sealed class SiteMsgDeptService(DefaultRepository<Sys_SiteMsgDept> rpo) /
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QuerySiteMsgDeptReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgDeptRsp> GetAsync(QuerySiteMsgDeptReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgDeptReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -54,6 +59,7 @@ public sealed class SiteMsgDeptService(DefaultRepository<Sys_SiteMsgDept> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QuerySiteMsgDeptRsp>> PagedQueryAsync(PagedQueryReq<QuerySiteMsgDeptReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -67,6 +73,7 @@ public sealed class SiteMsgDeptService(DefaultRepository<Sys_SiteMsgDept> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QuerySiteMsgDeptRsp>> QueryAsync(QueryReq<QuerySiteMsgDeptReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QuerySiteMsgDeptRsp>>();
|
||||
}
|
||||
@ -74,6 +81,7 @@ public sealed class SiteMsgDeptService(DefaultRepository<Sys_SiteMsgDept> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgDeptRsp> UpdateAsync(UpdateSiteMsgDeptReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||
return await UpdateForSqliteAsync(req).ConfigureAwait(false) as QuerySiteMsgDeptRsp;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public sealed class SiteMsgFlagService(DefaultRepository<Sys_SiteMsgFlag> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -26,6 +27,7 @@ public sealed class SiteMsgFlagService(DefaultRepository<Sys_SiteMsgFlag> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgFlagRsp> CreateAsync(CreateSiteMsgFlagReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QuerySiteMsgFlagRsp>();
|
||||
}
|
||||
@ -33,18 +35,21 @@ public sealed class SiteMsgFlagService(DefaultRepository<Sys_SiteMsgFlag> rpo) /
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QuerySiteMsgFlagReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgFlagRsp> GetAsync(QuerySiteMsgFlagReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgFlagReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -54,6 +59,7 @@ public sealed class SiteMsgFlagService(DefaultRepository<Sys_SiteMsgFlag> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QuerySiteMsgFlagRsp>> PagedQueryAsync(PagedQueryReq<QuerySiteMsgFlagReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -67,6 +73,7 @@ public sealed class SiteMsgFlagService(DefaultRepository<Sys_SiteMsgFlag> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QuerySiteMsgFlagRsp>> QueryAsync(QueryReq<QuerySiteMsgFlagReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QuerySiteMsgFlagRsp>>();
|
||||
}
|
||||
@ -74,6 +81,7 @@ public sealed class SiteMsgFlagService(DefaultRepository<Sys_SiteMsgFlag> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgFlagRsp> UpdateAsync(UpdateSiteMsgFlagReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||
return await UpdateForSqliteAsync(req).ConfigureAwait(false) as QuerySiteMsgFlagRsp;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public sealed class SiteMsgRoleService(DefaultRepository<Sys_SiteMsgRole> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -26,6 +27,7 @@ public sealed class SiteMsgRoleService(DefaultRepository<Sys_SiteMsgRole> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgRoleRsp> CreateAsync(CreateSiteMsgRoleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QuerySiteMsgRoleRsp>();
|
||||
}
|
||||
@ -33,18 +35,21 @@ public sealed class SiteMsgRoleService(DefaultRepository<Sys_SiteMsgRole> rpo) /
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QuerySiteMsgRoleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgRoleRsp> GetAsync(QuerySiteMsgRoleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgRoleReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -54,6 +59,7 @@ public sealed class SiteMsgRoleService(DefaultRepository<Sys_SiteMsgRole> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QuerySiteMsgRoleRsp>> PagedQueryAsync(PagedQueryReq<QuerySiteMsgRoleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -67,6 +73,7 @@ public sealed class SiteMsgRoleService(DefaultRepository<Sys_SiteMsgRole> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QuerySiteMsgRoleRsp>> QueryAsync(QueryReq<QuerySiteMsgRoleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QuerySiteMsgRoleRsp>>();
|
||||
}
|
||||
@ -74,6 +81,7 @@ public sealed class SiteMsgRoleService(DefaultRepository<Sys_SiteMsgRole> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgRoleRsp> UpdateAsync(UpdateSiteMsgRoleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||
return await UpdateForSqliteAsync(req).ConfigureAwait(false) as QuerySiteMsgRoleRsp;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ public sealed class SiteMsgService(
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -32,6 +33,7 @@ public sealed class SiteMsgService(
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgRsp> CreateAsync(CreateSiteMsgReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
await CreateUpdateCheckAsync(req).ConfigureAwait(false);
|
||||
|
||||
// 主表
|
||||
@ -56,6 +58,7 @@ public sealed class SiteMsgService(
|
||||
/// <inheritdoc />
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.DeleteCascadeByDatabaseAsync(a => a.Id == req.Id).ConfigureAwait(false);
|
||||
return ret.Count;
|
||||
}
|
||||
@ -63,12 +66,14 @@ public sealed class SiteMsgService(
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgRsp> GetAsync(QuerySiteMsgReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgReq> { Filter = req })
|
||||
.IncludeMany(a => a.Roles)
|
||||
.IncludeMany(a => a.Users)
|
||||
@ -81,6 +86,7 @@ public sealed class SiteMsgService(
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgRsp> GetMineAsync(QuerySiteMsgReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await PagedQueryMineAsync(
|
||||
new PagedQueryReq<QuerySiteMsgReq> {
|
||||
DynamicFilter
|
||||
@ -97,6 +103,7 @@ public sealed class SiteMsgService(
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QuerySiteMsgRsp>> PagedQueryAsync(PagedQueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -118,12 +125,14 @@ public sealed class SiteMsgService(
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QuerySiteMsgRsp>> PagedQueryMineAsync(PagedQueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return PagedQueryMineAsync(req, false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QuerySiteMsgRsp>> QueryAsync(QueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QuerySiteMsgRsp>>();
|
||||
}
|
||||
@ -131,6 +140,7 @@ public sealed class SiteMsgService(
|
||||
/// <inheritdoc />
|
||||
public async Task SetSiteMsgStatusAsync(UpdateSiteMsgFlagReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (!await ExistAsync(new QueryReq<QuerySiteMsgReq> { Filter = new QuerySiteMsgReq { Id = req.SiteMsgId } })
|
||||
.ConfigureAwait(false)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.站内信不存在);
|
||||
@ -160,6 +170,7 @@ public sealed class SiteMsgService(
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgRsp> UpdateAsync(UpdateSiteMsgReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
await CreateUpdateCheckAsync(req).ConfigureAwait(false);
|
||||
|
||||
// 主表
|
||||
|
@ -15,6 +15,7 @@ public sealed class SiteMsgUserService(DefaultRepository<Sys_SiteMsgUser> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -26,6 +27,7 @@ public sealed class SiteMsgUserService(DefaultRepository<Sys_SiteMsgUser> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgUserRsp> CreateAsync(CreateSiteMsgUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QuerySiteMsgUserRsp>();
|
||||
}
|
||||
@ -33,18 +35,21 @@ public sealed class SiteMsgUserService(DefaultRepository<Sys_SiteMsgUser> rpo) /
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QuerySiteMsgUserReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgUserRsp> GetAsync(QuerySiteMsgUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgUserReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -54,6 +59,7 @@ public sealed class SiteMsgUserService(DefaultRepository<Sys_SiteMsgUser> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QuerySiteMsgUserRsp>> PagedQueryAsync(PagedQueryReq<QuerySiteMsgUserReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -67,6 +73,7 @@ public sealed class SiteMsgUserService(DefaultRepository<Sys_SiteMsgUser> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QuerySiteMsgUserRsp>> QueryAsync(QueryReq<QuerySiteMsgUserReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QuerySiteMsgUserRsp>>();
|
||||
}
|
||||
@ -74,6 +81,7 @@ public sealed class SiteMsgUserService(DefaultRepository<Sys_SiteMsgUser> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgUserRsp> UpdateAsync(UpdateSiteMsgUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||
return await UpdateForSqliteAsync(req).ConfigureAwait(false) as QuerySiteMsgUserRsp;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ public sealed class UserProfileService(DefaultRepository<Sys_UserProfile> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -27,6 +28,7 @@ public sealed class UserProfileService(DefaultRepository<Sys_UserProfile> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserProfileRsp> CreateAsync(CreateUserProfileReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var entity = req.Adapt<Sys_UserProfile>();
|
||||
var ret = await Rpo.InsertAsync(entity).ConfigureAwait(false);
|
||||
return ret.Adapt<QueryUserProfileRsp>();
|
||||
@ -35,18 +37,21 @@ public sealed class UserProfileService(DefaultRepository<Sys_UserProfile> rpo) /
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryUserProfileReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserProfileRsp> GetAsync(QueryUserProfileReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryUserProfileReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -56,6 +61,7 @@ public sealed class UserProfileService(DefaultRepository<Sys_UserProfile> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryUserProfileRsp>> PagedQueryAsync(PagedQueryReq<QueryUserProfileReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -82,6 +88,7 @@ public sealed class UserProfileService(DefaultRepository<Sys_UserProfile> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryUserProfileRsp>> QueryAsync(QueryReq<QueryUserProfileReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req)
|
||||
.Take(req.Count)
|
||||
.ToListAsync((a, b, c, d, e) => new {
|
||||
@ -115,6 +122,7 @@ public sealed class UserProfileService(DefaultRepository<Sys_UserProfile> rpo) /
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserProfileRsp> UpdateAsync(UpdateUserProfileReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var entity = req.Adapt<Sys_UserProfile>();
|
||||
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||
return await UpdateForSqliteAsync(entity).ConfigureAwait(false) as QueryUserProfileRsp;
|
||||
|
@ -38,6 +38,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -49,12 +50,14 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> CheckMobileAvailableAsync(CheckMobileAvailableReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return !await Rpo.Select.Where(a => a.Mobile == req.Mobile && a.Id != req.Id).AnyAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> CheckUserNameAvailableAsync(CheckUserNameAvailableReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return !await Rpo.Select.Where(a => a.UserName == req.UserName && a.Id != req.Id)
|
||||
.AnyAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -63,6 +66,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserRsp> CreateAsync(CreateUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
await CreateUpdateCheckAsync(req).ConfigureAwait(false);
|
||||
|
||||
// 主表
|
||||
@ -82,6 +86,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var effect = 0;
|
||||
|
||||
// 删除主表
|
||||
@ -101,12 +106,14 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return await (await QueryInternalAsync(req).ConfigureAwait(false)).AnyAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserRsp> GetAsync(QueryUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await (await QueryInternalAsync(new QueryReq<QueryUserReq> { Filter = req }).ConfigureAwait(false))
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -116,6 +123,8 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserRsp> GetForUpdateAsync(QueryUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
|
||||
// ReSharper disable once MethodHasAsyncOverload
|
||||
#pragma warning disable VSTHRD103
|
||||
return (await QueryInternal(new QueryReq<QueryUserReq> { Filter = req })
|
||||
@ -129,6 +138,7 @@ public sealed class UserService(
|
||||
/// <exception cref="NetAdminInvalidOperationException">用户名或密码错误</exception>
|
||||
public async Task<LoginRsp> LoginByPwdAsync(LoginByPwdReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var pwd = req.Password.Pwd().Guid();
|
||||
|
||||
Sys_User dbUser;
|
||||
@ -155,6 +165,7 @@ public sealed class UserService(
|
||||
/// <exception cref="NetAdminInvalidOperationException">用户不存在</exception>
|
||||
public async Task<LoginRsp> LoginBySmsAsync(LoginBySmsReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (!await verifyCodeService.VerifyAsync(req.Adapt<VerifySmsCodeReq>()).ConfigureAwait(false)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.验证码不正确);
|
||||
}
|
||||
@ -163,9 +174,18 @@ public sealed class UserService(
|
||||
return dbUser == null ? throw new NetAdminInvalidOperationException(Ln.用户不存在) : LoginInternal(dbUser);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<LoginRsp> LoginByUserIdAsync(long userId)
|
||||
{
|
||||
var dbUser = await Rpo.Where(a => a.Id == userId).ToOneAsync().ConfigureAwait(false);
|
||||
|
||||
return LoginInternal(dbUser);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryUserRsp>> PagedQueryAsync(PagedQueryReq<QueryUserReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await (await QueryInternalAsync(req).ConfigureAwait(false)).Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
.ToListAsync(_selectUserFields)
|
||||
@ -176,6 +196,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryUserRsp>> QueryAsync(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await (await QueryInternalAsync(req).ConfigureAwait(false)).Take(req.Count)
|
||||
.ToListAsync(_selectUserFields)
|
||||
.ConfigureAwait(false);
|
||||
@ -185,6 +206,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryUserProfileRsp>> QueryProfileAsync(QueryReq<QueryUserProfileReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return userProfileService.QueryAsync(req);
|
||||
}
|
||||
|
||||
@ -192,6 +214,7 @@ public sealed class UserService(
|
||||
/// <exception cref="NetAdminInvalidOperationException">验证码不正确</exception>
|
||||
public async Task<UserInfoRsp> RegisterAsync(RegisterUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (!await verifyCodeService.VerifyAsync(req.VerifySmsCodeReq).ConfigureAwait(false)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.验证码不正确);
|
||||
}
|
||||
@ -205,6 +228,7 @@ public sealed class UserService(
|
||||
/// <exception cref="NetAdminInvalidOperationException">用户不存在</exception>
|
||||
public async Task<uint> ResetPasswordAsync(ResetPasswordReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return !await verifyCodeService.VerifyAsync(req.VerifySmsCodeReq).ConfigureAwait(false)
|
||||
? throw new NetAdminInvalidOperationException(Ln.验证码不正确)
|
||||
: (uint)await Rpo.UpdateDiy
|
||||
@ -221,6 +245,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<UserInfoRsp> SetAvatarAsync(SetAvatarReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (await Rpo.UpdateDiy
|
||||
.SetSource(req with {
|
||||
Id = UserToken.Id
|
||||
@ -244,6 +269,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<UserInfoRsp> SetEmailAsync(SetEmailReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var user = Rpo.Where(a => a.Id == UserToken.Id).ToOne(a => new { a.Mobile, a.Version, a.Email });
|
||||
|
||||
// 如果已绑定手机号、需要手机安全验证
|
||||
@ -277,6 +303,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<UserInfoRsp> SetMobileAsync(SetMobileReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var user = await Rpo.Where(a => a.Id == UserToken.Id)
|
||||
.ToOneAsync(a => new { a.Version, a.Mobile })
|
||||
.ConfigureAwait(false);
|
||||
@ -321,6 +348,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<uint> SetPasswordAsync(SetPasswordReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var version = await Rpo.Where(a => a.Id == UserToken.Id && a.Password == req.OldPassword.Pwd().Guid())
|
||||
.ToOneAsync(a => new long?(a.Version))
|
||||
.ConfigureAwait(false);
|
||||
@ -343,6 +371,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserRsp> UpdateAsync(UpdateUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
await CreateUpdateCheckAsync(req).ConfigureAwait(false);
|
||||
|
||||
// 主表
|
||||
@ -374,6 +403,7 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public Task UpdateSingleAsync(UpdateUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.UpdateAsync(req);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -30,6 +31,7 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryVerifyCodeRsp> CreateAsync(CreateVerifyCodeReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var entity = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
|
||||
var ret = entity.Adapt<QueryVerifyCodeRsp>();
|
||||
@ -43,18 +45,21 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryVerifyCodeReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryVerifyCodeRsp> GetAsync(QueryVerifyCodeReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryVerifyCodeReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -64,6 +69,7 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryVerifyCodeRsp>> PagedQueryAsync(PagedQueryReq<QueryVerifyCodeReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -77,6 +83,7 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryVerifyCodeRsp>> QueryAsync(QueryReq<QueryVerifyCodeReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryVerifyCodeRsp>>();
|
||||
}
|
||||
@ -84,6 +91,7 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
||||
/// <inheritdoc />
|
||||
public async Task<SendVerifyCodeRsp> SendVerifyCodeAsync(SendVerifyCodeReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var lastSent = await GetLastSentAsync(req.DestDevice).ConfigureAwait(false);
|
||||
|
||||
QueryVerifyCodeRsp ret;
|
||||
@ -110,6 +118,7 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryVerifyCodeRsp> UpdateAsync(UpdateVerifyCodeReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||
return await UpdateForSqliteAsync(req).ConfigureAwait(false) as QueryVerifyCodeRsp;
|
||||
}
|
||||
@ -121,6 +130,7 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> VerifyAsync(VerifyCodeReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
#if DEBUG
|
||||
if (req.Code == "8888") {
|
||||
return true;
|
||||
|
@ -15,6 +15,7 @@ public sealed class ExampleService(DefaultRepository<Tpl_Example> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var sum = 0;
|
||||
foreach (var item in req.Items) {
|
||||
sum += await DeleteAsync(item).ConfigureAwait(false);
|
||||
@ -26,6 +27,7 @@ public sealed class ExampleService(DefaultRepository<Tpl_Example> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryExampleRsp> CreateAsync(CreateExampleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QueryExampleRsp>();
|
||||
}
|
||||
@ -33,18 +35,21 @@ public sealed class ExampleService(DefaultRepository<Tpl_Example> rpo) //
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryExampleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryExampleRsp> GetAsync(QueryExampleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryExampleReq> { Filter = req })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
@ -54,6 +59,7 @@ public sealed class ExampleService(DefaultRepository<Tpl_Example> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryExampleRsp>> PagedQueryAsync(PagedQueryReq<QueryExampleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.Count(out var total)
|
||||
@ -67,6 +73,7 @@ public sealed class ExampleService(DefaultRepository<Tpl_Example> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryExampleRsp>> QueryAsync(QueryReq<QueryExampleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).Take(req.Count).ToListAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryExampleRsp>>();
|
||||
}
|
||||
@ -74,6 +81,7 @@ public sealed class ExampleService(DefaultRepository<Tpl_Example> rpo) //
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryExampleRsp> UpdateAsync(UpdateExampleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||
return await UpdateForSqliteAsync(req).ConfigureAwait(false) as QueryExampleRsp;
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
using NetAdmin.Cache;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
namespace NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业缓存
|
||||
/// </summary>
|
||||
public interface IJobCache : ICache<IDistributedCache, IJobService>, IJobModule;
|
@ -0,0 +1,10 @@
|
||||
using NetAdmin.Cache;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
namespace NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业执行记录缓存
|
||||
/// </summary>
|
||||
public interface IJobRecordCache : ICache<IDistributedCache, IJobRecordService>, IJobRecordModule;
|
66
src/backend/NetAdmin.SysComponent.Cache/Sys/JobCache.cs
Normal file
66
src/backend/NetAdmin.SysComponent.Cache/Sys/JobCache.cs
Normal file
@ -0,0 +1,66 @@
|
||||
using NetAdmin.Cache;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Job;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
using NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
|
||||
namespace NetAdmin.SysComponent.Cache.Sys;
|
||||
|
||||
/// <inheritdoc cref="IJobCache" />
|
||||
public sealed class JobCache(IDistributedCache cache, IJobService service)
|
||||
: DistributedCache<IJobService>(cache, service), IScoped, IJobCache
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Service.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryJobRsp> CreateAsync(CreateJobReq req)
|
||||
{
|
||||
return Service.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
return Service.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
return Service.ExistAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryJobRsp> GetAsync(QueryJobReq req)
|
||||
{
|
||||
return Service.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryJobRsp>> PagedQueryAsync(PagedQueryReq<QueryJobReq> req)
|
||||
{
|
||||
return Service.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryJobRsp>> QueryAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
return Service.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SetEnabledAsync(UpdateJobReq req)
|
||||
{
|
||||
return Service.SetEnabledAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryJobRsp> UpdateAsync(UpdateJobReq req)
|
||||
{
|
||||
return Service.UpdateAsync(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
using NetAdmin.Cache;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
using NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
|
||||
namespace NetAdmin.SysComponent.Cache.Sys;
|
||||
|
||||
/// <inheritdoc cref="IJobRecordCache" />
|
||||
public sealed class JobRecordCache(IDistributedCache cache, IJobRecordService service)
|
||||
: DistributedCache<IJobRecordService>(cache, service), IScoped, IJobRecordCache
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Service.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryJobRecordRsp> CreateAsync(CreateJobRecordReq req)
|
||||
{
|
||||
return Service.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
return Service.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
return Service.ExistAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryJobRecordRsp> GetAsync(QueryJobRecordReq req)
|
||||
{
|
||||
return Service.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryJobRecordRsp>> PagedQueryAsync(PagedQueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
return Service.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryJobRecordRsp>> QueryAsync(QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
return Service.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryJobRecordRsp> UpdateAsync(UpdateJobRecordReq req)
|
||||
{
|
||||
return Service.UpdateAsync(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Job;
|
||||
using NetAdmin.Host.Attributes;
|
||||
using NetAdmin.Host.Controllers;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
using NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
|
||||
namespace NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(nameof(Sys), Module = nameof(Sys))]
|
||||
public sealed class JobController(IJobCache cache) : ControllerBase<IJobCache, IJobService>(cache), IJobModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 批量删除计划作业
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Cache.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建计划作业
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<QueryJobRsp> CreateAsync(CreateJobReq req)
|
||||
{
|
||||
return Cache.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除计划作业
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
return Cache.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业是否存在
|
||||
/// </summary>
|
||||
public Task<bool> ExistAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
return Cache.ExistAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个计划作业
|
||||
/// </summary>
|
||||
public Task<QueryJobRsp> GetAsync(QueryJobReq req)
|
||||
{
|
||||
return Cache.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询计划作业
|
||||
/// </summary>
|
||||
public Task<PagedQueryRsp<QueryJobRsp>> PagedQueryAsync(PagedQueryReq<QueryJobReq> req)
|
||||
{
|
||||
return Cache.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询计划作业
|
||||
/// </summary>
|
||||
public Task<IEnumerable<QueryJobRsp>> QueryAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
return Cache.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启用/禁用作业
|
||||
/// </summary>
|
||||
public Task SetEnabledAsync(UpdateJobReq req)
|
||||
{
|
||||
return Cache.SetEnabledAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新计划作业
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<QueryJobRsp> UpdateAsync(UpdateJobReq req)
|
||||
{
|
||||
return Cache.UpdateAsync(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
using Furion.Schedule;
|
||||
using NetAdmin.SysComponent.Host.Jobs;
|
||||
|
||||
namespace NetAdmin.SysComponent.Host.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// ServiceCollection 扩展方法
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 添加定时任务
|
||||
/// </summary>
|
||||
public static IServiceCollection AddSchedules(this IServiceCollection me)
|
||||
{
|
||||
return me.AddSchedule( //
|
||||
builder => builder //
|
||||
.AddJob<ScheduledJob>(false, Triggers.PeriodSeconds(5).SetRunOnStart(true)));
|
||||
}
|
||||
}
|
141
src/backend/NetAdmin.SysComponent.Host/Jobs/ScheduledJob.cs
Normal file
141
src/backend/NetAdmin.SysComponent.Host/Jobs/ScheduledJob.cs
Normal file
@ -0,0 +1,141 @@
|
||||
using FreeSql.Internal;
|
||||
using Furion.RemoteRequest;
|
||||
using Furion.RemoteRequest.Extensions;
|
||||
using Furion.Schedule;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Job;
|
||||
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
using NetAdmin.Host.BackgroundRunning;
|
||||
using NetAdmin.Host.Extensions;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
namespace NetAdmin.SysComponent.Host.Jobs;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业
|
||||
/// </summary>
|
||||
public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
|
||||
{
|
||||
private static string _accessToken;
|
||||
private static string _refreshToken;
|
||||
private readonly IJobRecordService _jobRecordService;
|
||||
private readonly IJobService _jobService;
|
||||
private readonly ILogger<ScheduledJob> _logger;
|
||||
private readonly IUserService _userService;
|
||||
private string _requestHeader;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScheduledJob" /> class.
|
||||
/// </summary>
|
||||
public ScheduledJob()
|
||||
{
|
||||
_jobRecordService = ServiceProvider.GetService<IJobRecordService>();
|
||||
_jobService = ServiceProvider.GetService<IJobService>();
|
||||
_logger = ServiceProvider.GetService<ILogger<ScheduledJob>>();
|
||||
_userService = ServiceProvider.GetService<IUserService>();
|
||||
}
|
||||
|
||||
/// <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(stoppingToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通用工作流
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException">NotImplementedException</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">ArgumentOutOfRangeException</exception>
|
||||
protected override async ValueTask WorkflowAsync(CancellationToken cancelToken)
|
||||
{
|
||||
QueryJobRsp job = null;
|
||||
try {
|
||||
job = await _jobService.GetNextJobAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (DbUpdateVersionException) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
if (job == null) {
|
||||
_logger.Info(Ln.未获取到待执行任务);
|
||||
return;
|
||||
}
|
||||
|
||||
var request = BuildRequest(job);
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var rsp = await request.SendAsync(cancelToken).ConfigureAwait(false);
|
||||
if (rsp.StatusCode == HttpStatusCode.Unauthorized) {
|
||||
var loginRsp = await _userService.LoginByUserIdAsync(job.UserId).ConfigureAwait(false);
|
||||
#pragma warning disable S2696
|
||||
_accessToken = loginRsp.AccessToken;
|
||||
_refreshToken = loginRsp.RefreshToken;
|
||||
#pragma warning restore S2696
|
||||
request = BuildRequest(job);
|
||||
rsp = await request.SendAsync(cancelToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
await UowManager.AtomicOperateAsync(async () => {
|
||||
var rspBody = await rsp.Content.ReadAsStringAsync(cancelToken).ConfigureAwait(false);
|
||||
var jobRecord = new CreateJobRecordReq //
|
||||
{
|
||||
Duration = sw.ElapsedMilliseconds
|
||||
, HttpMethod = job.HttpMethod
|
||||
, HttpStatusCode = rsp.StatusCode
|
||||
, JobId = job.Id
|
||||
, RequestBody = job.RequestBody
|
||||
, RequestHeader = _requestHeader
|
||||
, RequestUrl = job.RequestUrl
|
||||
, ResponseBody = rspBody
|
||||
, ResponseHeader = rsp.Headers.Json()
|
||||
, TimeId = job.NextTimeId!.Value
|
||||
};
|
||||
_ = await _jobRecordService.CreateAsync(jobRecord).ConfigureAwait(false);
|
||||
await _jobService
|
||||
.FinishJobAsync(job.Adapt<UpdateJobReq>() with { LastStatusCode = rsp.StatusCode })
|
||||
.ConfigureAwait(false);
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private HttpRequestPart BuildRequest(Sys_Job job)
|
||||
{
|
||||
var ret = job.RequestUrl.SetHttpMethod(new HttpMethod(job.HttpMethod.ToString()));
|
||||
var headers = new Dictionary<string, string>();
|
||||
|
||||
if (!_accessToken.NullOrEmpty()) {
|
||||
headers.Add(Chars.FLG_ACCESS_TOKEN_HEADER_KEY, $"{Chars.FLG_AUTH_SCHEMA} {_accessToken}");
|
||||
}
|
||||
|
||||
if (!_refreshToken.NullOrEmpty()) {
|
||||
headers.Add(Chars.FLG_X_ACCESS_TOKEN_HEADER_KEY, $"{Chars.FLG_AUTH_SCHEMA} {_refreshToken}");
|
||||
}
|
||||
|
||||
if (!job.RequestHeader.NullOrEmpty()) {
|
||||
ret = ret.SetHeaders(headers.Union(job.RequestHeader.Object<Dictionary<string, string>>())
|
||||
.ToDictionary(x => x.Key, x => x.Value));
|
||||
}
|
||||
|
||||
if (!job.RequestBody.NullOrEmpty()) {
|
||||
ret = ret.SetBody(job.RequestBody);
|
||||
}
|
||||
|
||||
return ret.OnResponsing(GetRequestHeader).OnException(GetRequestHeader);
|
||||
}
|
||||
|
||||
private void GetRequestHeader(HttpClient _, HttpResponseMessage rsp, string __)
|
||||
{
|
||||
_requestHeader = rsp!.RequestMessage!.Headers.Json();
|
||||
}
|
||||
|
||||
private void GetRequestHeader(HttpClient _, HttpResponseMessage rsp)
|
||||
{
|
||||
GetRequestHeader(_, rsp, null);
|
||||
}
|
||||
}
|
106
src/frontend/admin/src/api/sys/job.js
Normal file
106
src/frontend/admin/src/api/sys/job.js
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 计划作业服务
|
||||
* @module @/api/sys/job
|
||||
*/
|
||||
import config from '@/config'
|
||||
import http from '@/utils/request'
|
||||
export default {
|
||||
/**
|
||||
* 批量删除计划作业
|
||||
*/
|
||||
bulkDelete: {
|
||||
url: `${config.API_URL}/api/sys/job/bulk.delete`,
|
||||
name: `批量删除计划作业`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建计划作业
|
||||
*/
|
||||
create: {
|
||||
url: `${config.API_URL}/api/sys/job/create`,
|
||||
name: `创建计划作业`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除计划作业
|
||||
*/
|
||||
delete: {
|
||||
url: `${config.API_URL}/api/sys/job/delete`,
|
||||
name: `删除计划作业`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 计划作业是否存在
|
||||
*/
|
||||
exist: {
|
||||
url: `${config.API_URL}/api/sys/job/exist`,
|
||||
name: `计划作业是否存在`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取单个计划作业
|
||||
*/
|
||||
get: {
|
||||
url: `${config.API_URL}/api/sys/job/get`,
|
||||
name: `获取单个计划作业`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 分页查询计划作业
|
||||
*/
|
||||
pagedQuery: {
|
||||
url: `${config.API_URL}/api/sys/job/paged.query`,
|
||||
name: `分页查询计划作业`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 查询计划作业
|
||||
*/
|
||||
query: {
|
||||
url: `${config.API_URL}/api/sys/job/query`,
|
||||
name: `查询计划作业`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 启用/禁用作业
|
||||
*/
|
||||
setEnabled: {
|
||||
url: `${config.API_URL}/api/sys/job/set.enabled`,
|
||||
name: `启用/禁用作业`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新计划作业
|
||||
*/
|
||||
update: {
|
||||
url: `${config.API_URL}/api/sys/job/update`,
|
||||
name: `更新计划作业`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
}
|
10
src/frontend/admin/src/assets/icons/ScheduledJob.vue
Normal file
10
src/frontend/admin/src/assets/icons/ScheduledJob.vue
Normal file
@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<svg t="1706693297583" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4279" width="128" height="128">
|
||||
<path
|
||||
d="M553 186.4v-84h204.8c22.5 0 41-18.4 41-41 0-22.5-18.4-41-41-41H266.2c-22.5 0-41 18.4-41 41 0 22.5 18.4 41 41 41H471v84C264 207 102.4 381.5 102.4 593.9c0 226.2 183.4 409.6 409.6 409.6s409.6-183.4 409.6-409.6c0-212.4-161.7-387-368.6-407.5z m-41 735.2c-180.7 0-327.7-147-327.7-327.7s147-327.7 327.7-327.7 327.7 147 327.7 327.7-147 327.7-327.7 327.7z"
|
||||
p-id="4280"></path>
|
||||
<path
|
||||
d="M532.5 556.5V368.6c0-22.5-18.4-41-41-41s-41 18.4-41 41v204.8c0 0.3 0.1 0.5 0.1 0.7 0 2.4 0.3 4.9 0.7 7.3 0.2 0.9 0.5 1.7 0.8 2.6 0.5 1.7 0.9 3.5 1.6 5.2 0.2 0.5 0.5 1 0.8 1.5 2 4.2 4.5 8.2 8 11.6l173.8 173.8c15.9 15.9 42 15.9 57.9 0 15.9-15.9 15.9-42 0-57.9L532.5 556.5z"
|
||||
p-id="4281"></path>
|
||||
</svg>
|
||||
</template>
|
@ -53,3 +53,4 @@ export { default as ExLog } from './ExLog.vue'
|
||||
export { default as Key } from './Key.vue'
|
||||
export { default as OpenDoor } from './OpenDoor.vue'
|
||||
export { default as Alert } from './Alert.vue'
|
||||
export { default as ScheduledJob } from './ScheduledJob.vue'
|
File diff suppressed because one or more lines are too long
@ -6,6 +6,7 @@ html {
|
||||
height: 100%;
|
||||
background-color: #f6f8f9;
|
||||
font-size: 13px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
a {
|
||||
|
229
src/frontend/admin/src/views/sys/job/index.vue
Normal file
229
src/frontend/admin/src/views/sys/job/index.vue
Normal file
@ -0,0 +1,229 @@
|
||||
<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', 'status'],
|
||||
options: Object.entries(this.$GLOBAL.enums.jobStatues).map((x) => {
|
||||
return { value: x[0], label: x[1][1] }
|
||||
}),
|
||||
placeholder: $t('作业状态'),
|
||||
style: 'width:15rem',
|
||||
},
|
||||
{
|
||||
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:15rem',
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: ['dy', 'enabled'],
|
||||
options: [
|
||||
{ label: '启用', value: true },
|
||||
{ label: '禁用', value: false },
|
||||
],
|
||||
placeholder: '状态',
|
||||
style: 'width:15rem',
|
||||
},
|
||||
]"
|
||||
:vue="this"
|
||||
@search="onSearch" />
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<na-button-add :vue="this" />
|
||||
<el-button :disabled="selection.length === 0" icon="el-icon-delete" plain type="danger" @click="batchDel"></el-button>
|
||||
</div>
|
||||
</el-header>
|
||||
<el-main class="nopadding">
|
||||
<sc-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
:apiObj="$API.sys_job.pagedQuery"
|
||||
:default-sort="{ prop: 'createdTime', order: 'descending' }"
|
||||
:params="query"
|
||||
remote-filter
|
||||
remote-sort
|
||||
stripe
|
||||
@selection-change="
|
||||
(items) => {
|
||||
selection = items
|
||||
}
|
||||
">
|
||||
<el-table-column type="selection"></el-table-column>
|
||||
<el-table-column :label="$t('作业编号')" prop="id" width="150" />
|
||||
<el-table-column :label="$t('作业名称')" prop="jobName" />
|
||||
<na-col-indicator
|
||||
:label="$t('作业状态')"
|
||||
:options="[
|
||||
{ text: '空闲', type: 'success', value: 'idle' },
|
||||
{ text: '运行', type: 'warning', value: 'running' },
|
||||
]"
|
||||
prop="status"
|
||||
width="100"></na-col-indicator>
|
||||
<na-col-indicator
|
||||
:label="$t('请求方式')"
|
||||
:options="
|
||||
Object.entries(this.$GLOBAL.enums.httpMethods).map((x) => {
|
||||
return { value: x[0], text: x[1][1] }
|
||||
})
|
||||
"
|
||||
prop="httpMethod" />
|
||||
<el-table-column :label="$t('上次执行时间')" prop="lastExecTime" sortable="custom" />
|
||||
<el-table-column :label="$t('上次执行状态')" prop="lastStatusCode" sortable="custom" />
|
||||
<el-table-column :label="$t('下次执行时间')" prop="nextExecTime" sortable="custom" />
|
||||
<el-table-column :label="$t('创建时间')" prop="createdTime" sortable="custom" />
|
||||
<el-table-column :label="$t('启用')" prop="enabled">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.enabled" @change="changeSwitch($event, scope.row)"></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<na-col-operation
|
||||
:buttons="
|
||||
naColOperation.buttons.concat({
|
||||
icon: 'el-icon-delete',
|
||||
confirm: true,
|
||||
title: $t('删除作业'),
|
||||
click: rowDel,
|
||||
})
|
||||
"
|
||||
:vue="this" />
|
||||
</sc-table>
|
||||
</el-main>
|
||||
</el-container>
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
ref="saveDialog"
|
||||
@closed="dialog.save = false"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"></save-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import saveDialog from './save'
|
||||
import table from '@/config/table'
|
||||
import naColOperation from '@/config/naColOperation'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
saveDialog,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
query: {
|
||||
dynamicFilter: {
|
||||
filters: [],
|
||||
},
|
||||
filter: {},
|
||||
},
|
||||
dialog: {
|
||||
save: false,
|
||||
},
|
||||
selection: [],
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
computed: {
|
||||
naColOperation() {
|
||||
return naColOperation
|
||||
},
|
||||
table() {
|
||||
return table
|
||||
},
|
||||
},
|
||||
mounted() {},
|
||||
created() {},
|
||||
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.status === 'string' && form.dy.status.trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'status',
|
||||
operator: 'eq',
|
||||
value: form.dy.status,
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof form.dy.enabled === 'boolean') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'enabled',
|
||||
operator: 'eq',
|
||||
value: form.dy.enabled,
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof form.dy.httpMethod === 'string' && form.dy.httpMethod.trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'httpMethod',
|
||||
operator: 'eq',
|
||||
value: form.dy.httpMethod,
|
||||
})
|
||||
}
|
||||
|
||||
this.$refs.table.upData()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
193
src/frontend/admin/src/views/sys/job/save.vue
Normal file
193
src/frontend/admin/src/views/sys/job/save.vue
Normal file
@ -0,0 +1,193 @@
|
||||
<template>
|
||||
<sc-dialog v-model="visible" :title="titleMap[mode]" :width="800" destroy-on-close fullscreen @closed="$emit('closed')">
|
||||
<el-form
|
||||
ref="dialogForm"
|
||||
v-loading="loading"
|
||||
:disabled="mode === 'view'"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-position="right"
|
||||
label-width="150px">
|
||||
<el-tabs tab-position="top">
|
||||
<el-tab-pane :label="$t('基本信息')">
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('作业编号')" prop="id">
|
||||
<el-input v-model="form.id" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('执行计划')" prop="executionCron">
|
||||
<el-input v-model="form.executionCron" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('请求方法')" prop="httpMethod">
|
||||
<el-select v-model="form.httpMethod" clearable filterable>
|
||||
<el-option v-for="(item, i) in $GLOBAL.enums.httpMethods" :key="i" :label="item[1]" :value="i" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('作业名称')" prop="jobName">
|
||||
<el-input v-model="form.jobName" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('最近一次执行时间')" prop="lastExecTime">
|
||||
<el-input v-model="form.lastExecTime" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('下一次执行时间')" prop="nextExecTime">
|
||||
<el-input v-model="form.nextExecTime" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('下一次执行时间编号')" prop="nextTimeId">
|
||||
<el-input v-model="form.nextTimeId" clearable />
|
||||
</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="requestBody">
|
||||
<el-input v-model="form.requestBody" 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 v-if="mode === 'view'" :label="$t('作业状态')" prop="status">
|
||||
<el-input v-model="form.status" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('执行用户编号')" prop="userId">
|
||||
<el-input v-model="form.userId" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-else :label="$t('执行用户')" prop="userId">
|
||||
<na-user v-model="form.userId"></na-user>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('创建时间')" prop="createdTime">
|
||||
<el-input v-model="form.createdTime" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('修改时间')" prop="modifiedTime">
|
||||
<el-input v-model="form.modifiedTime" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('数据版本')" prop="version">
|
||||
<el-input v-model="form.version" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('创建者编号')" prop="createdUserId">
|
||||
<el-input v-model="form.createdUserId" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('创建者用户名')" prop="createdUserName">
|
||||
<el-input v-model="form.createdUserName" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('修改者编号')" prop="modifiedUserId">
|
||||
<el-input v-model="form.modifiedUserId" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mode === 'view'" :label="$t('修改者用户名')" prop="modifiedUserName">
|
||||
<el-input v-model="form.modifiedUserName" 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>
|
||||
<el-button v-if="mode !== 'view'" :loading="loading" type="primary" @click="submit">保 存</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: {
|
||||
executionCron: [
|
||||
{
|
||||
required: true,
|
||||
pattern: this.$GLOBAL.chars.RGX_CRON,
|
||||
message: this.$t('执行计划不正确'),
|
||||
},
|
||||
],
|
||||
httpMethod: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('请求方不能为空'),
|
||||
},
|
||||
],
|
||||
jobName: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('作业名称不能为空'),
|
||||
},
|
||||
],
|
||||
requestUrl: [
|
||||
{
|
||||
required: true,
|
||||
pattern: this.$GLOBAL.chars.RGX_URL,
|
||||
message: this.$t('请求的网络地址不正确'),
|
||||
},
|
||||
],
|
||||
userId: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: this.$t('执行用户不能为空'),
|
||||
validator: (rule, value, callback) => {
|
||||
if (value.id) callback()
|
||||
else callback(new Error())
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
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.get.post({ id: data.id })
|
||||
Object.assign(this.form, res.data)
|
||||
}
|
||||
this.loading = false
|
||||
return this
|
||||
},
|
||||
|
||||
//表单提交方法
|
||||
async submit() {
|
||||
const valid = await this.$refs.dialogForm.validate().catch(() => {})
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
const method = this.mode === 'add' ? this.$API.sys_job.create : this.$API.sys_job.update
|
||||
this.loading = true
|
||||
const res = await method.post(Object.assign({}, this.form, { userId: this.form.userId.id }))
|
||||
this.loading = false
|
||||
this.$emit('success', res.data, this.mode)
|
||||
this.visible = false
|
||||
this.$message.success('操作成功')
|
||||
} catch {
|
||||
//
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
Loading…
x
Reference in New Issue
Block a user