update V 2.4.3.0
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+163
@@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
using Common.Service.Dtos.Validators;
|
||||
|
||||
namespace FASS.Service.Dtos.Warehouse.Validators
|
||||
{
|
||||
public class ContainerMaterialDtoValidator : AuditDtoValidator<ContainerMaterialDto>
|
||||
{
|
||||
public ContainerMaterialDtoValidator()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
using Common.Service.Dtos.Validators;
|
||||
|
||||
namespace FASS.Service.Dtos.Warehouse.Validators
|
||||
{
|
||||
public class MaterialStorageDtoValidator : AuditDtoValidator<MaterialStorageDto>
|
||||
{
|
||||
public MaterialStorageDtoValidator()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
using Common.Service.Dtos.Validators;
|
||||
|
||||
namespace FASS.Service.Dtos.Warehouse.Validators
|
||||
{
|
||||
public class MaterialStorageHistoryDtoValidator : AuditDtoValidator<MaterialStorageHistoryDto>
|
||||
{
|
||||
public MaterialStorageHistoryDtoValidator()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
using Common.Service.Dtos.Validators;
|
||||
|
||||
namespace FASS.Service.Dtos.Warehouse.Validators
|
||||
{
|
||||
public class StorageContainerDtoValidator : AuditDtoValidator<StorageContainerDto>
|
||||
{
|
||||
public StorageContainerDtoValidator()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -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!;
|
||||
}
|
||||
}
|
||||
+15
@@ -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!;
|
||||
}
|
||||
}
|
||||
+15
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -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
Reference in New Issue
Block a user