diff --git a/API/TaskManager.Entity/Entity.cs b/API/TaskManager.Entity/Entity.cs index 2a1bcb3..48b667e 100644 --- a/API/TaskManager.Entity/Entity.cs +++ b/API/TaskManager.Entity/Entity.cs @@ -570,7 +570,7 @@ namespace TaskManager.Entity /// 零件名称 /// [JsonPropertyName("materialDescription")] - [MaxLength(50)] + [MaxLength(100)] [ExporterHeader(DisplayName = "零件名称")] public string? MaterialDescription { get; set; } = string.Empty; @@ -767,7 +767,7 @@ namespace TaskManager.Entity /// 字符串长度限制:50 字节 /// [ExporterHeader(DisplayName = "零件名称")] - [StringLength(50)] + [StringLength(100)] public string? MaterialDescription { get; set; } = string.Empty; /// @@ -1029,7 +1029,7 @@ namespace TaskManager.Entity /// 零件名称 /// [ExporterHeader(DisplayName = "零件名称")] - [MaxLength(50)] + [MaxLength(100)] public string? MaterialDescription { get; set; } = ""; /// @@ -1166,7 +1166,7 @@ namespace TaskManager.Entity /// /// 物料描述 /// - [MaxLength(50)] + [MaxLength(100)] [ExporterHeader(DisplayName = "物料描述")] public string? MaterialDescription { get; set; } @@ -1342,7 +1342,7 @@ namespace TaskManager.Entity /// /// 物料描述 /// - [MaxLength(50)] + [MaxLength(100)] [ExporterHeader(DisplayName = "物料描述")] public string? MaterialDescription { get; set; } @@ -1447,7 +1447,7 @@ namespace TaskManager.Entity /// /// 物料描述 /// - [MaxLength(50)] + [MaxLength(100)] [ExporterHeader(DisplayName = "物料描述")] public string? MaterialDescription { get; set; } @@ -1559,7 +1559,7 @@ namespace TaskManager.Entity /// /// 物料描述 /// - [MaxLength(50)] + [MaxLength(100)] [ExporterHeader(DisplayName = "物料描述")] public string? MaterialDescription { get; set; } @@ -1695,7 +1695,7 @@ namespace TaskManager.Entity /// /// 零件名称 /// - [MaxLength(50)] + [MaxLength(100)] [ExporterHeader(DisplayName = "零件名称")] public string? MaterialDescription { get; set; } @@ -1858,7 +1858,7 @@ namespace TaskManager.Entity /// /// 零件名称 /// - [MaxLength(50)] + [MaxLength(100)] [ExporterHeader(DisplayName = "零件名称")] public string? MaterialDescription { get; set; } @@ -1971,7 +1971,7 @@ namespace TaskManager.Entity /// /// 零件名称 /// - [MaxLength(50)] + [MaxLength(100)] [ExporterHeader(DisplayName = "零件名称")] public string? MaterialDescription { get; set; } @@ -2098,7 +2098,7 @@ namespace TaskManager.Entity /// /// 零件名称 /// - [MaxLength(50)] + [MaxLength(100)] [ExporterHeader(DisplayName = "零件名称")] public string? MaterialDescription { get; set; } @@ -2250,7 +2250,7 @@ namespace TaskManager.Entity /// /// 零件名称 /// - [MaxLength(50)] + [MaxLength(100)] [ExporterHeader(DisplayName = "零件名称")] public string? MaterialDescription { get; set; } diff --git a/API/Wood.Admin.WebApi/Other/ServiceCollectionExtensions.cs b/API/Wood.Admin.WebApi/Other/ServiceCollectionExtensions.cs index dfeb160..36a1ea6 100644 --- a/API/Wood.Admin.WebApi/Other/ServiceCollectionExtensions.cs +++ b/API/Wood.Admin.WebApi/Other/ServiceCollectionExtensions.cs @@ -105,28 +105,28 @@ namespace Wood.Admin.WebApi #endregion #region autoJob 初始化 - public static void UseAutoJob(this IApplicationBuilder app) - { - Task.Run(async () => - { - if (GlobalContext.SystemConfig!.RunAutoJob) - { - //延迟 5s - await Task.Delay(5 * 1000); - try - { - - AutoJobCenter jobCenter = new AutoJobCenter(); - jobCenter.ScanJob(); - await jobCenter.AddScheduleJob(); - } - catch (Exception ex) - { - Log.Error(ex, "初始化自动job失败!"); - } - } - }); - } + //public static void UseAutoJob(this IApplicationBuilder app) + //{ + // Task.Run(async () => + // { + // if (GlobalContext.SystemConfig!.RunAutoJob) + // { + // //延迟 5s + // await Task.Delay(5 * 1000); + // try + // { + + // AutoJobCenter jobCenter = new AutoJobCenter(); + // jobCenter.ScanJob(); + // await jobCenter.AddScheduleJob(); + // } + // catch (Exception ex) + // { + // Log.Error(ex, "初始化自动job失败!"); + // } + // } + // }); + //} #endregion #region sqlsugar初始化 diff --git a/API/Wood.Admin.WebApi/Startup.cs b/API/Wood.Admin.WebApi/Startup.cs index 01fd093..c27ef33 100644 --- a/API/Wood.Admin.WebApi/Startup.cs +++ b/API/Wood.Admin.WebApi/Startup.cs @@ -11,15 +11,20 @@ using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Numeric; using Quartz; +using SixLabors.ImageSharp.Drawing; using Swashbuckle.AspNetCore.Filters; using System; using System.Collections.Generic; +using System.Drawing.Printing; using System.IO; using System.Linq; using System.Reflection; +using System.Security.Policy; using System.Text; using System.Threading.Tasks; + using TaskManager.Controllers; using TaskManager.Entity; using TaskManager.EntityFramework; @@ -28,7 +33,9 @@ using TaskManager.EntityFramework.Repository; using Wood.Admin.WebApi.Filter; using Wood.Admin.WebApi.Middleware; using Wood.Data.Repository; +using Wood.Service.Controllers; using Wood.Service.Controllers.RegistService; +using Wood.Service.SystemManage; using Wood.Util; namespace Wood.Admin.WebApi @@ -67,26 +74,8 @@ namespace Wood.Admin.WebApi GlobalContext.JwtConfig = Configuration.GetSection("JwtConfig").Get()!; GlobalContext.Services = services; GlobalContext.Configuration = Configuration; - - - //// 扫描当前程序集 - //var assembly = Assembly.GetExecutingAssembly(); - - //// 方法1:按约定注册服务 - //services.AddServicesByConvention(assembly); - - //// 方法2:注册所有实现了IRepository接口的类 - //services.AddImplementationsOf(assembly); - - //// 方法3:注册特定命名空间下的所有服务 - //services.Scan(scan => scan - // .FromAssemblyOf() - // .AddClasses(classes => classes.InNamespace("YourProject.Services")) - // .AsImplementedInterfaces() - // .WithScopedLifetime()); - - - + + @@ -97,51 +86,7 @@ namespace Wood.Admin.WebApi services.AddSqlSugar(Configuration); services.AddHttpClient(); - //services.AddScoped(); - - //services.AddScoped(); - - //// 注册所有需要通过 GetRequiredService 获取的服务 - - //// 1. 整车月度生产计划相关 - //services.AddScoped(); - - //// 2. M+6月物料需求计划相关 - //services.AddScoped(); - - //// 3. 日物料需求计划相关 - //services.AddScoped(); - - //// 4. 计划协议相关 - //services.AddScoped(); - - //// 5. 采购订单相关 - //services.AddScoped(); - - //// 6. 过焊装未过总装相关 - //services.AddScoped(); - - //// 7. 过涂装未过总装相关 - //services.AddScoped(); // 注意类型名是否包含大小写问题(如驼峰命名) - - //// 8. 排序供货相关 - //services.AddScoped(); - - //// 9. 看板配送单相关 - //services.AddScoped(); - - //// 10. 退货单相关 - //services.AddScoped(); - - //// 11. 奇瑞RDC共享库存相关 - //services.AddScoped(); - - //// 12. 日MRP预警推移相关 - //services.AddScoped(); - - //// 13. 供应商共享库存相关 - //services.AddScoped(); - + // 14. 风险确认相关服务(如果类型名正确) @@ -296,7 +241,7 @@ namespace Wood.Admin.WebApi { foreach (var item in assembly) { - var xmlPath = Path.Combine(AppContext.BaseDirectory, $"{item.GetName().Name}.xml"); + var xmlPath = System.IO.Path.Combine(AppContext.BaseDirectory, $"{item.GetName().Name}.xml"); if (File.Exists(xmlPath)) options.IncludeXmlComments(xmlPath, true); @@ -352,22 +297,26 @@ namespace Wood.Admin.WebApi #endregion }); - //services.AddControllers(); - //var s = services.BuildServiceProvider().GetRequiredService(); + //services.AddSingleton(); + //services.AddHostedService(); + + services.AddSingleton(); + services.AddHostedService(); + + - //s.TaskAllAsync("2025-05-29"); } - /// - /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - /// - /// - /// - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + /// + /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + /// + /// + /// + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { diff --git a/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs b/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs index 1a03d03..5889592 100644 --- a/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs +++ b/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs @@ -115,6 +115,7 @@ namespace TaskManager.Controllers T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; + entity.RequestDate = date; pagefirstList.Add(entity); allData.Add(itm); } @@ -171,6 +172,7 @@ namespace TaskManager.Controllers T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; + entity.RequestDate = date; pageList.Add(entity); allData.Add(itm); } @@ -244,6 +246,7 @@ namespace TaskManager.Controllers entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; pagefirstList.Add(entity); + entity.RequestDate = date; allData.Add(itm); } @@ -294,6 +297,7 @@ namespace TaskManager.Controllers T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; + entity.RequestDate = date; pageList.Add(entity); allData.Add(itm); } diff --git a/API/Wood.Service/Controllers/LogController.cs b/API/Wood.Service/Controllers/LogController.cs index 3e722da..41ae0a3 100644 --- a/API/Wood.Service/Controllers/LogController.cs +++ b/API/Wood.Service/Controllers/LogController.cs @@ -20,44 +20,61 @@ using Wood.Service.Controllers; namespace TaskManager.Controllers { - - public class LogController:NormalBaseController + + using System; + using System.Threading; + using System.Threading.Channels; + using System.Threading.Tasks; + + + + + + public class LogController { - public LogController(JobDbContext context, IServiceProvider builder, IConfiguration configuration, IRepository repository) : base(context, builder, configuration, repository) + private readonly Channel _logChannel; + + public LogController(int bufferSize = 1000) { + // 创建有界通道,设置缓冲区大小 + var options = new BoundedChannelOptions(bufferSize) + { + FullMode = BoundedChannelFullMode.Wait + }; + _logChannel = Channel.CreateBounded(options); } - public async Task> GetAll() + public void EnqueueLog(TaskLog log) { - var log = await _context.TaskLogs.ToListAsync(); - return log; + _logChannel.Writer.TryWrite(log); } - //[HttpGet("AddError")] - //public async Task AddError(string message,string taskname) + + + + + //private readonly LogBackgroundService _logService; + //public LogController(JobDbContext context, IServiceProvider builder, IConfiguration configuration, IRepository repository, LogBackgroundService logService) : base(context, builder, configuration, repository) //{ - // _context.TaskLogs.Add(new TaskLog() { Info = message, Type = "错误",TaskName=taskname ,CreationTime=DateTime.Now}); - // var result =await _context.SaveChangesAsync(); - // if (result > 0) - // { - // return true; - // } - // return false; + // _logService = logService; //} - //[HttpGet("AddInfo")] - //public async Task AddInfo(string message, string taskname) + + //[HttpGet] + //public async Task> GetAll() //{ - // _context.TaskLogs.Add(new TaskLog() { Info = message, Type = "记录", TaskName = taskname, CreationTime = DateTime.Now }); - // var result = await _context.SaveChangesAsync(); - // if (result > 0) - // { - // return true; - // } - // return false; + // var log = await _context.TaskLogs.ToListAsync(); + // return log; //} + public ChannelReader GetLogReader() + { + return _logChannel.Reader; + } + + - [HttpGet("AddError")] + [NonAction] + //[HttpGet("AddError")] public async Task AddError(string message, string taskname, Guid taskid, string version) { var log = new TaskLog @@ -69,14 +86,14 @@ namespace TaskManager.Controllers TaskId = taskid, Version = version?.ToString() }; - - _context.TaskLogs.Add(log); - var result = await _context.SaveChangesAsync(); + EnqueueLog(log); + //_context.TaskLogs.Add(log); + //var result = await _context.SaveChangesAsync(); return true; // 日志已入队,视为成功 } - - [HttpGet("AddInfo")] + [NonAction] + //[HttpGet("AddInfo")] public async Task AddInfo(string message, string taskname, Guid taskid, string version) { var log = new TaskLog @@ -88,14 +105,15 @@ namespace TaskManager.Controllers TaskId = taskid, Version = version?.ToString() }; - - _context.TaskLogs.Add(log); - var result = await _context.SaveChangesAsync(); + EnqueueLog(log); + //_context.TaskLogs.Add(log); + //var result = await _context.SaveChangesAsync(); return true; } - [HttpGet("AddPostRequest")] - public async Task AddPostRequest(string message, string taskname, Guid taskid, string version,string remark) + [NonAction] + //[HttpGet("AddPostRequest")] + public async Task AddPostRequest(string message, string taskname, Guid taskid, string version, string remark) { var log = new TaskLog { @@ -105,14 +123,16 @@ namespace TaskManager.Controllers CreationTime = DateTime.Now, TaskId = taskid, Version = version?.ToString(), - Remark = remark + Remark = remark }; - _context.TaskLogs.Add(log); - var result = await _context.SaveChangesAsync(); + EnqueueLog(log); + //_context.TaskLogs.Add(log); + //var result = await _context.SaveChangesAsync(); return true; } - [HttpGet("AddPostResponse")] - public async Task AddPostResponse(string message, string taskname, Guid taskid, string version,string remaek) + [NonAction] + //[HttpGet("AddPostResponse")] + public async Task AddPostResponse(string message, string taskname, Guid taskid, string version, string remaek) { var log = new TaskLog { @@ -122,99 +142,15 @@ namespace TaskManager.Controllers CreationTime = DateTime.Now, TaskId = taskid, Version = version?.ToString(), - Remark = remaek + Remark = remaek }; - _context.TaskLogs.Add(log); - var result = await _context.SaveChangesAsync(); + EnqueueLog(log); return true; } - - - - - - - - - - - - - - [HttpGet("AddInfoRemark")] - public async Task AddInfoRemark(string message, string taskname,string remark) - { - _context.TaskLogs.Add(new TaskLog() { Info = message, Type = "记录", TaskName = taskname, CreationTime = DateTime.Now,Remark=remark }); - var result = await _context.SaveChangesAsync(); - if (result > 0) - { - return true; - } - return false; - } - - - public async Task Export([FromQuery] int pageNumber = 1, - [FromQuery] int pageSize = 10, - [FromQuery] string sortBy = "", - [FromQuery] bool isAscending = true, - [FromQuery] Dictionary filters = null) - { - var pagingParams = new PagingParams - { - PageNumber = pageNumber, - PageSize = pageSize, - SortBy = sortBy, - IsAscending = isAscending, - Filters = filters - }; - - // 可以在这里构建表达式树过滤条件 - Expression> filter = null; - - var pagedResult = await _repository.GetPagedAsync(null, pagingParams); - return await ExportFile(pagedResult.Data, Guid.NewGuid().ToString() + ".xlsx"); - - - } - protected async Task ExportFile(ICollection dtos, string fileName) where T : class, new() - { - var excelExporter = HttpContext.RequestServices.GetRequiredService(); - var res = await excelExporter.ExportAsByteArray(dtos); - return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "_" + fileName }; - } - - - } - - /// 导出 - /// - /// 第几页 - /// 每页条数 - /// 排序列 - /// 是否升序 - /// 查询条件 - /// - - - - - - - //private readonly IServiceProvider _serviceProvider; - //public LogController(IServiceProvider serviceProvider) - //{ - // _serviceProvider = serviceProvider; - //} - //public async Task> GetLogs() - //{ - // var dbcontext= _serviceProvider.GetRequiredService(); - // var connection=dbcontext.Database.GetDbConnection(); - // connection.Query("select top 10 * from logs"); - //} - + } +} diff --git a/API/Wood.Service/Controllers/LogService.cs b/API/Wood.Service/Controllers/LogService.cs index bb7752d..9d56252 100644 --- a/API/Wood.Service/Controllers/LogService.cs +++ b/API/Wood.Service/Controllers/LogService.cs @@ -1,239 +1,286 @@ -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Identity.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http.Json; using System.Text; +using System.Text.Encodings.Web; +using System.Text.Json; using System.Threading.Channels; using System.Threading.Tasks; using TaskManager.Entity; using TaskManager.EntityFramework; +using Wood.Entity; +using Wood.Service.SystemManage; -namespace Wood.Service.Controllers +namespace TaskManager.Controllers { - public class LogController1 : BackgroundService + public class LogConsumerService : BackgroundService { - private readonly IServiceProvider _serviceProvider; - private readonly Channel _logChannel; + private readonly ChannelReader _logReader; + + private readonly ILogger _logger; + private const int BatchSize = 100; // 批量写入大小 private readonly string _logDirectory; + private readonly IServiceProvider _serviceProvider; - public LogController1( - IServiceProvider serviceProvider, - IConfiguration configuration) + + public LogConsumerService( + LogController logService, + + ILogger logger, IServiceProvider serviceProvider) { - _serviceProvider = serviceProvider; - _logDirectory = configuration["Logging:Directory"] ?? - Path.Combine(Directory.GetCurrentDirectory(), "Logs"); + _logReader = logService.GetLogReader(); + + _logger = logger; + _serviceProvider = serviceProvider; ; + _logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CustomLogs"); // 使用更安全的路径获取方式 EnsureDirectoryExists(_logDirectory); - _logChannel = Channel.CreateUnbounded(); - } - + } - public void EnqueueLog(TaskLog logMessage) + protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - // 设置日志路径并写入文件 - logMessage.Path= WriteLogToFile(logMessage); + _logger.LogInformation("日志消费服务已启动"); - // 将日志加入处理队列 - _logChannel.Writer.TryWrite(logMessage); + // 批量处理日志,减少数据库写入次数 + while (!stoppingToken.IsCancellationRequested && + await _logReader.WaitToReadAsync(stoppingToken)) + { + try + { + var logs = new List(); + int count = 0; + + // 读取一批日志 + while (_logReader.TryRead(out var log) && count < BatchSize) + { + logs.Add(log); + count++; + } + + if (logs.Any()) + { + + using var scope = _serviceProvider.CreateScope(); + var db = scope.ServiceProvider.GetRequiredService(); + + List logsToSave = new List(); + foreach (var log in logs) + { + if (!string.IsNullOrEmpty(log.Remark)) + { + log.Path = WriteLogToFile(log.Remark); + } + log.Remark = string.Empty; + logsToSave.Add(log); + } + + await db.TaskLogs.AddRangeAsync(logsToSave, stoppingToken); + await db.SaveChangesAsync(stoppingToken); + + + _logger.LogInformation($"已写入 {logs.Count} 条日志"); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "日志写入数据库失败"); + // 错误处理:可记录到临时文件或重试 + await Task.Delay(1000, stoppingToken); // 短暂延迟后重试 + } + } } - private string WriteLogToFile(TaskLog logMessage) + public override async Task StopAsync(CancellationToken stoppingToken) { - // 获取今天的日期目录 - string todayDirectory = Path.Combine(_logDirectory, DateTime.Now.ToString("yyyy-MM-dd")); + _logger.LogInformation("日志消费服务正在停止"); + // 处理剩余日志 + await base.StopAsync(stoppingToken); + } + private void EnsureDirectoryExists(string directoryPath) + { + if (!Directory.Exists(directoryPath)) + { + Directory.CreateDirectory(directoryPath); + } + } + // 修改后的日志写入方法 + private string WriteLogToFile(string jsonContent) + { + //if string.IsNullOrEmpty(logMessage.RawRemark)) return null; // 必须提供JSON数据 - // 确保目录存在 - EnsureDirectoryExists(todayDirectory); + // 创建日期目录 + string dateDirectory = DateTime.Now.ToString("yyyy-MM-dd"); + string fullDatePath = Path.Combine(_logDirectory, dateDirectory); + EnsureDirectoryExists(fullDatePath); - // 创建或追加到日志文件 - string logFilePath = Path.Combine(todayDirectory, "application.log"); + // 生成唯一文件名(时间戳+随机数) + string fileName = $"log_{DateTime.Now.Ticks}_{Random.Shared.Next(1000, 9999)}.json"; + string fullPath = Path.Combine(fullDatePath, fileName); try { - // 写入日志内容到文件 - File.AppendAllText(logFilePath, - $"[{logMessage.CreationTime:yyyy-MM-dd HH:mm:ss}] [{logMessage.Type}] {logMessage.Info}{Environment.NewLine}"); - // 返回相对路径(从日志根目录开始) - return Path.GetRelativePath(_logDirectory, logFilePath); + // 写入文件(使用UTF-8无BOM格式) + File.WriteAllText(fullPath, jsonContent, new UTF8Encoding(false)); + + // 存储相对路径(从日志根目录开始,使用正斜杠兼容API) + return Path.Combine(dateDirectory, fileName).Replace('\\', '/'); } catch (Exception ex) { - // 记录日志写入失败的错误 - Console.WriteLine($"Error writing log to file: {ex.Message}"); - return null; - } - } + Console.WriteLine($"JSON文件写入失败:{ex.Message}"); - private void EnsureDirectoryExists(string directoryPath) - { - if (!Directory.Exists(directoryPath)) - { - Directory.CreateDirectory(directoryPath); + return null; } } - - - //[HttpGet("AddError")] - //public async Task AddError(string message, string taskname, Guid taskid, Version version) - //{ - // var log = new TaskLog - // { - // Info = message, - // Type = "错误", - // TaskName = taskname, - // CreationTime = DateTime.Now, - // TaskId = taskid, - // Version = version?.ToString() - // }; - - // EnqueueLog(log); - - // return true; // 日志已入队,视为成功 - //} - - //[HttpGet("AddInfo")] - //public async Task AddInfo(string message, string taskname, Guid taskid, Version version) - //{ - // var log = new TaskLog - // { - // Info = message, - // Type = "错误", - // TaskName = taskname, - // CreationTime = DateTime.Now, - // TaskId = taskid, - // Version = version?.ToString() - // }; - - // EnqueueLog(log); - - // return true; - //} - - //[HttpGet("AddInfoRemark")] - //public async Task AddInfoRemark(string message, string taskname, string remark) - //{ - // var log = new TaskLog - // { - // Info = message, - // Type = "记录", - // TaskName = taskname, - // CreationTime = DateTime.Now, - // Remark = remark - // }; - - // EnqueueLog(log); - - // return true; - //} - - [HttpGet("AddError")] - public async Task AddError(string message, string taskname, Guid taskid, string version) - { - var log = new TaskLog - { - Info = message, - Type = "错误", - TaskName = taskname, - CreationTime = DateTime.Now, - TaskId = taskid, - Version = version?.ToString() - }; - EnqueueLog(log); - - return true; // 日志已入队,视为成功 - } + } - [HttpGet("AddInfo")] - public async Task AddInfo(string message, string taskname, Guid taskid, string version) - { - var log = new TaskLog - { - Info = message, - Type = "信息", - TaskName = taskname, - CreationTime = DateTime.Now, - TaskId = taskid, - Version = version?.ToString() - }; - EnqueueLog(log); - return true; - } - [HttpGet("AddPostRequest")] - public async Task AddPostRequest(string message, string taskname, Guid taskid, string version, string remark) - { - var log = new TaskLog - { - Info = message, - Type = "请求", - TaskName = taskname, - CreationTime = DateTime.Now, - TaskId = taskid, - Version = version?.ToString(), - Remark = remark - }; - EnqueueLog(log); - - return true; - } - [HttpGet("AddPostResponse")] - public async Task AddPostResponse(string message, string taskname, Guid taskid, string version, string remaek) - { - var log = new TaskLog - { - Info = message, - Type = "应答", - TaskName = taskname, - CreationTime = DateTime.Now, - TaskId = taskid, - Version = version?.ToString(), - Remark = remaek - }; - EnqueueLog(log); - - return true; - } + // 后台服务 + //public class LogBackgroundService : BackgroundService + //{ + + // private readonly Channel _logChannel; + // private readonly IServiceProvider _serviceProvider; + // private readonly string _logDirectory; + + // public LogBackgroundService(IServiceProvider serviceProvider, IConfiguration configuration) + // { + // Console.WriteLine("LogService 初始化"); + // _serviceProvider = serviceProvider; + // _logDirectory = configuration["Logging:Directory"] ?? + // Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CustomLogs"); // 使用更安全的路径获取方式 + + // EnsureDirectoryExists(_logDirectory); + // _logChannel = Channel.CreateUnbounded(); + // } + + // public void EnqueueLog(TaskLog log) + // { + // _logChannel.Writer.TryWrite(log); + // } + // public override async Task StartAsync(CancellationToken cancellationToken) + // { + // // 服务启动前的准备工作 + // // _logger.LogInformation("Worker starting up..."); + + // // 调用基类方法 + // await base.StartAsync(cancellationToken); + // } + + // public override async Task StopAsync(CancellationToken cancellationToken) + // { + // // 服务停止前的清理工作 + // //_logger.LogInformation("Worker shutting down..."); + + // // 调用基类方法 + // await base.StopAsync(cancellationToken); + // } + + // public override void Dispose() + // { + // // 资源释放 + // // _logger.LogInformation("Worker disposing resources"); + // base.Dispose(); + // } + // protected override async Task ExecuteAsync(CancellationToken stoppingToken) + // { + // Console.WriteLine("LogService 开始执行后台任务"); + + + // using PeriodicTimer timer = new(TimeSpan.FromSeconds(10)); + + + // // 主循环 - 使用 PeriodicTimer 等待下一个触发时间 + // while (await timer.WaitForNextTickAsync(stoppingToken)) + // { + // await foreach (var log in _logChannel.Reader.ReadAllAsync(stoppingToken)) + // { + // try + // { + // if (!string.IsNullOrEmpty(log.Remark)) + // { + // log.Path = WriteLogToFile(log.Remark); + // } + // log.Remark = string.Empty; + // using var scope = _serviceProvider.CreateScope(); + // var db = scope.ServiceProvider.GetRequiredService(); + // await db.TaskLogs.AddAsync(log, stoppingToken); + // await db.SaveChangesAsync(stoppingToken); + // Console.WriteLine($"日志已保存: {log.Info}"); + // } + // catch (Exception ex) + // { + // Console.WriteLine($"日志处理失败: {ex.Message}"); + // } + // } + // } + + // Console.WriteLine("LogService 后台任务已停止"); + // } + // private void EnsureDirectoryExists(string directoryPath) + // { + // if (!Directory.Exists(directoryPath)) + // { + // Directory.CreateDirectory(directoryPath); + // } + // } + // // 修改后的日志写入方法 + // private string WriteLogToFile(string jsonContent) + // { + // //if string.IsNullOrEmpty(logMessage.RawRemark)) return null; // 必须提供JSON数据 + + // // 创建日期目录 + // string dateDirectory = DateTime.Now.ToString("yyyy-MM-dd"); + // string fullDatePath = Path.Combine(_logDirectory, dateDirectory); + // EnsureDirectoryExists(fullDatePath); + + // // 生成唯一文件名(时间戳+随机数) + // string fileName = $"log_{DateTime.Now.Ticks}_{Random.Shared.Next(1000, 9999)}.json"; + // string fullPath = Path.Combine(fullDatePath, fileName); + + // try + // { + + // // 写入文件(使用UTF-8无BOM格式) + // File.WriteAllText(fullPath, jsonContent, new UTF8Encoding(false)); + + // // 存储相对路径(从日志根目录开始,使用正斜杠兼容API) + // return Path.Combine(dateDirectory, fileName).Replace('\\', '/'); + // } + // catch (Exception ex) + // { + // Console.WriteLine($"JSON文件写入失败:{ex.Message}"); + + // return null; + // } + // } + //} +} - // 其他方法保持不变... - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - await foreach (var logMessage in _logChannel.Reader.ReadAllAsync(stoppingToken)) - { - // 使用IServiceScopeFactory创建独立的作用域 - using var scope = _serviceProvider.CreateScope(); - var dbContext = scope.ServiceProvider.GetRequiredService(); - try - { - dbContext.TaskLogs.Add(logMessage); - await dbContext.SaveChangesAsync(stoppingToken); - } - catch (Exception ex) - { - Console.WriteLine($"Error saving log: {ex.Message}"); - } - } - } - } -} diff --git a/API/Wood.Service/Controllers/TaskConifgureController.cs b/API/Wood.Service/Controllers/TaskConifgureController.cs index c606002..eae14d6 100644 --- a/API/Wood.Service/Controllers/TaskConifgureController.cs +++ b/API/Wood.Service/Controllers/TaskConifgureController.cs @@ -68,185 +68,7 @@ namespace TaskManager.Controllers } - /// - - - - - - - ///// - ///// 执行铁定任务 - ///// - ///// - ///// - //[NonAction] - //public async Task testTask(string taskName) - //{ - // var first = await _context.TaskConifgure.FirstOrDefaultAsync(p => p.TaskName == taskName); - // var url = first.Url; - // var path = first.Api; - // var controller = _builder.GetRequiredService(); - // await controller.TestAsync(url, path, taskName, "2025-04-21"); - - //} - //[NonAction] - //public async Task TaskAllAsync(string date) - //{ - // var tasks = _context.TaskConifgure.Where(p => p.IsAuto == true && !string.IsNullOrEmpty(p.Corn) - // && !string.IsNullOrEmpty(p.Api) && !string.IsNullOrEmpty(p.Url)).ToList(); - - - // foreach (var task in tasks) - // { - // try - // { - // var url = task.Url; - // var path = task.Api; - // var taskname = task.TaskName; - - // switch (task.TaskName) - // { - // //case "整车月度生产计划1": - - // // // 添加的代码块 - // // var controller1 = _builder.GetRequiredService(); - // // await controller1.TestAsync(url, path, taskname, "2025-05-29"); - // // break; - - // case "M+6月物料需求计划1": - - // // 添加的代码块 - // var controller2 = _builder.GetRequiredService(); - // await controller2.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "整车月度生产计划2": - - // // 添加的代码块 - // var controller3 = _builder.GetRequiredService(); - // await controller3.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "M+6月物料需求计划2": - - // // 添加的代码块 - // var controller4 = _builder.GetRequiredService(); - // await controller4.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "日物料需求计划": - - // // 添加的代码块 - // var controller5 = _builder.GetRequiredService(); - // await controller5.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "计划协议": - - // // 添加的代码块 - // var controller6 = _builder.GetRequiredService(); - // await controller6.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "采购订单": - - // // 添加的代码块 - // var controller7 = _builder.GetRequiredService(); - // await controller7.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "过焊装未过总装": - - // // 添加的代码块 - // var controller8 = _builder.GetRequiredService(); - // await controller8.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "过涂装未过总装": - - // // 添加的代码块 - // var controller9 = _builder.GetRequiredService(); - // await controller9.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "排序供货": - - // // 添加的代码块 - // var controller10 = _builder.GetRequiredService(); - // await controller10.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "看板配送单": - - // // 添加的代码块 - // var controller11 = _builder.GetRequiredService(); - // await controller11.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "退货单": - - // // 添加的代码块 - // var controller12 = _builder.GetRequiredService(); - // await controller12.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "奇瑞RDC共享库存": - - // // 添加的代码块 - // var controller13 = _builder.GetRequiredService(); - // await controller13.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "日MRP状态监控": - - // // 添加的代码块 - // var controller14 = _builder.GetRequiredService(); - // await controller14.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "日MRP预警推移": - - // // 添加的代码块 - // var controller15 = _builder.GetRequiredService(); - // await controller15.TestAsync(url, path, taskname, "2025-05-29"); - // break; - // case "供应商共享库存-上午": - - // // 添加的代码块 - // var controller19 = _builder.GetRequiredService(); - // await controller19.TestAsync(url, path, taskname, "2025-05-29"); - // break; - - // case "供应商共享库存-晚上": - - // // 添加的代码块 - // var controller20 = _builder.GetRequiredService(); - // await controller20.TestAsync(url, path, taskname, "2025-05-29"); - // break; - // } - - - - // } - // catch - // { - - // } - - - - - - - - - - - - - // } - //} + /// /// 设置任务是否自动执行 @@ -306,6 +128,16 @@ namespace TaskManager.Controllers public async Task RefreshTaskConfig() { + + //RecurringJob.AddOrUpdate( + // "日志定时任务", + // x => x.ExecuteAsync(), + // "*/10 * * * * *", + // TimeZoneInfo.Local + // ); + + + // 从数据库加载所有任务配置 var tasks = _context.TaskConifgure.Where(p => p.IsAuto == true && !string.IsNullOrEmpty(p.Corn)