diff --git a/DOAN.Admin.WebApi/Controllers/MES/Group/AchievementController.cs b/DOAN.Admin.WebApi/Controllers/MES/Group/AchievementController.cs index 8d69006..38bc53b 100644 --- a/DOAN.Admin.WebApi/Controllers/MES/Group/AchievementController.cs +++ b/DOAN.Admin.WebApi/Controllers/MES/Group/AchievementController.cs @@ -2,6 +2,7 @@ using DOAN.Model.MES.Group.Dto; using DOAN.Model.MES.order.Dto; using DOAN.Service.MES.Group.IService; +using Infrastructure.Converter; using Microsoft.AspNetCore.Mvc; namespace DOAN.Admin.WebApi.Controllers.MES.Group { @@ -19,7 +20,17 @@ namespace DOAN.Admin.WebApi.Controllers.MES.Group _achievementService = achievementService; } - + /// + /// + /// + /// + [HttpPost("test")] + [AllowAnonymous] + public IActionResult Test([FromBody] TestQuery parm) + { + parm.JobDatetime= parm.JobDatetime.ToLocalTime(); + return SUCCESS(parm.JobDatetime); + } /// /// 获取y工绩效列表 /// @@ -28,6 +39,8 @@ namespace DOAN.Admin.WebApi.Controllers.MES.Group [HttpPost("get_staff_achievement_list")] public IActionResult GetstaffAchievementList([FromBody]AchievementQueryDto parm) { + parm.JobDatetime[0]= DOANConvertDate.ConvertLocalDateTime(parm.JobDatetime[0]); + parm.JobDatetime[1]= DOANConvertDate.ConvertLocalDateTime(parm.JobDatetime[1]); var response = _achievementService.GetstaffAchievementList(parm); return SUCCESS(response); } diff --git a/DOAN.Admin.WebApi/Program.cs b/DOAN.Admin.WebApi/Program.cs index 37e756e..31ea43b 100644 --- a/DOAN.Admin.WebApi/Program.cs +++ b/DOAN.Admin.WebApi/Program.cs @@ -22,7 +22,10 @@ builder.Host.UseNLog(); builder.Services.AddDynamicApi(); // Add services to the container. -builder.Services.AddControllers(); +builder.Services.AddControllers(options => +{ + options.ModelBinderProviders.Insert(0, new LocalDateModelBinderProvider()); +}); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); @@ -65,15 +68,17 @@ if (openRedis == "1") builder.Services.AddMvc(options => { options.Filters.Add(typeof(GlobalActionMonitor));//全局注册 -}) +}); +builder.Services.AddControllers() +//解析来自客户端的 POST 请求中的 JSON 数据 .AddJsonOptions(options => { //options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString; options.JsonSerializerOptions.WriteIndented = true; + options.JsonSerializerOptions.Converters.Add(new DateTimeArrayConverter()); // 注册新的转换器 options.JsonSerializerOptions.Converters.Add(new JsonConverterUtil.DateTimeConverter()); options.JsonSerializerOptions.Converters.Add(new JsonConverterUtil.DateTimeNullConverter()); - options.JsonSerializerOptions.Converters.Add(new JsonConverterUtil.DateTimeArrayConverter()); - options.JsonSerializerOptions.Converters.Add(new JsonConverterUtil.DateTimeNullableArrayConverter()); + options.JsonSerializerOptions.Converters.Add(new StringConverter()); //PropertyNamingPolicy属性用于前端传过来的属性的格式策略,目前内置的仅有一种策略CamelCase options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; @@ -117,6 +122,8 @@ app.Use(async (context, next) => }); //使用全局异常中间件 app.UseMiddleware(); +//创建一个中间件来统一处理所有进入的 HTTP GET 请求,并对其中可能存在的 UTC 格式的时间数组进行转换 +//app.UseMiddleware(); // 配置中间件以支持本地化 var supportedCultures = new List { diff --git a/DOAN.Model/MES/Group/Dto/AchievementQueryDto.cs b/DOAN.Model/MES/Group/Dto/AchievementQueryDto.cs index bbadac5..f02ba00 100644 --- a/DOAN.Model/MES/Group/Dto/AchievementQueryDto.cs +++ b/DOAN.Model/MES/Group/Dto/AchievementQueryDto.cs @@ -14,4 +14,10 @@ namespace DOAN.Model.MES.Group.Dto } + + + public class TestQuery + { + public DateTime JobDatetime { get; set; } + } } diff --git a/DOAN.Service/MES/Group/AchievementService.cs b/DOAN.Service/MES/Group/AchievementService.cs index 5327eb0..d738438 100644 --- a/DOAN.Service/MES/Group/AchievementService.cs +++ b/DOAN.Service/MES/Group/AchievementService.cs @@ -22,35 +22,24 @@ namespace DOAN.Service.MES.Group /// /// /// - public List GetstaffAchievementList(AchievementQueryDto parm) + public List GetstaffAchievementList(AchievementQueryDto parm) { var predicate = QueryExp(parm); - var result= Context.Queryable().Where(predicate.ToExpression()) - .GroupBy(x => x.Worker) - .Select(it=>new AchievementDto + var result = Context.Queryable().Where(predicate.ToExpression()) + .GroupBy(it => it.Worker) + .Select(it => new AchievementDto { Worker = it.Worker, - - MaterialUse=SqlFunc.Subqueryable().Where(x=>x.Worker==it.Worker&&x.ProcessId==10).Where(predicate.ToExpression()).Sum(x=>x.FinishNum??0), - - MechanicalProcessing = SqlFunc.Subqueryable().Where(x => x.Worker == it.Worker && x.ProcessId == 20).Where(predicate.ToExpression()).Sum(x => x.FinishNum ?? 0), - - MiddleCheck = SqlFunc.Subqueryable().Where(x => x.Worker == it.Worker && x.ProcessId == 10).Where(predicate.ToExpression()).Sum(x => x.FinishNum ?? 0), - - Handgrind = SqlFunc.Subqueryable().Where(x => x.Worker == it.Worker && x.ProcessId == 10).Where(predicate.ToExpression()).Sum(x => x.FinishNum ?? 0), - - Machinegrind = SqlFunc.Subqueryable().Where(x => x.Worker == it.Worker && x.ProcessId == 10).Where(predicate.ToExpression()).Sum(x => x.FinishNum ?? 0), - - - Finegrind = SqlFunc.Subqueryable().Where(x => x.Worker == it.Worker && x.ProcessId == 10).Where(predicate.ToExpression()).Sum(x => x.FinishNum ?? 0), - - - WarehouseInspection = SqlFunc.Subqueryable().Where(x => x.Worker == it.Worker && x.ProcessId == 10).Where(predicate.ToExpression()).Sum(x => x.FinishNum ?? 0), - - - Shipment = SqlFunc.Subqueryable().Where(x => x.Worker == it.Worker && x.ProcessId == 10).Where(predicate.ToExpression()).Sum(x => x.FinishNum ?? 0), - - }).Distinct().ToList(); + MaterialUse = SqlFunc.AggregateSum(it.ProcessId == 10 ? it.FinishNum ?? 0 : 0), + MechanicalProcessing = SqlFunc.AggregateSum(it.ProcessId == 20 ? it.FinishNum ?? 0 : 0), + MiddleCheck = SqlFunc.AggregateSum(it.ProcessId == 30 ? it.FinishNum ?? 0 : 0), + Handgrind = SqlFunc.AggregateSum(it.ProcessId == 40 ? it.FinishNum ?? 0 : 0), + Machinegrind = SqlFunc.AggregateSum(it.ProcessId == 50 ? it.FinishNum ?? 0 : 0), + Finegrind = SqlFunc.AggregateSum(it.ProcessId == 60 ? it.FinishNum ?? 0 : 0), + WarehouseInspection = SqlFunc.AggregateSum(it.ProcessId == 70 ? it.FinishNum ?? 0 : 0), + Shipment = SqlFunc.AggregateSum(it.ProcessId == 90 ? it.FinishNum ?? 0 : 0) + }).Distinct() + .ToList(); int index = 0; foreach (var item in result) { @@ -62,11 +51,11 @@ namespace DOAN.Service.MES.Group private static Expressionable QueryExp(AchievementQueryDto parm) { - + var predicate = Expressionable.Create() .AndIF(!string.IsNullOrEmpty(parm.Worker), it => it.Worker.Contains(parm.Worker)) - .AndIF(parm.JobDatetime != null&& parm.JobDatetime[0]>DateTime.MinValue, it => it.JobDateTime >=parm.JobDatetime[0]) - .AndIF(parm.JobDatetime != null&& parm.JobDatetime[0]>DateTime.MinValue, it => it.JobDateTime <=parm.JobDatetime[1]) + .AndIF(parm.JobDatetime != null && parm.JobDatetime[0] > DateTime.MinValue, it => it.JobDateTime >= parm.JobDatetime[0]) + .AndIF(parm.JobDatetime != null && parm.JobDatetime[0] > DateTime.MinValue, it => it.JobDateTime <= parm.JobDatetime[1]) ; return predicate; diff --git a/DOAN.ServiceCore/Middleware/UtcToLocalMiddleware.cs b/DOAN.ServiceCore/Middleware/UtcToLocalMiddleware.cs new file mode 100644 index 0000000..276e1e8 --- /dev/null +++ b/DOAN.ServiceCore/Middleware/UtcToLocalMiddleware.cs @@ -0,0 +1,71 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DOAN.ServiceCore.Middleware +{ + public class UtcToLocalMiddleware + { + private readonly RequestDelegate _next; + + public UtcToLocalMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + // 检查是否是GET请求 + if (HttpMethods.IsGet(context.Request.Method)) + { + var query = context.Request.Query; // 获取查询参数集合 + var queryParams = new List>(); + + foreach (var queryParameter in query) + { + if(queryParameter.Value.Count()>0) + { + foreach (var value in queryParameter.Value) + { + if (DateTime.TryParse(value, + CultureInfo.InvariantCulture, + DateTimeStyles.AssumeUniversal, + out DateTime utcDate)) + { + // 转换为本地时间 + var localTime = utcDate.ToLocalTime(); + + queryParams.Add(new KeyValuePair(queryParameter.Key, new StringValues(localTime.ToString("o")))); + } + else + { + // 如果不是时间格式,则保持原样添加 + queryParams.Add(new KeyValuePair(queryParameter.Key, new StringValues(value))); + } + + } + + } + + + } + + // 构建新的 QueryString + var newQueryString = string.Join("&", queryParams.Select(kv => $"{kv.Key}={Uri.EscapeDataString(kv.Value)}")); + context.Request.QueryString = new QueryString("?" + newQueryString); + } + + // Call the next delegate/middleware in the pipeline + await _next(context); + } + } + + +} diff --git a/DOAN.ServiceCore/ModelBinder/LocalDateModelBinder.cs b/DOAN.ServiceCore/ModelBinder/LocalDateModelBinder.cs new file mode 100644 index 0000000..de79e22 --- /dev/null +++ b/DOAN.ServiceCore/ModelBinder/LocalDateModelBinder.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Mvc.ModelBinding; +using System; +using System.Globalization; +using System.Threading.Tasks; + +public class LocalDateModelBinder : IModelBinder +{ + public Task BindModelAsync(ModelBindingContext bindingContext) + { + var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); + + if (valueProviderResult == ValueProviderResult.None) + return Task.CompletedTask; + + var dateStr = valueProviderResult.FirstValue; + + // 尝试根据特定格式和当前文化信息解析日期字符串 + if (DateTime.TryParse(dateStr, CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal, out DateTime parsedDate)) + { + bindingContext.Result = ModelBindingResult.Success(parsedDate); + } + else + { + bindingContext.ModelState.TryAddModelError( + bindingContext.ModelName, + "Invalid date format."); + } + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/DOAN.ServiceCore/ModelBinder/LocalDateModelBinderProvider.cs b/DOAN.ServiceCore/ModelBinder/LocalDateModelBinderProvider.cs new file mode 100644 index 0000000..1f9e500 --- /dev/null +++ b/DOAN.ServiceCore/ModelBinder/LocalDateModelBinderProvider.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Mvc.ModelBinding; +using System; + +public class LocalDateModelBinderProvider : IModelBinderProvider +{ + public IModelBinder GetBinder(ModelBinderProviderContext context) + { + if (context.Metadata.ModelType == typeof(DateTime)) + { + return new LocalDateModelBinder(); + } + + return null; + } +} \ No newline at end of file diff --git a/Infrastructure/Converter/JsonConverterUtil.cs b/Infrastructure/Converter/JsonConverterUtil.cs index e6ca958..0159b55 100644 --- a/Infrastructure/Converter/JsonConverterUtil.cs +++ b/Infrastructure/Converter/JsonConverterUtil.cs @@ -12,9 +12,11 @@ namespace Infrastructure.Converter /// public class DateTimeNullConverter : JsonConverter { + //该方法用于将 JSON 字符串反序列化为 DateTime? 类型的值。 public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => string.IsNullOrEmpty(reader.GetString()) ? default : ParseDateTime(reader.GetString()); + //方法用于将 DateTime? 类型的值序列化为 JSON 字符串 public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) => writer.WriteStringValue(value?.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")); } @@ -39,85 +41,47 @@ namespace Infrastructure.Converter } //******************************DOAN JSON 转换器处理日期数组**************************************** - public class DateTimeArrayConverter : JsonConverter + public class DateTimeArrayConverter : JsonConverter> { - public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override IEnumerable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - if (reader.TokenType == JsonTokenType.String) + if (reader.TokenType == JsonTokenType.StartArray) { - if (DateTime.TryParse(reader.GetString(), out var date)) + var list = new List(); + while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) { - return date; - } - } - throw new JsonException("Invalid date format"); - } - - public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) - { - writer.WriteStringValue(value.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ss")); - } - } - - public class DateTimeNullableArrayConverter : JsonConverter - { - public override DateTime?[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType != JsonTokenType.StartArray) - { - throw new JsonException("Expected start of array."); - } - - var dates = new List(); - - while (reader.Read()) - { - if (reader.TokenType == JsonTokenType.EndArray) - { - return dates.ToArray(); - } - - if (reader.TokenType == JsonTokenType.String) - { - var dateString = reader.GetString(); - if (string.IsNullOrEmpty(dateString)) + if (reader.TokenType == JsonTokenType.String) { - dates.Add(null); - } - else if (DateTime.TryParse(dateString, out var date)) - { - dates.Add(date); - } - else - { - throw new JsonException($"Invalid date format: {dateString}"); + var dateTime = ParseDateTime(reader.GetString()); + if (dateTime != null) + { + list.Add(dateTime.Value.ToLocalTime()); // 将UTC时间转为本地时间 + } } } - else - { - throw new JsonException("Expected string value in array."); - } + return list; } - - throw new JsonException("Unexpected end of JSON."); + throw new JsonException(); } - public override void Write(Utf8JsonWriter writer, DateTime?[] value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, IEnumerable value, JsonSerializerOptions options) { writer.WriteStartArray(); foreach (var date in value) { - if (date.HasValue) - { - writer.WriteStringValue(date.Value.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")); - } - else - { - writer.WriteNullValue(); - } + writer.WriteStringValue(date.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")); } writer.WriteEndArray(); } + + private static DateTime? ParseDateTime(string dateStr) + { + if (!string.IsNullOrEmpty(dateStr) && DateTime.TryParse(dateStr, out var dateVal)) + { + return dateVal; // 假设输入的已经是UTC时间 + } + return null; + } } } }