From 90f0f3a5ee0398667dc8c8471b2bd0b57caab8b1 Mon Sep 17 00:00:00 2001 From: me Date: Tue, 10 Jun 2025 13:54:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=96=B9=E6=B3=95=E5=9F=BA?= =?UTF-8?q?=E7=B1=BB=EF=BC=8C=E4=BF=AE=E6=94=B93=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API/Wood.Service/Commons/CommonService.cs | 1 + API/Wood.Service/Commons/ValidationHelper.cs | 49 ++++++++++++++ .../CheryRecurringJobInputPageController.cs | 67 +++++++++---------- .../CheryRecurringJobOutPageController.cs | 45 +++++++++---- .../Controllers/NormalBaseController.cs | 46 ++++++++----- 5 files changed, 143 insertions(+), 65 deletions(-) create mode 100644 API/Wood.Service/Commons/ValidationHelper.cs diff --git a/API/Wood.Service/Commons/CommonService.cs b/API/Wood.Service/Commons/CommonService.cs index 0e609e9..58e14a8 100644 --- a/API/Wood.Service/Commons/CommonService.cs +++ b/API/Wood.Service/Commons/CommonService.cs @@ -62,4 +62,5 @@ namespace Wood.Service } } + } diff --git a/API/Wood.Service/Commons/ValidationHelper.cs b/API/Wood.Service/Commons/ValidationHelper.cs new file mode 100644 index 0000000..b1b6878 --- /dev/null +++ b/API/Wood.Service/Commons/ValidationHelper.cs @@ -0,0 +1,49 @@ +using Magicodes.ExporterAndImporter.Core; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.IdentityModel.Tokens; +using System.Reflection; + +namespace Wood.Service +{ + public static class ValidationHelper + { + public static List ValidateDataLength(IList dataList, DbContext dbContext) where T : class + { + var errors = new List(); + var entityType = dbContext.Model.FindEntityType(typeof(T)); + int rowNum = 1; + foreach (var data in dataList) + { + foreach (var property in entityType.GetProperties()) + { + var maxLength = property.GetMaxLength(); + if (maxLength > 0 && property.ClrType == typeof(string)) + { + var value = property.PropertyInfo.GetValue(data) as string; + + + if (!string.IsNullOrEmpty(value) && value.Length > maxLength) + { + string title = property.GetImporterHeader(); + errors.Add($"第{rowNum}行数据错误:字段 {(title.IsNullOrEmpty() ? property.Name : title)} 的长度超过限制 ({value.Length} > {maxLength})"); + } + } + } + rowNum++; + } + + return errors; + } + } + + public static class PropertyExtension + { + public static string GetImporterHeader(this IProperty value) + { + string ret = value?.PropertyInfo?.GetCustomAttribute()?.Name; + return ret; + } + } + +} diff --git a/API/Wood.Service/Controllers/CheryRecurringJobInputPageController.cs b/API/Wood.Service/Controllers/CheryRecurringJobInputPageController.cs index ec558c0..bee8444 100644 --- a/API/Wood.Service/Controllers/CheryRecurringJobInputPageController.cs +++ b/API/Wood.Service/Controllers/CheryRecurringJobInputPageController.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Omu.ValueInjecter; +using SkiaSharp; using System.Data; using System.Drawing.Printing; using System.Linq.Expressions; @@ -19,6 +20,7 @@ using TaskManager.Contracts.Dtos; using TaskManager.Entity; using TaskManager.EntityFramework; using TaskManager.EntityFramework.Repository; +using Wood.Service; using Wood.Util; using Wood.Util.Filters; using static Dapper.SqlMapper; @@ -216,7 +218,6 @@ namespace TaskManager.Controllers } } - [HttpGet] public async Task>> GetAll() @@ -363,11 +364,6 @@ namespace TaskManager.Controllers return await ExportFile(pagedResult.Data, Guid.NewGuid().ToString() + ".xlsx"); } - - - - - // [HttpGet] // public async Task Export([FromQuery] int pageNumber = 1, //[FromQuery] int pageSize = 10, @@ -399,11 +395,7 @@ namespace TaskManager.Controllers return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "_" + fileName }; } - - - [HttpGet] - public async Task GetImportTemplate() { try @@ -441,43 +433,60 @@ namespace TaskManager.Controllers return StatusCode(500, "生成导入模板时发生错误"); } } + [HttpPost("Import")] public async virtual Task Import(IFormFile file) { if (file == null || file.Length <= 0) { - return BadRequest("No file uploaded."); + return NotFound("No file uploaded."); } - try { var excelImporter = HttpContext.RequestServices.GetRequiredService(); var importResult = await excelImporter.Import(file.OpenReadStream()); - //if (importResult.HasError) - //{ - // return BadRequest(importResult.ErrorMessage); - //} + if (importResult.HasError) + { + StringBuilder sb = new StringBuilder(); + foreach (var rowErr in importResult.RowErrors) + { + string temp = string.Join(";", rowErr.FieldErrors.Select(itm => $"第{rowErr.RowIndex}行:{itm.Key}-{itm.Value}")); + sb.AppendLine(temp); + } + foreach (var templateErr in importResult.TemplateErrors) + { + string temp = $"列名:{templateErr.RequireColumnName},错误信息:{templateErr.Message}"; + sb.AppendLine(temp); + } + throw new Exception(sb.ToString()); + } // 处理导入的数据 - List list = new List(); - foreach (var item in importResult.Data) - { - list.Add(item); + List list = importResult.Data.ToList(); - } await ImportBefore(list); + // 校验数据长度 + var validationErrors = ValidationHelper.ValidateDataLength(list, _jobDbContext); + if (validationErrors.Any()) + { + throw new Exception("数据校验失败:" + string.Join(", ", validationErrors)); + } + foreach (var item in list) + { + item.ReadState = true; + item.CreationTime = CommonHelper.CurrentTime; + } await _jobDbContext.BulkInsertAsync(list); await ImportAfter(list); - return new JsonResult(new { Code = 200, Message = "修改成功!" }); } catch (Exception ex) { await _logger.AddError(ex.Message, TaskName); - return new JsonResult(new { Code = 400, Message = "导入失败!" }); + return new JsonResult(new { Code = 400, Message = "导入失败:" + ex.Message }); } } @@ -500,17 +509,5 @@ namespace TaskManager.Controllers { } - - - - - - - - } - - - - } diff --git a/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs b/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs index aa3b9a2..bd6b31c 100644 --- a/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs +++ b/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs @@ -13,6 +13,7 @@ using Omu.ValueInjecter; using System.Data; using System.Data.Common; using System.Linq.Expressions; +using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; @@ -21,6 +22,7 @@ using TaskManager.Controllers; using TaskManager.Entity; using TaskManager.EntityFramework; using TaskManager.EntityFramework.Repository; +using Wood.Service; using Wood.Util; using Wood.Util.Filters; @@ -610,42 +612,57 @@ namespace TaskManager.Controllers { if (file == null || file.Length <= 0) { - return BadRequest("No file uploaded."); + return NotFound("No file uploaded."); } - try { var excelImporter = HttpContext.RequestServices.GetRequiredService(); var importResult = await excelImporter.Import(file.OpenReadStream()); - //if (importResult.HasError) - //{ - // return BadRequest(importResult.ErrorMessage); - //} + if (importResult.HasError) + { + StringBuilder sb = new StringBuilder(); + foreach (var rowErr in importResult.RowErrors) + { + string temp = string.Join(";", rowErr.FieldErrors.Select(itm => $"第{rowErr.RowIndex}行:{itm.Key}-{itm.Value}")); + sb.AppendLine(temp); + } + foreach (var templateErr in importResult.TemplateErrors) + { + string temp = $"列名:{templateErr.RequireColumnName},错误信息:{templateErr.Message}"; + sb.AppendLine(temp); + } + throw new Exception(sb.ToString()); + } // 处理导入的数据 - List list = new List(); - foreach (var item in importResult.Data) - { - list.Add(item); + List list = importResult.Data.ToList(); - } await ImportBefore(list); + // 校验数据长度 + var validationErrors = ValidationHelper.ValidateDataLength(list, _jobDbContext); + if (validationErrors.Any()) + { + throw new Exception("数据校验失败:" + string.Join(", ", validationErrors)); + } + foreach (var item in list) + { + item.ReadState = true; + item.CreationTime = CommonHelper.CurrentTime; + } await _jobDbContext.BulkInsertAsync(list); await ImportAfter(list); - return new JsonResult(new { Code = 200, Message = "修改成功!" }); } catch (Exception ex) { await _logger.AddError(ex.Message, TaskName); - return new JsonResult(new { Code = 400, Message = "导入失败!" }); + return new JsonResult(new { Code = 400, Message = "导入失败:" + ex.Message }); } } - protected virtual async Task ImportBefore(List p_list) { diff --git a/API/Wood.Service/Controllers/NormalBaseController.cs b/API/Wood.Service/Controllers/NormalBaseController.cs index 3d0bdc6..92d7827 100644 --- a/API/Wood.Service/Controllers/NormalBaseController.cs +++ b/API/Wood.Service/Controllers/NormalBaseController.cs @@ -289,43 +289,57 @@ namespace Wood.Service.Controllers { if (file == null || file.Length <= 0) { - return BadRequest("No file uploaded."); + return NotFound("No file uploaded."); } - try { var excelImporter = HttpContext.RequestServices.GetRequiredService(); var importResult = await excelImporter.Import(file.OpenReadStream()); - //if (importResult.HasError) - //{ - // return BadRequest(importResult.ErrorMessage); - //} + if (importResult.HasError) + { + StringBuilder sb = new StringBuilder(); + foreach (var rowErr in importResult.RowErrors) + { + string temp = string.Join(";", rowErr.FieldErrors.Select(itm => $"第{rowErr.RowIndex}行:{itm.Key}-{itm.Value}")); + sb.AppendLine(temp); + } + foreach (var templateErr in importResult.TemplateErrors) + { + string temp = $"列名:{templateErr.RequireColumnName},错误信息:{templateErr.Message}"; + sb.AppendLine(temp); + } + throw new Exception(sb.ToString()); + } // 处理导入的数据 - List list = new List(); - foreach (var item in importResult.Data) - { - list.Add(item); + List list = importResult.Data.ToList(); - } await ImportBefore(list); + // 校验数据长度 + var validationErrors = ValidationHelper.ValidateDataLength(list, _context); + if (validationErrors.Any()) + { + throw new Exception("数据校验失败:" + string.Join(", ", validationErrors)); + } + foreach (var item in list) + { + item.ReadState = true; + item.CreationTime = CommonHelper.CurrentTime; + } await _context.BulkInsertAsync(list); await ImportAfter(list); - return new JsonResult(new { Code = 200, Message = "修改成功!" }); } catch (Exception ex) { - throw new Exception("NormalBaseController.Import报错:" + ex.Message); - // await _logger.AddError(ex.Message, TaskName); - return new JsonResult(new { Code = 400, Message = "导入失败!" }); + //await _logger.AddError(ex.Message, TaskName); + return new JsonResult(new { Code = 400, Message = "导入失败:" + ex.Message }); } } - protected virtual async Task ImportBefore(List p_list) {