diff --git a/Admin.NET/Admin.NET.Core/Const/CacheConst.cs b/Admin.NET/Admin.NET.Core/Const/CacheConst.cs index 758e8ce0..6114a8d7 100644 --- a/Admin.NET/Admin.NET.Core/Const/CacheConst.cs +++ b/Admin.NET/Admin.NET.Core/Const/CacheConst.cs @@ -100,4 +100,9 @@ public class CacheConst /// 系统字典缓存 /// public const string KeyDict = "sys_dict:"; + + /// + /// Excel临时文件缓存 + /// + public const string KeyExcelTemp = "sys_excel_temp:"; } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs b/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs index 91813ae2..792fc444 100644 --- a/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs @@ -121,4 +121,23 @@ public class SysCommonService : IDynamicApiController, ITransient } return apiList; } + + /// + /// 下载标记错误的临时 Excel(全局) + /// + /// + [DisplayName("下载标记错误的临时 Excel")] + public async Task DownloadErrorExcelTemp([FromQuery] string fileName = null) + { + var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value; + var resultStream = App.GetRequiredService().Get(CacheConst.KeyExcelTemp + userId); + + if (resultStream == null) + throw Oops.Oh("错误标记文件已过期。"); + + return await Task.FromResult(new FileStreamResult(resultStream, "application/octet-stream") + { + FileDownloadName = $"{(string.IsNullOrEmpty(fileName) ? "错误标记_" + DateTime.Now.ToString("yyyyMMddhhmmss") : fileName)}.xlsx" + }); + } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Util/CommonUtil.cs b/Admin.NET/Admin.NET.Core/Util/CommonUtil.cs index 39587679..67dd0d2e 100644 --- a/Admin.NET/Admin.NET.Core/Util/CommonUtil.cs +++ b/Admin.NET/Admin.NET.Core/Util/CommonUtil.cs @@ -203,7 +203,44 @@ public static class CommonUtil foreach (var item in drErrorInfo.FieldErrors) message += $"\r\n{item.Key}:{item.Value}(文件第{drErrorInfo.RowIndex}行)"; } - message += "字段缺失:" + string.Join(",", res.TemplateErrors.Select(m => m.RequireColumnName).ToList()); + message += "\r\n字段缺失:" + string.Join(",", res.TemplateErrors.Select(m => m.RequireColumnName).ToList()); + throw Oops.Oh("导入异常:" + message); + } + return res.Data; + } + + /// + /// 导入Excel数据并错误标记 + /// + /// + /// + public static async Task> ImportExcelData([Required] IFormFile file, Func, ImportResult> importResultCallback = null) where T : class, new() + { + IImporter importer = new ExcelImporter(); + var resultStream = new MemoryStream(); + var res = await importer.Import(file.OpenReadStream(), resultStream, importResultCallback); + resultStream.Seek(0, SeekOrigin.Begin); + var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value; + + App.GetRequiredService().Remove(CacheConst.KeyExcelTemp + userId); + App.GetRequiredService().Set(CacheConst.KeyExcelTemp + userId, resultStream, TimeSpan.FromMinutes(5)); + + var message = string.Empty; + if (res.HasError) + { + if (res.Exception != null) + message += $"\r\n{res.Exception.Message}"; + foreach (DataRowErrorInfo drErrorInfo in res.RowErrors) + { + int rowNum = drErrorInfo.RowIndex; + foreach (var item in drErrorInfo.FieldErrors) + message += $"\r\n{item.Key}:{item.Value}(文件第{drErrorInfo.RowIndex}行)"; + } + if (res.TemplateErrors.Count > 0) + message += "\r\n字段缺失:" + string.Join(",", res.TemplateErrors.Select(m => m.RequireColumnName).ToList()); + + if (message.Length > 200) + message = message.Substring(0, 200) + "...\r\n异常过多,建议下载错误标记文件查看详细错误信息并重新导入。"; throw Oops.Oh("导入异常:" + message); } return res.Data;