diff --git a/be/Modules/Shared/src/Win_in.Sfs.Shared.Application.Contracts/ExportAndImport/IExportImportService.cs b/be/Modules/Shared/src/Win_in.Sfs.Shared.Application.Contracts/ExportAndImport/IExportImportService.cs index a3121f32b..6cf47a38d 100644 --- a/be/Modules/Shared/src/Win_in.Sfs.Shared.Application.Contracts/ExportAndImport/IExportImportService.cs +++ b/be/Modules/Shared/src/Win_in.Sfs.Shared.Application.Contracts/ExportAndImport/IExportImportService.cs @@ -15,4 +15,6 @@ public interface IExportImportService FileContentResult GetImportTemplate(); IList Import(byte[] bytes); + + Dictionary> ImportHaveValidationResult(byte[] bytes); } diff --git a/be/Modules/Shared/src/Win_in.Sfs.Shared.Application/ExportAndImport/ClosedXmlExportImportService.cs b/be/Modules/Shared/src/Win_in.Sfs.Shared.Application/ExportAndImport/ClosedXmlExportImportService.cs index 6dd254dba..087072235 100644 --- a/be/Modules/Shared/src/Win_in.Sfs.Shared.Application/ExportAndImport/ClosedXmlExportImportService.cs +++ b/be/Modules/Shared/src/Win_in.Sfs.Shared.Application/ExportAndImport/ClosedXmlExportImportService.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Linq.Dynamic.Core; using System.Reflection; using AutoMapper.Internal; +using ClosedXML; using ClosedXML.Excel; using ClosedXML.Graphics; using DocumentFormat.OpenXml; @@ -16,6 +17,7 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.Uow; using Win_in.Sfs.Shared.Application.Contracts; using Win_in.Sfs.Shared.Application.Contracts.ExportAndImport; +using Win_in.Sfs.Shared.Domain; using Win_in.Sfs.Shared.Domain.Shared; namespace Win_in.Sfs.Shared.Application; @@ -156,6 +158,72 @@ public class ClosedXmlExportImportService : IExportImportService var row = ws.Row(rowIndex); var model = Activator.CreateInstance(); for (int j = 0; j < ws.ColumnsUsed().Count(); j++) + { + var columnIndex = j + 1; + var cell = row.Cell(columnIndex); + var value = cell.Value; + if (value.ToString() != "") + { + var headerName = ws.Cell(1, columnIndex).Value.ToString().Trim(); + properties.TryGetValue(headerName, out PropertyInfo property); + if (property != null) + { + var propertyType = property.PropertyType; + if (propertyType.IsEnum) + { + var enumValue = Enum.GetNames(propertyType) + .Select(o => new KeyValuePair(o, (Enum)Enum.Parse(propertyType, o))) + .Where(o => o.Value.GetDisplayName() == value.ToString()) + .Select(o => o.Value) + .FirstOrDefault(); + property.SetValue(model, enumValue); + } + else if (propertyType.Name == nameof(Boolean)) + { + if (value.GetText() == "是") + { + property.SetValue(model, true); + } + else + { + property.SetValue(model, false); + } + } + else + { + var propertyValue = Convert.ChangeType(value.ToString(), propertyType); + property.SetValue(model, propertyValue); + } + } + } + } + result.Add(model); + } + return result; + } + catch (Exception ex) + { + throw new Exception($"导入数据错误:{ex.Message}", ex); + } + } + + public Dictionary> ImportHaveValidationResult(byte[] bytes) + { + try + { + var result = new Dictionary>(); + using var workbook = new XLWorkbook(new MemoryStream(bytes)); + var type = typeof(TImportModel); + var properties = GetPropertiesForImportModel(type).ToDictionary(o => o.GetCustomAttribute()?.Name ?? o.GetCustomAttribute()?.Name ?? o.Name); + var name = type.GetCustomAttribute()?.Name ?? typeof(TImportModel).Name; + var ws = workbook.Worksheets.FirstOrDefault(); + for (int i = 1; i < ws.RowsUsed().Count(); i++) + { + var rowIndex = i + 1; + var row = ws.Row(rowIndex); + var model = Activator.CreateInstance(); + var validationRresults = new List(); + for (int j = 0; j < ws.ColumnsUsed().Count(); j++) { var columnIndex = j + 1; var cell = row.Cell(columnIndex); @@ -165,39 +233,53 @@ public class ClosedXmlExportImportService : IExportImportService if (property != null) { var propertyType = property.PropertyType; - if (propertyType.IsEnum) - { - var enumValue = Enum.GetNames(propertyType) - .Select(o => new KeyValuePair(o, (Enum)Enum.Parse(propertyType, o))) - .Where(o => o.Value.GetDisplayName() == value.ToString()) - .Select(o => o.Value) - .FirstOrDefault(); - property.SetValue(model, enumValue); - } - else if (propertyType.Name == nameof(Boolean)) + + if (value.ToString() != "") { - if (value.GetText() == "是") + if (propertyType.IsEnum) { - property.SetValue(model, true); + var enumValue = Enum.GetNames(propertyType) + .Select(o => new KeyValuePair(o, (Enum)Enum.Parse(propertyType, o))) + .Where(o => o.Value.GetDisplayName() == value.ToString()) + .Select(o => o.Value) + .FirstOrDefault(); + property.SetValue(model, enumValue); + } + else if (propertyType.Name == nameof(Boolean)) + { + if (value.GetText() == "是") + { + property.SetValue(model, true); + } + else + { + property.SetValue(model, false); + } } else { - property.SetValue(model, false); + var propertyValue = Convert.ChangeType(value.ToString(), propertyType); + property.SetValue(model, propertyValue); } } else { - if (value.ToString() != "") + if (propertyType.IsEnum || propertyType.Name == nameof(Boolean) || propertyType.IsValueType) { - var propertyValue = Convert.ChangeType(value.ToString(), propertyType); - property.SetValue(model, propertyValue); + var isHasRequiredAttribute = property.HasAttribute(); + if (isHasRequiredAttribute == true) + { + var requiredAttribute = property.GetCustomAttribute(); + var displayName = property.GetCustomAttribute()?.Name ?? headerName; + string errorMessage = string.Format(requiredAttribute.ErrorMessage, displayName); + validationRresults.Add(new ValidationResult(errorMessage, new string[] { "错误" })); + } } - } + } } } - result.Add(model); + result.Add(model, validationRresults); } - // return result; } catch (Exception ex) @@ -233,7 +315,7 @@ public class ClosedXmlExportImportService : IExportImportService else { SetCellStyle(row.Cell(1).SetValue("失败"), rowIndex, 1, fontColor: XLColor.Red); - var desc = string.Join("\\n", errors.Select(o => $"{o.MemberNames?.First()} {o.ErrorMessage}")); + var desc = string.Join("\n", errors.Select(o => $"{o.MemberNames?.First()} {o.ErrorMessage}")); SetCellStyle(row.Cell(2).SetValue(desc), rowIndex, 2, fontColor: XLColor.Red); } } diff --git a/be/Modules/Shared/src/Win_in.Sfs.Shared.Application/SfsCrudWithDetailsAppServiceBase.cs b/be/Modules/Shared/src/Win_in.Sfs.Shared.Application/SfsCrudWithDetailsAppServiceBase.cs index fd024bfd3..91119054b 100644 --- a/be/Modules/Shared/src/Win_in.Sfs.Shared.Application/SfsCrudWithDetailsAppServiceBase.cs +++ b/be/Modules/Shared/src/Win_in.Sfs.Shared.Application/SfsCrudWithDetailsAppServiceBase.cs @@ -519,15 +519,15 @@ public abstract class SfsCrudWithDetailsAppServiceBase o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IMasterEntity<>)); - modelList = ExportImportService.Import(inputFileBytes); - - foreach (var model in modelList) + modelDict = ExportImportService.ImportHaveValidationResult(inputFileBytes); + foreach (var modelDictItem in modelDict) { // DataAnnotations 静态验证 - var validationRresults = new List(); - modelDict.Add(model, validationRresults); + var validationRresults = modelDictItem.Value; + var model = modelDictItem.Key; Validator.TryValidateObject(model, new ValidationContext(model, null, null), validationRresults); } + modelList = modelDict.Keys.ToList(); // 如果没有验证错误或允许部分导入 if (!modelDict.SelectMany(o => o.Value).Any() || requestInput.IsAllowPartImport)