update V 2.4.3.0

This commit is contained in:
rnchg
2026-07-21 19:00:11 +08:00
parent 4b28b75e57
commit 86bb4d07e4
1571 changed files with 511366 additions and 244 deletions
View File
View File
View File
View File
View File
@@ -0,0 +1,77 @@
using Common.AspNetCore.Extensions;
using Common.AspNetCore.Helpers;
using Common.Frame.Dtos.Trace;
using Common.Frame.Services.Trace.Interfaces;
using Common.NETCore.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Diagnostics;
namespace FASS.Scheduler.Attributes
{
public class ActionLogIgnoreAttribute : ActionFilterAttribute
{
}
public class ActionLogAttribute : ActionFilterAttribute
{
private readonly IUserActionService _userLogService;
private readonly ILogger<ActionLogAttribute> _logger;
public ActionLogAttribute(
IUserActionService userLogService,
ILogger<ActionLogAttribute> logger)
{
_userLogService = userLogService;
_logger = logger;
}
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (IsIgnore(context))
{
await next();
return;
}
var watch = Stopwatch.StartNew();
try
{
await next();
}
finally
{
watch.Stop();
var userActionDto = new UserActionDto
{
UserId = IdentityHelper.ToUserIdentity(context.HttpContext.User).Id,
Controller = context.RouteData.DataTokens["area"] is null ? $"{context.RouteData.Values["controller"]}" : $"{context.RouteData.DataTokens["area"]}/{context.RouteData.Values["controller"]}",
Action = $"{context.RouteData.Values["action"]}",
Watch = watch.Elapsed.ToString(),
RequestUrl = context.HttpContext.Request.GetAbsoluteUri(),
RequestToken = context.HttpContext.Request.Cookies["Authorization"],
ResponseCode = context.HttpContext.Response.StatusCode.ToString(),
UserAgent = context.HttpContext.Request.Headers["User-Agent"],
IpAddress = context.HttpContext.GetUserIp()
};
try
{
await _userLogService.AddAsync(userActionDto);
}
catch (Exception ex)
{
_logger.LogError(ex, "记录用户操作日志失败");
}
}
}
private static bool IsIgnore(FilterContext context)
{
if (context.Filters.OfType<ActionLogIgnoreAttribute>().Any())
{
return true;
}
return context.ActionDescriptor.FilterDescriptors.Select(f => f.Filter).OfType<TypeFilterAttribute>().Any(f => f.ImplementationType == typeof(ActionLogIgnoreAttribute));
}
}
}
@@ -0,0 +1,56 @@
using Common.AspNetCore.Helpers;
using Common.Frame.Services.Account.Interfaces;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FASS.Scheduler.Attributes
{
[AttributeUsage(AttributeTargets.All)]
public class AuthorizeActionIgnoreAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
}
}
[AttributeUsage(AttributeTargets.All)]
public class AuthorizeActionAttribute : Attribute, IAsyncAuthorizationFilter
{
private readonly IPermissionService _permissionService;
public AuthorizeActionAttribute(
IPermissionService permissionService)
{
_permissionService = permissionService;
}
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
if (IsIgnore(context))
{
return;
}
var userIdentity = IdentityHelper.ToUserIdentity(context.HttpContext.User);
if (userIdentity.IsSystem)
{
return;
}
var target = context.HttpContext.Request.Path.ToString();
var isOk = await _permissionService.CheckTargetAsync(userIdentity.Id, target);
if (isOk)
{
return;
}
context.Result = new UnauthorizedResult();
}
private static bool IsIgnore(AuthorizationFilterContext context)
{
if (context.Filters.OfType<AuthorizeActionIgnoreAttribute>().Any())
{
return true;
}
return context.ActionDescriptor.FilterDescriptors.Select(f => f.Filter).OfType<TypeFilterAttribute>().Any(f => f.ImplementationType == typeof(AuthorizeActionIgnoreAttribute));
}
}
}
@@ -0,0 +1,46 @@
using Common.NETCore.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Net;
namespace FASS.Scheduler.Attributes
{
public class ResultAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
if (context.Result is StatusCodeResult statusCodeResult)
{
var responseResult = new ResponseResult();
responseResult.Code = statusCodeResult.StatusCode.ToString();
if (statusCodeResult is OkResult)
{
responseResult.Success = true;
responseResult.Data = Enum.GetName(typeof(HttpStatusCode), (HttpStatusCode)statusCodeResult.StatusCode);
}
else
{
responseResult.Success = false;
responseResult.Message = Enum.GetName(typeof(HttpStatusCode), (HttpStatusCode)statusCodeResult.StatusCode);
}
context.Result = new OkObjectResult(responseResult);
}
else if (context.Result is ObjectResult objectResult)
{
var responseResult = new ResponseResult();
responseResult.Code = (objectResult?.StatusCode ?? 0).ToString();
if (objectResult is OkObjectResult)
{
responseResult.Success = true;
responseResult.Data = objectResult.Value;
}
else
{
responseResult.Success = false;
responseResult.Message = objectResult?.Value;
}
context.Result = new OkObjectResult(responseResult);
}
}
}
}
@@ -0,0 +1,16 @@
using FASS.Scheduler.Attributes;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace FASS.Scheduler.Controllers.Base
{
[Authorize]
[ApiController]
[Route("api/v1/[controller]/[action]")]
[TypeFilter(typeof(AuthorizeActionAttribute))]
[TypeFilter(typeof(ActionLogAttribute))]
public class BaseController : ControllerBase
{
}
}
@@ -0,0 +1,33 @@
using FASS.Scheduler.Attributes;
using FASS.Scheduler.Controllers.Base;
using FASS.Service.Consts.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
namespace FASS.Scheduler.Controllers
{
[AllowAnonymous]
[TypeFilter(typeof(AuthorizeActionIgnoreAttribute))]
[TypeFilter(typeof(ActionLogIgnoreAttribute))]
[Tags("接口")]
[EnableRateLimiting(AppConst.Rate.Name)]
public class CarController : BaseController
{
private readonly ILogger<CarController> _logger;
public CarController(
ILogger<CarController> logger)
{
_logger = logger;
}
[Tags("状态")]
[HttpPost]
[DisableRateLimiting]
public IActionResult State()
{
return Ok("Ok");
}
}
}
@@ -0,0 +1,65 @@
using FASS.Scheduler.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
namespace FASS.Scheduler.Extensions.Configure
{
public static class AuthExtension
{
public static IServiceCollection AddAuth(this IServiceCollection services, AppSettings appSettings)
{
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidIssuer = appSettings.Auth.Issuer,
ValidateAudience = true,
ValidAudience = appSettings.Auth.Audience,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(appSettings.Auth.SigningKey)),
ValidateLifetime = true,
RequireExpirationTime = true,
ClockSkew = TimeSpan.Zero
};
options.Events = new JwtBearerEvents()
{
OnMessageReceived = context =>
{
if (context.Request.Headers.ContainsKey("Authorization"))
{
context.Token = context.Request.Headers["Authorization"].FirstOrDefault()?.Substring("Bearer ".Length);
}
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
if (context.Exception is SecurityTokenExpiredException)
{
context.Response.Headers.Append("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});
return services;
}
public static IApplicationBuilder UseAuth(this IApplicationBuilder app)
{
app.UseAuthentication();
app.UseAuthorization();
return app;
}
}
}
@@ -0,0 +1,30 @@
using FASS.Scheduler.Models;
using FASS.Scheduler.Services.CronTasks;
using FASS.Scheduler.Services.EventBus;
using FASS.Scheduler.Services.Extends;
using FASS.Service.Extensions;
namespace FASS.Scheduler.Extensions.Configure
{
public static class BootExtension
{
public static IServiceCollection AddBoot(this IServiceCollection services, IConfiguration configuration, AppSettings appSettings)
{
services.AddSingleton<ExtendService>();
services.AddSingleton<CronTaskService>();
services.AddSingleton<EventBusService>();
services.AddService(configuration, appSettings.App.ActivationCode, () => appSettings.Frame);
return services;
}
public static IServiceProvider UseBoot(this IServiceProvider provider)
{
provider.UseService();
return provider;
}
}
}
@@ -0,0 +1,44 @@
using Common.NETCore.Extensions;
using Common.NETCore.Models;
using Microsoft.AspNetCore.Diagnostics;
using System.Text.Json;
namespace FASS.Scheduler.Extensions.Configure
{
public static class ExceptionExtension
{
public static IApplicationBuilder UseException(this IApplicationBuilder app)
{
var jsonSerializerOptions = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase
};
app.UseExceptionHandler(builder =>
{
builder.Run(async context =>
{
var ex = context.Features.Get<IExceptionHandlerFeature>()?.Error.GetBaseException();
var responseResult = new ResponseResult()
{
Success = false,
Code = context.Response.StatusCode.ToString()
};
if (ex != null)
{
responseResult.Message = ex.Message;
}
else
{
responseResult.Message = "未知错误";
}
context.Response.StatusCode = StatusCodes.Status200OK;
context.Response.ContentType = "application/json";
await context.Response.Body.WriteAsync(responseResult.ToJson(jsonSerializerOptions).ToBytes());
});
});
return app;
}
}
}
@@ -0,0 +1,12 @@
using Common.AspNetCore.Extensions;
namespace FASS.Scheduler.Extensions.Configure
{
public static class SessionExtension
{
public static IApplicationBuilder UseCurrent(this IApplicationBuilder app)
{
return app.UseCurrentUserContext();
}
}
}
@@ -0,0 +1,45 @@
using Common.NETCore.Utility;
using Microsoft.OpenApi;
namespace FASS.Scheduler.Extensions.Configure
{
public static class SwaggerExtension
{
public static IServiceCollection AddSwashbuckle(this IServiceCollection services)
{
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = Session.AssemblyName.Name,
Version = Session.AssemblyName.Version?.ToString()
});
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Name = "Authorization",
BearerFormat = "JWT",
Description = "Value {Bearer Token}"
});
options.AddSecurityRequirement(document => new OpenApiSecurityRequirement
{
[new OpenApiSecuritySchemeReference("Bearer", document)] = []
});
options.OrderActionsBy(api => api.RelativePath);
//options.TagActionsBy(api => [api.HttpMethod]);
});
return services;
}
public static IApplicationBuilder UseSwashbuckle(this IApplicationBuilder app)
{
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
});
return app;
}
}
}
@@ -0,0 +1,29 @@
using Common.AspNetCore.Helpers;
using FASS.Scheduler.Models;
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;
namespace FASS.Scheduler.Extensions
{
public static class TokenExtension
{
public static string GetToken(this AppSettings appSettings, IEnumerable<Claim> claims)
{
var signingKey = appSettings.Auth.SigningKey;
var algorithm = SecurityAlgorithms.HmacSha256;
var issuer = appSettings.Auth.Issuer;
var audience = appSettings.Auth.Audience;
var notBefore = DateTime.Now;
var expires = notBefore.AddSeconds(appSettings.Auth.ExpireSeconds);
var token = JwtHelper.CreateToken(signingKey, algorithm, issuer, audience, claims, notBefore, expires);
return token;
}
public static string RefreshToken(this AppSettings appSettings, string token)
{
var signingKey = appSettings.Auth.SigningKey;
var refreshToken = JwtHelper.RefreshToken(token, signingKey);
return refreshToken;
}
}
}
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<CETCompat>false</CETCompat>
<Version>2.4.3</Version>
<AssemblyName>FASS.Scheduler</AssemblyName>
<ApplicationIcon>Resources\App.ico</ApplicationIcon>
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Common.Net" Version="2.4.3" />
<PackageReference Include="Grpc.AspNetCore" Version="2.80.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.10" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.10" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FASS.Service.Lite\FASS.Service.Lite.csproj" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="Protos\remote.proto" GrpcServices="Server" />
</ItemGroup>
</Project>
@@ -0,0 +1,6 @@
@FASS.Scheduler.Lite_HostAddress = http://localhost:5276
GET {{FASS.Scheduler.Lite_HostAddress}}/weatherforecast/
Accept: application/json
###
@@ -0,0 +1,53 @@
using FASS.Scheduler.Grpc;
using Grpc.Core;
namespace FASS.Scheduler.Grpcs;
public sealed class RemoteService : Remote.RemoteBase
{
private readonly ILogger<RemoteService> _logger;
public RemoteService(ILogger<RemoteService> logger)
{
_logger = logger;
}
private async Task<ResponseReply> TryExecuteResponseAsync(
string operation,
Func<CancellationToken, Task<ResponseReply>> action,
CancellationToken cancellationToken = default)
{
try
{
return await action(cancellationToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "远程调用执行失败:操作[{Operation}]。", operation);
return new ResponseReply
{
Success = false,
Message = ex.Message
};
}
}
private Task<ResponseReply> Execute(
string operation,
Action action,
CancellationToken cancellationToken = default) =>
TryExecuteResponseAsync(
operation,
_ =>
{
action();
return Task.FromResult(new ResponseReply { Success = true });
},
cancellationToken);
public override Task<ResponseReply> CarAdd(CarAddRequest request, ServerCallContext context) =>
Execute(nameof(CarAdd), () =>
{
_logger.LogDebug("成功:{RequestDto}", request.Dto);
}, context.CancellationToken);
}
@@ -0,0 +1,56 @@
using Common.Frame.Options;
namespace FASS.Scheduler.Models
{
public class AppSettings
{
public Rate Rate { get; set; } = null!;
public Auth Auth { get; set; } = null!;
public App App { get; set; } = null!;
public FrameOption Frame { get; set; } = null!;
public Scheduler Scheduler { get; set; } = null!;
public Extend Extend { get; set; } = null!;
}
public class Rate
{
public int PermitLimit { get; set; }
public int QueueLimit { get; set; }
public int WindowMilliseconds { get; set; }
}
public class Auth
{
public required string SigningKey { get; set; }
public required string Issuer { get; set; }
public required string Audience { get; set; }
public int ExpireSeconds { get; set; }
}
public class App
{
public required string ActivationCode { get; set; }
}
public class Scheduler
{
public int StartupDueTime { get; set; }
}
public class Service
{
public string? TcpServerLocalIP { get; set; }
public string? UdpServerLocalIP { get; set; }
}
public class Extend
{
public bool EnableComClient { get; set; }
public string? ComClientPortName { get; set; }
public bool EnableTcpClient { get; set; }
public string? TcpClientRemoteIP { get; set; }
public bool EnableTcpServer { get; set; }
public string? TcpServerLocalIP { get; set; }
public bool EnableUdpServer { get; set; }
public string? UdpServerRemoteIP { get; set; }
public string? UdpServerLocalIP { get; set; }
public bool EnableHttpClient { get; set; }
public string? HttpClientBaseAddress { get; set; }
public bool EnableHttpServer { get; set; }
public List<string> HttpServerPrefixes { get; set; } = [];
}
}
@@ -0,0 +1,68 @@
using Common.NETCore;
using Common.NETCore.Extensions;
using Common.NETCore.Helpers;
using FASS.Scheduler.Attributes;
using FASS.Scheduler.Extensions.Configure;
using FASS.Scheduler.Grpcs;
using FASS.Scheduler.Models;
using FASS.Scheduler.Services;
using FASS.Service.Consts.Core;
using Microsoft.AspNetCore.RateLimiting;
using Serilog;
using System.Threading.RateLimiting;
var builder = WebApplication.CreateBuilder(args);
var appSettings = builder.Configuration.Get<AppSettings>();
builder.Services.AddSingleton(Guard.NotNull(appSettings));
builder.Services.AddSerilog((services, logger) => logger.ReadFrom.Configuration(builder.Configuration));
builder.Services
.AddControllers(options =>
{
options.Filters.Add(typeof(ResultAttribute));
options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true;
})
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.AddDefaultOptions();
});
builder.Services.AddHttpContextAccessor();
builder.Services.AddSignalR();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwashbuckle();
builder.Services.AddAuth(appSettings);
builder.Services.AddBoot(builder.Configuration, appSettings);
builder.Services.AddHostedService<AppHostService>();
builder.Services.AddOpenApi();
builder.Services.AddGrpc();
builder.Services.AddCors(options =>
{
options.AddPolicy(AppConst.Cors.Name, policy =>
{
policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().WithExposedHeaders("X-Pagination");
});
});
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter(AppConst.Rate.Name, opt =>
{
opt.Window = TimeSpan.FromMilliseconds(appSettings.Rate.WindowMilliseconds);
opt.PermitLimit = appSettings.Rate.PermitLimit;
opt.QueueLimit = appSettings.Rate.QueueLimit;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
});
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
});
var app = builder.Build();
app.UseException();
app.UseSerilogRequestLogging();
app.UseRouting();
app.UseSwashbuckle();
app.UseAuth();
app.UseCurrent();
app.Services.UseBoot();
app.MapGrpcService<RemoteService>();
app.UseCors(AppConst.Cors.Name);
app.UseRateLimiter();
app.MapControllers();
app.Lifetime.ApplicationStarted.Register(() => BrowserHelper.OpenBrowser($"{app.Urls.First()}/swagger"));
app.Run();
@@ -0,0 +1,14 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:20101",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
@@ -0,0 +1,19 @@
syntax = "proto3";
option csharp_namespace = "FASS.Scheduler.Grpc";
package remote;
service Remote {
rpc CarAdd (CarAddRequest) returns (ResponseReply);
}
message ResponseReply {
bool success = 1;
string message = 2;
string data = 3;
}
message CarAddRequest {
string dto = 1;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

@@ -0,0 +1,148 @@
using Common.AspNetCore.Extensions;
using Common.Frame.Services.Cache.Interfaces;
using Common.NETCore.Utility;
using FASS.Scheduler.Models;
using FASS.Scheduler.Services.CronTasks;
using FASS.Scheduler.Services.EventBus;
using FASS.Scheduler.Services.Extends;
using FASS.Scheduler.Utility;
using FASS.Service.Dtos.Setting;
namespace FASS.Scheduler.Services;
public class AppHostService : IHostedService, IAsyncDisposable
{
private IHostApplicationLifetime Lifetime { get; }
private CancellationTokenSource? _startupTokenSource;
private Task? _startupTask;
public ILogger<AppHostService> Logger { get; }
public AppSettings AppSettings { get; }
public IServiceProvider ServiceProvider { get; }
public ExtendService ExtendService { get; private set; } = null!;
public EventBusService EventBusService { get; private set; } = null!;
public CronTaskService CronTaskService { get; private set; } = null!;
public AppHostService(
IHostApplicationLifetime lifetime,
ILogger<AppHostService> logger,
AppSettings appSettings,
IServiceProvider serviceProvider)
{
Lifetime = lifetime;
Logger = logger;
AppSettings = appSettings;
ServiceProvider = serviceProvider;
Lifetime.ApplicationStarted.Register(OnApplicationStarted);
}
public Task StartAsync(CancellationToken cancellationToken)
{
Logger.LogInformation("服务启动中");
return Task.CompletedTask;
}
public async Task StopAsync(CancellationToken cancellationToken)
{
Logger.LogInformation("服务停止中");
var startupTokenSource = Interlocked.Exchange(ref _startupTokenSource, null);
startupTokenSource?.Cancel();
var startupTask = Interlocked.Exchange(ref _startupTask, null);
if (startupTask is not null)
{
try
{
await startupTask.WaitAsync(cancellationToken);
}
catch (OperationCanceledException) when (startupTokenSource?.IsCancellationRequested == true || cancellationToken.IsCancellationRequested)
{
Logger.LogInformation("服务启动流程已取消");
}
catch (Exception ex)
{
Logger.LogError(ex, "服务等待启动流程结束失败");
}
}
startupTokenSource?.Dispose();
var stopTasks = new List<Task>();
if (CronTaskService is not null)
{
stopTasks.Add(CronTaskService.StopAsync(cancellationToken));
}
if (EventBusService is not null)
{
stopTasks.Add(EventBusService.StopAsync(cancellationToken));
}
if (ExtendService is not null)
{
stopTasks.Add(ExtendService.StopAsync(cancellationToken));
}
await Task.WhenAll(stopTasks);
}
public async ValueTask DisposeAsync()
{
Logger.LogInformation("服务释放资源");
}
private void OnApplicationStarted()
{
if (_startupTask is not null)
{
return;
}
_startupTokenSource = new CancellationTokenSource();
_startupTask = RunStartupAsync(_startupTokenSource.Token);
}
private async Task RunStartupAsync(CancellationToken cancellationToken)
{
try
{
Logger.LogInformation("[{Name} V {Version}]", Session.AssemblyName.Name, Session.AssemblyName.Version);
if (AppSettings.Scheduler.StartupDueTime > 0)
{
Logger.LogInformation("启动延迟:{Delay} 毫秒", AppSettings.Scheduler.StartupDueTime);
await Task.Delay(AppSettings.Scheduler.StartupDueTime, cancellationToken);
}
Logger.LogInformation("--------初始化--------");
InitializeCache();
InitializeService();
Logger.LogInformation("--------启动--------");
await Task.WhenAll(
ExtendService.StartAsync(cancellationToken),
EventBusService.StartAsync(cancellationToken),
CronTaskService.StartAsync(cancellationToken));
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
Logger.LogInformation("--------取消--------");
}
catch (Exception ex)
{
Logger.LogCritical(ex, "错误");
}
}
public void InitializeCache()
{
ServiceProvider.GetScopeService<IDataService>().GetConfigToDto<ConfigServiceDto>(CacheKey.Setting.ConfigService);
}
public void InitializeService()
{
ExtendService = ServiceProvider.GetRequiredService<ExtendService>();
EventBusService = ServiceProvider.GetRequiredService<EventBusService>();
CronTaskService = ServiceProvider.GetRequiredService<CronTaskService>();
}
}
@@ -0,0 +1,91 @@
using FASS.Scheduler.Models;
using FASS.Scheduler.Services.CronTasks.Jobs;
using Quartz;
namespace FASS.Scheduler.Services.CronTasks
{
public class CronTaskService
{
public ILogger<CronTaskService> Logger { get; }
public AppSettings AppSettings { get; }
public IServiceProvider ServiceProvider { get; }
private IScheduler? _scheduler;
private static readonly JobKey DefaultJobKey = new("defaultJob", "defaultGroup");
private static readonly TriggerKey DefaultTriggerKey = new("defaultTrigger", "defaultGroup");
public CronTaskService(
ILogger<CronTaskService> logger,
AppSettings appSettings,
IServiceProvider serviceProvider)
{
Logger = logger;
AppSettings = appSettings;
ServiceProvider = serviceProvider;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
if (!AppSettings.Frame.CronTask.IsEnable)
{
Logger.LogInformation("定时任务未启用");
return;
}
try
{
var factory = ServiceProvider.GetRequiredService<ISchedulerFactory>();
_scheduler ??= await factory.GetScheduler(cancellationToken);
if (!_scheduler.IsStarted)
{
await _scheduler.Start(cancellationToken);
}
if (!await _scheduler.CheckExists(DefaultJobKey, cancellationToken))
{
var job = JobBuilder.Create<DefaultJob>()
.WithIdentity(DefaultJobKey)
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity(DefaultTriggerKey)
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(10)
.RepeatForever())
.Build();
await _scheduler.ScheduleJob(job, trigger, cancellationToken);
}
Logger.LogInformation("定时任务已启动");
}
catch (Exception ex)
{
Logger.LogError(ex, "错误");
}
}
public async Task StopAsync(CancellationToken cancellationToken)
{
if (!AppSettings.Frame.CronTask.IsEnable)
{
Logger.LogInformation("定时任务未启用");
return;
}
try
{
if (_scheduler is not null && !_scheduler.IsShutdown)
{
await _scheduler.Shutdown(cancellationToken);
}
Logger.LogInformation("定时任务已停止");
}
catch (Exception ex)
{
Logger.LogError(ex, "错误");
}
}
}
}
@@ -0,0 +1,22 @@
using Quartz;
namespace FASS.Scheduler.Services.CronTasks.Jobs
{
public class DefaultJob : IJob
{
public ILogger<DefaultJob> Logger { get; }
public DefaultJob(
ILogger<DefaultJob> logger)
{
Logger = logger;
}
public Task Execute(IJobExecutionContext context)
{
Logger.LogInformation("当前时间:[{DateTimeNow}]", DateTime.Now);
return Task.CompletedTask;
}
}
}
@@ -0,0 +1,61 @@
using DotNetCore.CAP;
using FASS.Scheduler.Models;
using FASS.Scheduler.Services.EventBus.Subscribes;
namespace FASS.Scheduler.Services.EventBus
{
public class EventBusService : ICapSubscribe
{
public ILogger<EventBusService> Logger { get; }
public AppSettings AppSettings { get; }
public IServiceProvider ServiceProvider { get; }
public DefaultSubscribe DefaultSubscribe { get; } = null!;
public EventBusService(
ILogger<EventBusService> logger,
AppSettings appSettings,
IServiceProvider serviceProvider)
{
Logger = logger;
AppSettings = appSettings;
ServiceProvider = serviceProvider;
}
public Task StartAsync(CancellationToken cancellationToken)
{
if (!AppSettings.Frame.EventBus.IsEnable)
{
Logger.LogInformation("事件总线未启用");
return Task.CompletedTask;
}
try
{
Logger.LogInformation("事件总线已启动");
}
catch (Exception ex)
{
Logger.LogError(ex, "错误");
}
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
if (!AppSettings.Frame.EventBus.IsEnable)
{
Logger.LogInformation("事件总线未启用");
return Task.CompletedTask;
}
try
{
Logger.LogInformation("事件总线已停止");
}
catch (Exception ex)
{
Logger.LogError(ex, "错误");
}
return Task.CompletedTask;
}
}
}
@@ -0,0 +1,27 @@
using DotNetCore.CAP;
namespace FASS.Scheduler.Services.EventBus.Subscribes
{
public class DefaultSubscribe : ICapSubscribe
{
public EventBusService EventBusService { get; }
public DefaultSubscribe(
EventBusService eventBusService)
{
EventBusService = eventBusService;
}
[CapSubscribe("CarController.Lock")]
public void CarControllerLock(string json)
{
}
[CapSubscribe("CarController.UnLock")]
public void CarControllerUnLock(string json)
{
}
}
}
@@ -0,0 +1,123 @@
using Common.NETCore;
using Common.NETCore.Helpers;
using ComClient = Common.Net.Com.ComClient;
namespace FASS.Scheduler.Services.Extends.Demo
{
public class ExtendComClientService
{
public ExtendService ExtendService { get; }
public bool IsRunning { get; private set; }
private readonly ComClient _comClient;
public ExtendComClientService(
ExtendService extendService)
{
ExtendService = extendService;
var comClientPortName = Guard.NotNull(ExtendService.AppSettings.Extend.ComClientPortName);
_comClient = new ComClient() { PortName = comClientPortName };
_comClient.Opened += ComClient_Opened;
_comClient.Closed += ComClient_Closed;
_comClient.Writed += ComClient_Writed;
_comClient.Readed += ComClient_Readed;
}
public void Start()
{
try
{
if (IsRunning)
{
return;
}
IsRunning = true;
_comClient.OpenAndRead();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
public void Stop()
{
try
{
if (!IsRunning)
{
return;
}
IsRunning = false;
_comClient.Close();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
private void ComClient_Opened(ComClient client)
{
Task.Run(() => KeepaliveAsync(client));
ExtendService.Logger.LogInformation("串口客户端已打开:端口[{PortName}] 波特率[{BaudRate}]。", client.Client.PortName, client.Client.BaudRate);
}
private void ComClient_Closed(ComClient client)
{
Task.Run(() => ReconnectAsync(client));
ExtendService.Logger.LogInformation("串口客户端已关闭。");
}
private void ComClient_Writed(ComClient client, byte[] data)
{
ExtendService.Logger.LogInformation("串口客户端已发送:端口[{PortName}] 波特率[{BaudRate}] 数据[{Data}]。", client.Client.PortName, client.Client.BaudRate, ByteHelper.ByteArrayToHexString(data));
}
private void ComClient_Readed(ComClient client, byte[] data)
{
ExtendService.Logger.LogInformation("串口客户端已接收:端口[{PortName}] 波特率[{BaudRate}] 数据[{Data}]。", client.Client.PortName, client.Client.BaudRate, ByteHelper.ByteArrayToHexString(data));
_comClient.Write(data);
}
private async Task KeepaliveAsync(ComClient client)
{
while (IsRunning && client.IsOpen)
{
try
{
byte[] sendByteArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
client.Write(sendByteArray);
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
finally
{
await Task.Delay(500);
}
}
}
private async Task ReconnectAsync(ComClient client)
{
while (IsRunning && !client.IsOpen)
{
try
{
client.OpenAndRead();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
finally
{
await Task.Delay(5000);
}
}
}
}
}
@@ -0,0 +1,96 @@
using Common.NETCore;
using HttpClient = Common.Net.Http.HttpClient;
namespace FASS.Scheduler.Services.Extends.Demo
{
public class ExtendHttpClientService
{
public ExtendService ExtendService { get; }
public bool IsRunning { get; private set; }
private readonly HttpClient _httpClient;
public ExtendHttpClientService(
ExtendService extendService)
{
ExtendService = extendService;
var httpClientBaseAddress = Guard.NotNull(ExtendService.AppSettings.Extend.HttpClientBaseAddress);
_httpClient = new HttpClient() { BaseAddress = new Uri(httpClientBaseAddress) };
}
public void Start()
{
try
{
if (IsRunning)
{
return;
}
IsRunning = true;
Task.Run(Keepalive);
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
public void Stop()
{
try
{
if (!IsRunning)
{
return;
}
IsRunning = false;
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
public async Task HttpGetAsync(object? param = null)
{
var response = await _httpClient.GetAsTextAsync("/test/get", param);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
ExtendService.Logger.LogInformation("HTTP GET 响应:[{Result}]。", result);
}
public async Task HttpPostAsync(object? param = null)
{
var response = await _httpClient.PostAsTextAsync("/test/post", param);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
ExtendService.Logger.LogInformation("HTTP POST 响应:[{Result}]。", result);
}
private async Task Keepalive()
{
while (true)
{
if (!IsRunning)
{
break;
}
try
{
var message = "ACK";
await HttpPostAsync(new { data = message });
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
finally
{
await Task.Delay(500);
}
}
}
}
}
@@ -0,0 +1,163 @@
using Common.NETCore.Extensions;
using Common.NETCore.Models;
using System.Net;
using System.Text;
using HttpServer = Common.Net.Http.HttpServer;
namespace FASS.Scheduler.Services.Extends.Demo
{
public class ExtendHttpServerService
{
public ExtendService ExtendService { get; }
public bool IsRunning { get; private set; }
private readonly HttpServer _httpServer;
public ExtendHttpServerService(
ExtendService extendService)
{
ExtendService = extendService;
_httpServer = new HttpServer();
_httpServer.Prefixes = ExtendService.AppSettings.Extend.HttpServerPrefixes;
_httpServer.Started += HttpServer_Started;
_httpServer.Stopped += HttpServer_Stopped;
_httpServer.Method += HttpServer_Method;
_httpServer.Get += HttpServer_Get;
_httpServer.Post += HttpServer_Post;
}
public void Start()
{
try
{
if (IsRunning)
{
return;
}
IsRunning = true;
_httpServer.StartAndAccept();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
public void Stop()
{
try
{
if (!IsRunning)
{
return;
}
IsRunning = false;
_httpServer.Stop();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
private void HttpServer_Started(HttpServer server)
{
ExtendService.Logger.LogInformation("HTTP 服务端已启动:监听[{Prefixes}]。", string.Join(',', server.Server.Prefixes));
}
private void HttpServer_Stopped(HttpServer server)
{
ExtendService.Logger.LogInformation("HTTP 服务端已停止。");
if (!IsRunning)
{
return;
}
_ = Task.Run(async () =>
{
await Task.Delay(3000);
if (IsRunning)
{
server.Start();
}
});
}
private void HttpServer_Method(HttpServer server, HttpListenerContext context, string data)
{
ExtendService.Logger.LogInformation("HTTP 请求:方法[{Method}] 地址[{Url}] 数据:{Data}", context.Request.HttpMethod, context.Request.RawUrl, data);
}
private void HttpServer_Get(HttpServer server, HttpListenerContext context, string data)
{
var responseResult = new ResponseResult();
responseResult.Success = true;
responseResult.Data = data;
SendResponse(context, responseResult);
}
private void HttpServer_Post(HttpServer server, HttpListenerContext context, string data)
{
var responseResult = new ResponseResult();
if (context.Request.RawUrl is null) return;
try
{
if (context.Request.RawUrl.Equals("/agv/carState", StringComparison.OrdinalIgnoreCase))
{
var requestJson = data.JsonParseDocument();
if (!requestJson.RootElement.TryGetProperty("carCode", out var carCodeJson))
{
responseResult.Success = false;
responseResult.Message = "获取参数失败 [carCode]";
SendResponse(context, responseResult);
return;
}
var carCode = carCodeJson.GetString();
if (string.IsNullOrWhiteSpace(carCode))
{
responseResult.Success = true;
responseResult.Data = Enumerable.Range(0, 10).Select(e => e.ToString()).ToList();
SendResponse(context, responseResult);
return;
}
var car = Enumerable.Range(0, 10).Select(e => e.ToString()).FirstOrDefault(e => e == carCode);
if (car is null)
{
responseResult.Success = false;
responseResult.Message = $"获取车辆失败 [{carCode}]";
SendResponse(context, responseResult);
return;
}
responseResult.Success = true;
responseResult.Data = car.ToString();
SendResponse(context, responseResult);
return;
}
else
{
responseResult.Success = false;
responseResult.Message = "无效接口";
SendResponse(context, responseResult);
return;
}
}
catch (Exception ex)
{
responseResult.Success = false;
responseResult.Message = ex.Message;
SendResponse(context, responseResult);
return;
}
}
public void SendResponse(HttpListenerContext context, ResponseResult responseResult)
{
ExtendService.Logger.LogInformation("HTTP 响应:方法[{Method}] 地址[{Url}] 数据:{Data}", context.Request.HttpMethod, context.Request.RawUrl, responseResult.ToJson());
context.Response.StatusCode = 200;
context.Response.ContentType = "application/json;charset=UTF-8";
context.Response.ContentEncoding = Encoding.UTF8;
context.Response.OutputStream.Write(Encoding.UTF8.GetBytes(responseResult.ToJson()));
context.Response.OutputStream.Close();
}
}
}
@@ -0,0 +1,123 @@
using Common.NETCore;
using Common.NETCore.Helpers;
using System.Net;
using TcpClient = Common.Net.Tcp.TcpClient;
namespace FASS.Scheduler.Services.Extends.Demo
{
public class ExtendTcpClientService
{
public ExtendService ExtendService { get; }
public bool IsRunning { get; private set; }
private readonly TcpClient _tcpClient;
public ExtendTcpClientService(
ExtendService eventService)
{
ExtendService = eventService;
var tcpClientRemoteIP = Guard.NotNull(ExtendService.AppSettings.Extend.TcpClientRemoteIP);
_tcpClient = new TcpClient() { RemoteEndPoint = IPEndPoint.Parse(tcpClientRemoteIP) };
_tcpClient.Connected += TcpClient_Connected;
_tcpClient.Disconnected += TcpClient_Disconnected;
_tcpClient.Sent += TcpClient_Sent;
_tcpClient.Received += TcpClient_Received;
}
public void Start()
{
try
{
if (IsRunning)
{
return;
}
IsRunning = true;
_tcpClient.ConnectAndReceive();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
public void Stop()
{
try
{
if (!IsRunning)
{
return;
}
IsRunning = false;
_tcpClient.Disconnect();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
private void TcpClient_Connected(TcpClient client)
{
Task.Run(() => KeepaliveAsync(client));
ExtendService.Logger.LogInformation("TCP 客户端已连接:本地[{LocalEndPoint}] 远端[{RemoteEndPoint}]。", client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
}
private void TcpClient_Disconnected(TcpClient client)
{
Task.Run(() => ReconnectAsync(client));
ExtendService.Logger.LogInformation("TCP 客户端已断开。");
}
private void TcpClient_Sent(TcpClient client, byte[] data)
{
ExtendService.Logger.LogInformation("TCP 客户端已发送:本地[{LocalEndPoint}] 远端[{RemoteEndPoint}] 数据[{Data}]。", client.Client.LocalEndPoint, client.Client.RemoteEndPoint, ByteHelper.ByteArrayToHexString(data));
}
private void TcpClient_Received(TcpClient client, byte[] data)
{
ExtendService.Logger.LogInformation("TCP 客户端已接收:本地[{LocalEndPoint}] 远端[{RemoteEndPoint}] 数据[{Data}]。", client.Client.LocalEndPoint, client.Client.RemoteEndPoint, ByteHelper.ByteArrayToHexString(data));
}
private async Task KeepaliveAsync(TcpClient client)
{
while (IsRunning && client.IsConnected)
{
try
{
byte[] sendByteArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
client.Send(sendByteArray);
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
finally
{
await Task.Delay(500);
}
}
}
private async Task ReconnectAsync(TcpClient client)
{
while (IsRunning && !client.IsConnected)
{
try
{
client.ConnectAndReceive();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
finally
{
await Task.Delay(5000);
}
}
}
}
}
@@ -0,0 +1,102 @@
using Common.Net.Tcp;
using Common.NETCore;
using Common.NETCore.Helpers;
using System.Net;
using TcpServer = Common.Net.Tcp.TcpServer;
namespace FASS.Scheduler.Services.Extends.Demo
{
public class ExtendTcpServerService
{
public ExtendService ExtendService { get; }
public bool IsRunning { get; private set; }
private readonly TcpServer _tcpServer;
public ExtendTcpServerService(
ExtendService eventService)
{
ExtendService = eventService;
var tcpServerLocalIP = Guard.NotNull(ExtendService.AppSettings.Extend.TcpServerLocalIP);
_tcpServer = new TcpServer() { LocalEndPoint = IPEndPoint.Parse(tcpServerLocalIP) };
_tcpServer.Started += TcpServer_Started;
_tcpServer.Stopped += TcpServer_Stopped;
_tcpServer.Accepted += TcpServer_Accepted;
}
public void Start()
{
try
{
if (IsRunning)
{
return;
}
IsRunning = true;
_tcpServer.StartAndAccept();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
public void Stop()
{
try
{
if (!IsRunning)
{
return;
}
IsRunning = false;
_tcpServer.Stop();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
private void TcpServer_Started(TcpServer server)
{
ExtendService.Logger.LogInformation("TCP 服务端已启动:本地[{LocalEndPoint}]。", server.Server.LocalEndPoint);
}
private void TcpServer_Stopped(TcpServer server)
{
ExtendService.Logger.LogInformation("TCP 服务端已停止。");
}
private void TcpServer_Accepted(TcpServer server, TcpClient client)
{
ExtendService.Logger.LogInformation("TCP 服务端已接入连接:本地[{LocalEndPoint}] 远端[{RemoteEndPoint}]。", server.Server.LocalEndPoint, client.Client.LocalEndPoint);
client.Connected += Client_Connected;
client.Disconnected += Client_Disconnected;
client.Sent += Client_Sent;
client.Received += Client_Received;
}
private void Client_Connected(TcpClient client)
{
ExtendService.Logger.LogInformation("TCP 会话已连接:本地[{LocalEndPoint}] 远端[{RemoteEndPoint}]。", client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
}
private void Client_Disconnected(TcpClient client)
{
ExtendService.Logger.LogInformation("TCP 会话已断开。");
}
private void Client_Sent(TcpClient client, byte[] data)
{
ExtendService.Logger.LogInformation("TCP 会话已发送:本地[{LocalEndPoint}] 远端[{RemoteEndPoint}] 数据[{Data}]。", client.Client.LocalEndPoint, client.Client.RemoteEndPoint, ByteHelper.ByteArrayToHexString(data));
}
private void Client_Received(TcpClient client, byte[] data)
{
ExtendService.Logger.LogInformation("TCP 会话已接收:本地[{LocalEndPoint}] 远端[{RemoteEndPoint}] 数据[{Data}]。", client.Client.LocalEndPoint, client.Client.RemoteEndPoint, ByteHelper.ByteArrayToHexString(data));
client.Send(data);
}
}
}
@@ -0,0 +1,133 @@
using Common.NETCore;
using Common.NETCore.Helpers;
using System.Net;
using UdpServer = Common.Net.Udp.UdpServer;
namespace FASS.Scheduler.Services.Extends.Demo
{
public class ExtendUdpServerService
{
public ExtendService ExtendService { get; }
public bool IsRunning { get; private set; }
private readonly UdpServer _udpServer;
public ExtendUdpServerService(
ExtendService eventService)
{
ExtendService = eventService;
var udpServerLocalIP = Guard.NotNull(ExtendService.AppSettings.Extend.UdpServerLocalIP);
var udpServerRemoteIP = Guard.NotNull(ExtendService.AppSettings.Extend.UdpServerRemoteIP);
_udpServer = new UdpServer
{
LocalEndPoint = IPEndPoint.Parse(udpServerLocalIP),
RemoteEndPoint = IPEndPoint.Parse(udpServerRemoteIP)
};
_udpServer.Started += UdpServer_Started;
_udpServer.Stopped += UdpServer_Stopped;
_udpServer.Sent += UdpServer_Sent;
_udpServer.Received += UdpServer_Received;
}
public void Start()
{
try
{
if (IsRunning)
{
return;
}
IsRunning = true;
_udpServer.StartAndReceive();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
public void Stop()
{
try
{
if (!IsRunning)
{
return;
}
IsRunning = false;
_udpServer.Stop();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
}
private void UdpServer_Started(UdpServer server)
{
Task.Run(() => KeepaliveAsync(server));
ExtendService.Logger.LogInformation("UDP 服务端已启动:本地[{LocalEndPoint}]。", server.Server.LocalEndPoint);
}
private void UdpServer_Stopped(UdpServer server)
{
if (!IsRunning)
{
return;
}
Task.Run(() => ReconnectAsync(server));
ExtendService.Logger.LogInformation("UDP 服务端已停止。");
}
private void UdpServer_Sent(UdpServer server, byte[] data, EndPoint point)
{
ExtendService.Logger.LogInformation("UDP 服务端已发送:本地[{LocalEndPoint}] 远端[{RemoteEndPoint}] 数据[{Data}]。", server.Server.LocalEndPoint, point, ByteHelper.ByteArrayToHexString(data));
}
private void UdpServer_Received(UdpServer server, byte[] data, EndPoint point)
{
ExtendService.Logger.LogInformation("UDP 服务端已接收:本地[{LocalEndPoint}] 远端[{RemoteEndPoint}] 数据[{Data}]。", server.Server.LocalEndPoint, server.Server.RemoteEndPoint, ByteHelper.ByteArrayToHexString(data));
server.Send(data, point);
}
private async Task KeepaliveAsync(UdpServer server)
{
while (IsRunning && server.IsRunning)
{
try
{
byte[] sendByteArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
server.Send(sendByteArray);
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
finally
{
await Task.Delay(500);
}
}
}
private async Task ReconnectAsync(UdpServer server)
{
while (IsRunning && !server.IsRunning)
{
try
{
server.StartAndReceive();
}
catch (Exception ex)
{
ExtendService.Logger.LogError(ex, "错误");
}
finally
{
await Task.Delay(5000);
}
}
}
}
}
@@ -0,0 +1,126 @@
using FASS.Scheduler.Models;
using FASS.Scheduler.Services.Extends.Demo;
namespace FASS.Scheduler.Services.Extends
{
public class ExtendService
{
public ILogger<ExtendService> Logger { get; }
public AppSettings AppSettings { get; }
public IServiceProvider ServiceProvider { get; }
public ExtendComClientService ExtendComClientService { get; } = null!;
public ExtendHttpClientService ExtendHttpClientService { get; } = null!;
public ExtendHttpServerService ExtendHttpServerService { get; } = null!;
public ExtendTcpClientService ExtendTcpClientService { get; } = null!;
public ExtendTcpServerService ExtendTcpServerService { get; } = null!;
public ExtendUdpServerService ExtendUdpClientService { get; } = null!;
public ExtendService(
ILogger<ExtendService> logger,
AppSettings appSettings,
IServiceProvider serviceProvider)
{
Logger = logger;
AppSettings = appSettings;
ServiceProvider = serviceProvider;
if (AppSettings.Extend.EnableComClient)
{
ExtendComClientService = new ExtendComClientService(this);
}
if (AppSettings.Extend.EnableTcpClient)
{
ExtendTcpClientService = new ExtendTcpClientService(this);
}
if (AppSettings.Extend.EnableTcpServer)
{
ExtendTcpServerService = new ExtendTcpServerService(this);
}
if (AppSettings.Extend.EnableUdpServer)
{
ExtendUdpClientService = new ExtendUdpServerService(this);
}
if (AppSettings.Extend.EnableHttpClient)
{
ExtendHttpClientService = new ExtendHttpClientService(this);
}
if (AppSettings.Extend.EnableHttpServer)
{
ExtendHttpServerService = new ExtendHttpServerService(this);
}
}
public Task StartAsync(CancellationToken cancellationToken)
{
try
{
if (AppSettings.Extend.EnableComClient)
{
ExtendComClientService.Start();
}
if (AppSettings.Extend.EnableTcpClient)
{
ExtendTcpClientService.Start();
}
if (AppSettings.Extend.EnableTcpServer)
{
ExtendTcpServerService.Start();
}
if (AppSettings.Extend.EnableUdpServer)
{
ExtendUdpClientService.Start();
}
if (AppSettings.Extend.EnableHttpClient)
{
ExtendHttpClientService.Start();
}
if (AppSettings.Extend.EnableHttpServer)
{
ExtendHttpServerService.Start();
}
}
catch (Exception ex)
{
Logger.LogError(ex, "扩展服务启动失败");
}
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
try
{
if (AppSettings.Extend.EnableComClient)
{
ExtendComClientService.Stop();
}
if (AppSettings.Extend.EnableTcpClient)
{
ExtendTcpClientService.Stop();
}
if (AppSettings.Extend.EnableTcpServer)
{
ExtendTcpServerService.Stop();
}
if (AppSettings.Extend.EnableUdpServer)
{
ExtendUdpClientService.Stop();
}
if (AppSettings.Extend.EnableHttpClient)
{
ExtendHttpClientService.Stop();
}
if (AppSettings.Extend.EnableHttpServer)
{
ExtendHttpServerService.Stop();
}
}
catch (Exception ex)
{
Logger.LogError(ex, "扩展服务停止失败");
}
return Task.CompletedTask;
}
}
}
@@ -0,0 +1,21 @@
namespace FASS.Scheduler.Utility
{
public static class CacheKey
{
public static class Login
{
public static string Captcha => $"LoginCaptcha{Guid.NewGuid()}";
}
public static class Setting
{
public static string Config => "SettingConfig";
public static string DictItem => "SettingDictItem";
public static string ConfigData => "SettingConfigData";
public static string ConfigService => "SettingConfigService";
}
public static class Dashboard
{
public static string Home(string username) => $"DashboardHome{username}";
}
}
}
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
@@ -0,0 +1,131 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.AspNetCore": "Debug",
"Microsoft.Hosting.Lifetime": "Debug",
"Microsoft.EntityFrameworkCore": "Debug",
"Grpc": "Debug"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Endpoints": {
"Default": {
"Url": "http://localhost:20101"
},
"Web": {
"Url": "http://*:20101"
},
"Grpc": {
"Url": "http://*:20201",
"Protocols": "Http2"
}
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.Debug", "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft.AspNetCore": "Warning",
"Microsoft.Hosting.Lifetime": "Warning",
"Microsoft.EntityFrameworkCore": "Warning"
}
},
"WriteTo": [
{ "Name": "Debug" },
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"shared": true,
"path": "Logs/log.txt",
"rollingInterval": "Day",
"fileSizeLimitBytes": "104857600",
"rollOnFileSizeLimit": true,
"retainedFileTimeLimit": "90.00:00:00",
"retainedFileCountLimit": "100",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level:u3}] {Message:lj} [{SourceContext}]{NewLine}{Exception}"
}
}
]
},
"Rate": {
"PermitLimit": 1,
"QueueLimit": 0,
"WindowMilliseconds": 100
},
"Auth": {
"SigningKey": "12345678123456781234567812345678",
"Issuer": "12345678",
"Audience": "12345678",
"ExpireSeconds": 86400
},
"App": {
"ActivationCode": "592AF4AF3F7220EEF6F36BCD3A13E9B0ED5D4DC3F005F6D2246764DAF89F09AF9DEC5D4980D3C37F2E6AE2549C1419E9E7523855BAFB9EEE1C87A9678F2D78B00B86FDA6F90E982954B2D6822FF9CF2B4A5021C2D0BF1293EC952EAE33C81965DA6CAEB2F8A6DCC666BA69942C1F28A97FF803E72D84519AC8AD0F48F3437045408265F3EFA3622B356E08266D111F40"
},
"Frame": {
"Database": {
"IsEnable": true,
//Provider 支持 SqlServer/PostgreSql/Sqlite
"Provider": "PostgreSql",
//PostgreSql 示例
"ConnectionString": "Server=127.0.0.1;Port=5432;Database=fass.lite;Username=postgres;Password=123456;Pooling=true",
"EnableSplitQuery": true,
"EnableChecks": false,
"EnableSensitiveDataLogging": false,
"EnableDetailedErrors": false,
"EnableDataAudit": false
},
"Cache": {
"IsEnable": true,
//Provider 支持 Memory/Redis
"Provider": "Memory"
//Redis 示例
//"ConnectionString": "127.0.0.1:6379,ssl=false,defaultDatabase=0,connectTimeout=5000,abortConnect=false"
},
"EventBus": { //Memory 模式无法跨进程
"IsEnable": true,
//StorageProvider 支持 Memory/SqlServer/PostgreSql
"StorageProvider": "Memory",
//PostgreSql 示例
//"StorageConnectionString": "Server=127.0.0.1;Port=5432;Database=fass.lite;Username=postgres;Password=123456;Pooling=true",
//TransportProvider 支持 Memory/RabbitMQ/Kafka/Redis
"TransportProvider": "Memory"
//Redis 示例
//"TransportConnectionString": "127.0.0.1:6379,ssl=false,defaultDatabase=0,connectTimeout=5000,abortConnect=false"
},
"CronTask": {
"IsEnable": false,
//Provider 支持 Memory/SqlServer/PostgreSql/Sqlite
"Provider": "Memory"
//PostgreSql 示例
//"ConnectionString": "Server=127.0.0.1;Port=5432;Database=fass.lite;Username=postgres;Password=123456;Pooling=true"
}
},
"Scheduler": {
"StartupDueTime": 1000
},
"Service": {
"TcpServerLocalIP": "0.0.0.0:20102",
"UdpServerLocalIP": "0.0.0.0:20103"
},
"Extend": {
"EnableComClient": false,
"ComClientPortName": "COM1",
"EnableTcpClient": false,
"TcpClientRemoteIP": "127.0.0.1:10001",
"EnableTcpServer": false,
"TcpServerLocalIP": "127.0.0.1:20001",
"EnableUdpServer": false,
"UdpServerRemoteIP": "127.0.0.1:10002",
"UdpServerLocalIP": "127.0.0.1:20002",
"EnableHttpClient": false,
"HttpClientBaseAddress": "http://localhost:10101/",
"EnableHttpServer": false,
"HttpServerPrefixes": [ "http://localhost:20102/" ]
}
}
@@ -0,0 +1,20 @@
namespace FASS.Service.Consts.Core
{
public class AppConst
{
public class App
{
public const string Name = "FASS";
}
public class Cors
{
public const string Name = "Default";
}
public class Rate
{
public const string Name = "Default";
}
}
}
@@ -0,0 +1,19 @@
namespace FASS.Service.Consts.Custom
{
public struct DemoConst
{
public struct Type
{
public const string Type1 = "Type1";
public const string Type2 = "Type2";
public const string Type3 = "Type3";
}
public struct State
{
public const string State1 = "State1";
public const string State2 = "State2";
public const string State3 = "State3";
}
}
}
@@ -0,0 +1,19 @@
namespace FASS.Service.Consts.Record
{
public class AlarmConst
{
public class Level
{
public const string Debug = "Debug";
public const string Information = "Information";
public const string Warning = "Warning";
public const string Error = "Error";
}
public class Type
{
public const string None = "None";
public const string CarAlarm = "CarAlarm";
}
}
}
@@ -0,0 +1,19 @@
namespace FASS.Service.Consts.Record
{
public class DiaryConst
{
public class Level
{
public const string Debug = "Debug";
public const string Information = "Information";
public const string Warning = "Warning";
public const string Error = "Error";
}
public class Type
{
public const string None = "None";
public const string CarState = "CarState";
}
}
}
@@ -0,0 +1,14 @@
namespace FASS.Service.Consts.Warehouse
{
public class AreaConst
{
public class Type
{
public const string Default = "Default";
}
public class State
{
public const string Default = "Default";
}
}
}
@@ -0,0 +1,15 @@
namespace FASS.Service.Consts.Warehouse
{
public class ContainerConst
{
public class Type
{
public const string Default = "Default";
}
public class State
{
public const string EmptyMaterial = "EmptyMaterial";
public const string FullMaterial = "FullMaterial";
}
}
}
@@ -0,0 +1,11 @@
namespace FASS.Service.Consts.Warehouse
{
public class ContainerMaterialHistoryConst
{
public class State
{
public const string Add = "Add";
public const string Delete = "Delete";
}
}
}
@@ -0,0 +1,15 @@
namespace FASS.Service.Consts.Warehouse
{
public class MaterialConst
{
public class Type
{
public const string Default = "Default";
}
public class State
{
public const string Bind = "Bind";
public const string UnBind = "UnBind";
}
}
}
@@ -0,0 +1,11 @@
namespace FASS.Service.Consts.Warehouse
{
public class MaterialStorageHistoryConst
{
public class State
{
public const string Add = "Add";
public const string Delete = "Delete";
}
}
}
@@ -0,0 +1,16 @@
namespace FASS.Service.Consts.Warehouse
{
public class StorageConst
{
public class Type
{
public const string Default = "Default";
}
public class State
{
public const string NoneContainer = "NoneContainer";
public const string EmptyContainer = "EmptyContainer";
public const string FullContainer = "FullContainer";
}
}
}
@@ -0,0 +1,11 @@
namespace FASS.Service.Consts.Warehouse
{
public class StorageContainerHistoryConst
{
public class State
{
public const string Add = "Add";
public const string Delete = "Delete";
}
}
}
@@ -0,0 +1,43 @@
namespace FASS.Service.Consts.Warehouse
{
public class WorkConst
{
public class Type
{
public const string Normal = "Normal";
}
public class State
{
public const string Created = "Created";
public const string Released = "Released";
public const string Distributed = "Distributed";
public const string Running = "Running";
public const string Pausing = "Pausing";
public const string Paused = "Paused";
public const string Resuming = "Resuming";
public const string Resumed = "Resumed";
public const string Completing = "Completing";
public const string Canceling = "Canceling";
public const string Faulting = "Faulting";
public const string Completed = "Completed";
public const string Canceled = "Canceled";
public const string Faulted = "Faulted";
public static readonly string[] Update = [Created];
public static readonly string[] Release = [Created];
public static readonly string[] Delete = [Created, Completed, Canceled, Faulted];
public static readonly string[] Pause = [Running];
public static readonly string[] Resume = [Paused];
public static readonly string[] Cancel = [Running, Paused, Resumed];
public static readonly string[] Distribute = [Released];
public static readonly string[] Start = [Created, Released];
public static readonly string[] Execute = [Distributed, Running, Pausing, Paused, Resuming, Resumed, Completing, Canceling, Faulting];
public static readonly string[] Stop = [Completed, Canceled, Faulted];
}
}
}
@@ -0,0 +1,13 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Custom
{
public class DemoDto : AuditDto
{
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Custom.Validators
{
public class DemoDtoValidator : AuditDtoValidator<DemoDto>
{
public DemoDtoValidator()
{
}
}
}
@@ -0,0 +1,17 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Record
{
public class AlarmDto : AuditDto
{
public required string Level { get; set; }
public required string Type { get; set; }
public string? Code { get; set; }
public string? State { get; set; }
public string? Message { get; set; }
public string? Data { get; set; }
public int Count { get; set; } = 1;
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
}
}
@@ -0,0 +1,17 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Record
{
public class DiaryDto : AuditDto
{
public required string Level { get; set; }
public required string Type { get; set; }
public string? Code { get; set; }
public string? State { get; set; }
public string? Message { get; set; }
public string? Data { get; set; }
public int Count { get; set; } = 1;
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Record.Validators
{
public class AlarmDtoValidator : AuditDtoValidator<AlarmDto>
{
public AlarmDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Record.Validators
{
public class DiaryDtoValidator : AuditDtoValidator<DiaryDto>
{
public DiaryDtoValidator()
{
}
}
}
@@ -0,0 +1,9 @@
namespace FASS.Service.Dtos.Setting
{
public class ConfigServiceDto
{
public string? Item1 { get; set; }
public string? Item2 { get; set; }
public string? Item3 { get; set; }
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class AreaDto : AuditDto
{
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
}
}
@@ -0,0 +1,24 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class ContainerDto : AuditDto
{
public required string AreaId { get; set; }
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
public bool IsLock { get; set; }
public string? Barcode { get; set; }
public double Length { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public string? AreaCode { get; set; }
}
}
@@ -0,0 +1,10 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class ContainerMaterialDto : AuditDto
{
public required string ContainerId { get; set; }
public required string MaterialId { get; set; }
}
}
@@ -0,0 +1,15 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class ContainerMaterialHistoryDto : AuditDto
{
public required string ContainerId { get; set; }
public required string MaterialId { get; set; }
public required string State { get; set; }
public string? ContainerCode { get; set; }
public string? MaterialCode { get; set; }
}
}
@@ -0,0 +1,22 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class MaterialDto : AuditDto
{
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
public bool IsLock { get; set; }
public string? Barcode { get; set; }
public string? Batch { get; set; }
public string? Spec { get; set; }
public string? Unit { get; set; }
public int Quantity { get; set; }
}
}
@@ -0,0 +1,10 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class MaterialStorageDto : AuditDto
{
public required string MaterialId { get; set; }
public required string StorageId { get; set; }
}
}
@@ -0,0 +1,15 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class MaterialStorageHistoryDto : AuditDto
{
public required string MaterialId { get; set; }
public required string StorageId { get; set; }
public required string State { get; set; }
public string? MaterialCode { get; set; }
public string? StorageCode { get; set; }
}
}
@@ -0,0 +1,10 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class StorageContainerDto : AuditDto
{
public required string StorageId { get; set; }
public required string ContainerId { get; set; }
}
}
@@ -0,0 +1,15 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class StorageContainerHistoryDto : AuditDto
{
public required string StorageId { get; set; }
public required string ContainerId { get; set; }
public required string State { get; set; }
public string? StorageCode { get; set; }
public string? ContainerCode { get; set; }
}
}
@@ -0,0 +1,23 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class StorageDto : AuditDto
{
public required string AreaId { get; set; }
public required string NodeId { get; set; }
public required string NodeCode { get; set; }
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
public bool IsLock { get; set; }
public string? Barcode { get; set; }
public string? AreaCode { get; set; }
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class AreaDtoValidator : AuditDtoValidator<AreaDto>
{
public AreaDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class ContainerDtoValidator : AuditDtoValidator<ContainerDto>
{
public ContainerDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class ContainerMaterialDtoValidator : AuditDtoValidator<ContainerMaterialDto>
{
public ContainerMaterialDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class ContainerMaterialHistoryDtoValidator : AuditDtoValidator<ContainerMaterialHistoryDto>
{
public ContainerMaterialHistoryDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class MaterialDtoValidator : AuditDtoValidator<MaterialDto>
{
public MaterialDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class MaterialStorageDtoValidator : AuditDtoValidator<MaterialStorageDto>
{
public MaterialStorageDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class MaterialStorageHistoryDtoValidator : AuditDtoValidator<MaterialStorageHistoryDto>
{
public MaterialStorageHistoryDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class StorageContainerDtoValidator : AuditDtoValidator<StorageContainerDto>
{
public StorageContainerDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class StorageContainerHistoryDtoValidator : AuditDtoValidator<StorageContainerHistoryDto>
{
public StorageContainerHistoryDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class StorageDtoValidator : AuditDtoValidator<StorageDto>
{
public StorageDtoValidator()
{
}
}
}
@@ -0,0 +1,12 @@
using Common.Service.Dtos.Validators;
namespace FASS.Service.Dtos.Warehouse.Validators
{
public class WorkDtoValidator : AuditDtoValidator<WorkDto>
{
public WorkDtoValidator()
{
}
}
}
@@ -0,0 +1,19 @@
using Common.Service.Dtos;
namespace FASS.Service.Dtos.Warehouse
{
public class WorkDto : AuditDto
{
public required string ContainerId { get; set; }
public string? TaskId { get; set; }
public string? TaskCode { get; set; }
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
public string? ContainerCode { get; set; }
}
}
@@ -0,0 +1,12 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Custom
{
public class DemoEntity : AuditEntity
{
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
}
}
@@ -0,0 +1,23 @@
using Common.Service.Entities.Types;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace FASS.Service.Entities.Custom.Types
{
public class DemoEntityType : AuditEntityType<DemoEntity>
{
public override void Configure(EntityTypeBuilder<DemoEntity> builder)
{
base.Configure(builder);
builder.ToTable("custom_demo");
builder.Property(e => e.Code).HasColumnName("code").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.Name).HasColumnName("name").HasColumnType("varchar(50)");
builder.Property(e => e.Type).HasColumnName("type").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.State).HasColumnName("state").HasColumnType("varchar(50)").IsRequired();
builder.HasIndex(e => e.Code).IsUnique();
}
}
}
@@ -0,0 +1,17 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Record
{
public class AlarmEntity : AuditEntity
{
public required string Level { get; set; }
public required string Type { get; set; }
public string? Code { get; set; }
public string? State { get; set; }
public string? Message { get; set; }
public string? Data { get; set; }
public int Count { get; set; } = 1;
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
}
}
@@ -0,0 +1,17 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Record
{
public class DiaryEntity : AuditEntity
{
public required string Level { get; set; }
public required string Type { get; set; }
public string? Code { get; set; }
public string? State { get; set; }
public string? Message { get; set; }
public string? Data { get; set; }
public int Count { get; set; } = 1;
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
}
}
@@ -0,0 +1,28 @@
using Common.Service.Entities.Types;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace FASS.Service.Entities.Record.Types
{
public class AlarmEntityType : AuditEntityType<AlarmEntity>
{
public override void Configure(EntityTypeBuilder<AlarmEntity> builder)
{
base.Configure(builder);
builder.ToTable("record_alarm");
builder.Property(e => e.Level).HasColumnName("level").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.Type).HasColumnName("type").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.Code).HasColumnName("code").HasColumnType("varchar(50)");
builder.Property(e => e.State).HasColumnName("state").HasColumnType("varchar(50)");
builder.Property(e => e.Message).HasColumnName("message").HasColumnType("varchar(1000)");
builder.Property(e => e.Data).HasColumnName("data").HasColumnType("text");
builder.Property(e => e.Count).HasColumnName("count").HasColumnType("int4").IsRequired();
builder.Property(e => e.StartTime).HasColumnName("start_time").HasColumnType("timestamp");
builder.Property(e => e.EndTime).HasColumnName("end_time").HasColumnType("timestamp");
builder.HasIndex(e => e.Level);
builder.HasIndex(e => new { e.Level, e.Type, e.Code, e.State });
}
}
}
@@ -0,0 +1,28 @@
using Common.Service.Entities.Types;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace FASS.Service.Entities.Record.Types
{
public class DiaryEntityType : AuditEntityType<DiaryEntity>
{
public override void Configure(EntityTypeBuilder<DiaryEntity> builder)
{
base.Configure(builder);
builder.ToTable("record_diary");
builder.Property(e => e.Level).HasColumnName("level").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.Type).HasColumnName("type").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.Code).HasColumnName("code").HasColumnType("varchar(50)");
builder.Property(e => e.State).HasColumnName("state").HasColumnType("varchar(50)");
builder.Property(e => e.Message).HasColumnName("message").HasColumnType("varchar(1000)");
builder.Property(e => e.Data).HasColumnName("data").HasColumnType("text");
builder.Property(e => e.Count).HasColumnName("count").HasColumnType("int4").IsRequired();
builder.Property(e => e.StartTime).HasColumnName("start_time").HasColumnType("timestamp");
builder.Property(e => e.EndTime).HasColumnName("end_time").HasColumnType("timestamp");
builder.HasIndex(e => e.Level);
builder.HasIndex(e => new { e.Level, e.Type, e.Code, e.State });
}
}
}
@@ -0,0 +1,16 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Warehouse
{
public class AreaEntity : AuditEntity
{
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
public virtual ICollection<StorageEntity> Storages { get; set; } = [];
public virtual ICollection<ContainerEntity> Containers { get; set; } = [];
}
}
@@ -0,0 +1,32 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Warehouse
{
public class ContainerEntity : AuditEntity
{
public required string AreaId { get; set; }
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
public bool IsLock { get; set; }
public string? Barcode { get; set; }
public double Length { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public virtual AreaEntity Area { get; set; } = null!;
public virtual ICollection<StorageContainerEntity> StorageContainers { get; set; } = [];
public virtual ICollection<ContainerMaterialEntity> ContainerMaterials { get; set; } = [];
public virtual ICollection<StorageContainerHistoryEntity> StorageContainerHistorys { get; set; } = [];
public virtual ICollection<ContainerMaterialHistoryEntity> ContainerMaterialHistorys { get; set; } = [];
public virtual ICollection<WorkEntity> Works { get; set; } = [];
}
}
@@ -0,0 +1,13 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Warehouse
{
public class ContainerMaterialEntity : AuditEntity
{
public required string ContainerId { get; set; }
public required string MaterialId { get; set; }
public virtual ContainerEntity Container { get; set; } = null!;
public virtual MaterialEntity Material { get; set; } = null!;
}
}
@@ -0,0 +1,15 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Warehouse
{
public class ContainerMaterialHistoryEntity : AuditEntity
{
public required string ContainerId { get; set; }
public required string MaterialId { get; set; }
public required string State { get; set; }
public virtual ContainerEntity Container { get; set; } = null!;
public virtual MaterialEntity Material { get; set; } = null!;
}
}
@@ -0,0 +1,28 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Warehouse
{
public class MaterialEntity : AuditEntity
{
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
public bool IsLock { get; set; }
public string? Barcode { get; set; }
public string? Batch { get; set; }
public string? Spec { get; set; }
public string? Unit { get; set; }
public int Quantity { get; set; }
public virtual ICollection<ContainerMaterialEntity> ContainerMaterials { get; set; } = [];
public virtual ICollection<MaterialStorageEntity> MaterialStorages { get; set; } = [];
public virtual ICollection<ContainerMaterialHistoryEntity> ContainerMaterialHistorys { get; set; } = [];
public virtual ICollection<MaterialStorageHistoryEntity> MaterialStorageHistorys { get; set; } = [];
}
}
@@ -0,0 +1,13 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Warehouse
{
public class MaterialStorageEntity : AuditEntity
{
public required string MaterialId { get; set; }
public required string StorageId { get; set; }
public virtual MaterialEntity Material { get; set; } = null!;
public virtual StorageEntity Storage { get; set; } = null!;
}
}
@@ -0,0 +1,15 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Warehouse
{
public class MaterialStorageHistoryEntity : AuditEntity
{
public required string MaterialId { get; set; }
public required string StorageId { get; set; }
public required string State { get; set; }
public virtual MaterialEntity Material { get; set; } = null!;
public virtual StorageEntity Storage { get; set; } = null!;
}
}
@@ -0,0 +1,13 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Warehouse
{
public class StorageContainerEntity : AuditEntity
{
public required string StorageId { get; set; }
public required string ContainerId { get; set; }
public virtual StorageEntity Storage { get; set; } = null!;
public virtual ContainerEntity Container { get; set; } = null!;
}
}
@@ -0,0 +1,15 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Warehouse
{
public class StorageContainerHistoryEntity : AuditEntity
{
public required string StorageId { get; set; }
public required string ContainerId { get; set; }
public required string State { get; set; }
public virtual StorageEntity Storage { get; set; } = null!;
public virtual ContainerEntity Container { get; set; } = null!;
}
}
@@ -0,0 +1,29 @@
using Common.Service.Entities;
namespace FASS.Service.Entities.Warehouse
{
public class StorageEntity : AuditEntity
{
public required string AreaId { get; set; }
public required string NodeId { get; set; }
public required string NodeCode { get; set; }
public required string Code { get; set; }
public string? Name { get; set; }
public required string Type { get; set; }
public required string State { get; set; }
public bool IsLock { get; set; }
public string? Barcode { get; set; }
public virtual AreaEntity Area { get; set; } = null!;
public virtual ICollection<StorageContainerEntity> StorageContainers { get; set; } = [];
public virtual ICollection<MaterialStorageEntity> MaterialStorages { get; set; } = [];
public virtual ICollection<StorageContainerHistoryEntity> StorageContainerHistorys { get; set; } = [];
public virtual ICollection<MaterialStorageHistoryEntity> MaterialStorageHistorys { get; set; } = [];
}
}
@@ -0,0 +1,22 @@
using Common.Service.Entities.Types;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace FASS.Service.Entities.Warehouse.Types
{
public class AreaEntityType : AuditEntityType<AreaEntity>
{
public override void Configure(EntityTypeBuilder<AreaEntity> builder)
{
base.Configure(builder);
builder.ToTable("warehouse_area");
builder.Property(e => e.Code).HasColumnName("code").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.Name).HasColumnName("name").HasColumnType("varchar(50)");
builder.Property(e => e.Type).HasColumnName("type").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.State).HasColumnName("state").HasColumnType("varchar(50)").IsRequired();
builder.HasIndex(e => e.Code).IsUnique();
}
}
}
@@ -0,0 +1,35 @@
using Common.Service.Entities.Types;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace FASS.Service.Entities.Warehouse.Types
{
public class ContainerEntityType : AuditEntityType<ContainerEntity>
{
public override void Configure(EntityTypeBuilder<ContainerEntity> builder)
{
base.Configure(builder);
builder.ToTable("warehouse_container");
builder.Property(e => e.AreaId).HasColumnName("area_id").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.Code).HasColumnName("code").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.Name).HasColumnName("name").HasColumnType("varchar(50)");
builder.Property(e => e.Type).HasColumnName("type").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.State).HasColumnName("state").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.IsLock).HasColumnName("is_lock").HasColumnType("bool").IsRequired();
builder.Property(e => e.Barcode).HasColumnName("barcode").HasColumnType("text");
builder.Property(e => e.Length).HasColumnName("length").HasColumnType("float8");
builder.Property(e => e.Width).HasColumnName("width").HasColumnType("float8");
builder.Property(e => e.Height).HasColumnName("height").HasColumnType("float8");
builder.HasOne(e => e.Area).WithMany(e => e.Containers).HasForeignKey(e => e.AreaId).OnDelete(DeleteBehavior.Cascade);
builder.HasIndex(e => e.AreaId);
builder.HasIndex(e => e.Code).IsUnique();
}
}
}
@@ -0,0 +1,24 @@
using Common.Service.Entities.Types;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace FASS.Service.Entities.Warehouse.Types
{
public class ContainerMaterialEntityType : AuditEntityType<ContainerMaterialEntity>
{
public override void Configure(EntityTypeBuilder<ContainerMaterialEntity> builder)
{
base.Configure(builder);
builder.ToTable("warehouse_container_material");
builder.Property(e => e.ContainerId).HasColumnName("container_id").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.MaterialId).HasColumnName("material_id").HasColumnType("varchar(50)").IsRequired();
builder.HasOne(e => e.Container).WithMany(e => e.ContainerMaterials).HasForeignKey(e => e.ContainerId).OnDelete(DeleteBehavior.SetNull);
builder.HasOne(e => e.Material).WithMany(e => e.ContainerMaterials).HasForeignKey(e => e.MaterialId).OnDelete(DeleteBehavior.SetNull);
builder.HasIndex(e => e.ContainerId);
builder.HasIndex(e => e.MaterialId);
}
}
}
@@ -0,0 +1,26 @@
using Common.Service.Entities.Types;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace FASS.Service.Entities.Warehouse.Types
{
public class ContainerMaterialHistoryEntityType : AuditEntityType<ContainerMaterialHistoryEntity>
{
public override void Configure(EntityTypeBuilder<ContainerMaterialHistoryEntity> builder)
{
base.Configure(builder);
builder.ToTable("warehouse_container_material_history");
builder.Property(e => e.ContainerId).HasColumnName("container_id").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.MaterialId).HasColumnName("material_id").HasColumnType("varchar(50)").IsRequired();
builder.Property(e => e.State).HasColumnName("state").HasColumnType("varchar(50)").IsRequired();
builder.HasOne(e => e.Container).WithMany(e => e.ContainerMaterialHistorys).HasForeignKey(e => e.ContainerId).OnDelete(DeleteBehavior.Cascade);
builder.HasOne(e => e.Material).WithMany(e => e.ContainerMaterialHistorys).HasForeignKey(e => e.MaterialId).OnDelete(DeleteBehavior.Cascade);
builder.HasIndex(e => e.ContainerId);
builder.HasIndex(e => e.MaterialId);
}
}
}

Some files were not shown because too many files have changed in this diff Show More