using Magicodes.ExporterAndImporter.Core.Extension; using Magicodes.ExporterAndImporter.Excel; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; using Omu.ValueInjecter; using System.Data; using System.Data.Common; using System.Linq.Expressions; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; using TaskManager.Contracts.Dtos; using TaskManager.Controllers; using TaskManager.Entity; using TaskManager.EntityFramework; using TaskManager.EntityFramework.Repository; using Wood.Util.Filters; namespace TaskManager.Controllers { //[ApiController] //[Route("api/[controller]")] public class CheryRecurringJobOutPageController : RecurringJobBaseController where T : CherryReadBaseEntity, new() where ToutputDetial : CherryReadBaseEntityDto { protected readonly IRepository _repository; public CheryRecurringJobOutPageController(HttpClient httpClient, JobDbContext jobDbContext, LogController log, IRepository repository) : base(httpClient, jobDbContext, log) { _repository = repository; } protected virtual async Task ConfirmDataInsertAsync(List plist,JobDbContext dbContext, DbTransaction dbTransaction) { } private async Task InsertDataAsync(List list) { if (list.Any()) { using (var transaction = await _jobDbContext.Database.BeginTransactionAsync()) { var tran = transaction.GetDbTransaction(); try { _jobDbContext.BulkInsert(list); await ConfirmDataInsertAsync(list, _jobDbContext, tran); // 提交事务 await transaction.CommitAsync(); } catch (Exception ex) { await transaction.RollbackAsync(); new JsonResult(new { Code = 400, Message = ex.Message }); } } } } [NonAction] public async Task> FetchAllDataAsync(string inputdate) { var allData = new List(); int totalItems = 0; int pageSize = 0; int currentPage = 1; string date = !string.IsNullOrEmpty(inputdate) ? inputdate : DateTime.Now.ToString("yyyy-MM-dd"); var readedcount = _jobDbContext.Set().Where(p => p.RequestDate == inputdate).Count(); if (readedcount == 0)//第一次请求用false,接口人胡启名要求 { PagedResponse firstResponse = await GetPageAsync(new PAGE_DTO() { Date = date, IsForce = false}); if (firstResponse == null || firstResponse.Code != 200) { await _logger.AddError("首次请求失败,无法获取分页信息。", TaskName); return allData; } if (firstResponse.Data.Total == "0") { await _logger.AddInfo("首次请求失败,Total为0是否已经全部读取过。", TaskName); return allData; } if (readedcount != int.Parse(firstResponse.Data.Total))//记录数不相等 { var ids = _jobDbContext.Set().Where(p => p.RequestDate == inputdate).Select(p => p.Id).ToList();//已经同步的ID totalItems = int.Parse(firstResponse.Data.Total); pageSize = int.Parse(firstResponse.Data.PageSize); List pagefirstList = new List(); if (readedcount > 0) { var listrows = firstResponse.Data.Rows.Where(p => !ids.Contains(p.Id)); foreach (var itm in firstResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; pagefirstList.Add(entity); allData.Add(itm); } } else { foreach (var itm in firstResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; pagefirstList.Add(entity); allData.Add(itm); } } if (pagefirstList.Any()) { await InsertDataAsync(pagefirstList); } // 计算总页数 int totalPages = (int)Math.Ceiling((double)totalItems / pageSize); //Console.WriteLine($"总共需要请求 {totalPages} 页数据"); // 循环请求剩余页面 for (currentPage = 2; currentPage <= totalPages; currentPage++) { PAGE_DTO pageinput = new PAGE_DTO() { Date = date, PageNum = currentPage, IsForce = false }; Console.WriteLine($"正在请求第 {currentPage} 页..."); PagedResponse pageResponse = await GetPageAsync(pageinput); if (pageResponse?.Data.Rows != null && pageResponse.Data.Rows.Count > 0) { List pageList = new List(); if (readedcount > 0) { var listrows = pageResponse.Data.Rows.Where(p => !ids.Contains(p.Id)); foreach (var itm in pageResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; pageList.Add(entity); allData.Add(itm); } } else { foreach (var itm in pageResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; pageList.Add(entity); allData.Add(itm); } } if (pageList.Any()) { await InsertDataAsync(pageList); } } else { await _logger.AddInfo($"第 {currentPage} 页未返回数据", TaskName); } // 简单的请求间隔,避免过于频繁 await Task.Delay(200); } await _logger.AddInfo($"所有数据获取完成,总共获取了 {allData.Count} 条记录", TaskName); } } else { PagedResponse firstResponse = await GetPageAsync(new PAGE_DTO() { Date = date, IsForce = true }); if (firstResponse == null || firstResponse.Code != 200) { await _logger.AddInfo("首次请求失败,无法获取分页信息。", TaskName); return allData; } if (firstResponse.Data.Total == "0") { await _logger.AddError("首次请求失败,Total为0是否已经全部读取过。", TaskName); return allData; } if (readedcount != int.Parse(firstResponse.Data.Total))//记录数不相等 { var ids = _jobDbContext.Set().Where(p => p.RequestDate == inputdate).Select(p => p.Id).ToList();//已经同步的ID totalItems = int.Parse(firstResponse.Data.Total); pageSize = int.Parse(firstResponse.Data.PageSize); List pagefirstList = new List(); if (readedcount > 0) { var listrows = firstResponse.Data.Rows.Where(p => !ids.Contains(p.Id)); foreach (var itm in firstResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; pagefirstList.Add(entity); allData.Add(itm); } } else { foreach (var itm in firstResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; pagefirstList.Add(entity); allData.Add(itm); } } if (pagefirstList.Any()) { await InsertDataAsync(pagefirstList); } //Console.WriteLine($"总记录数: {totalItems}, 每页大小: {pageSize}"); // 计算总页数 int totalPages = (int)Math.Ceiling((double)totalItems / pageSize); //Console.WriteLine($"总共需要请求 {totalPages} 页数据"); // 循环请求剩余页面 for (currentPage = 2; currentPage <= totalPages; currentPage++) { PAGE_DTO pageinput = new PAGE_DTO() { Date = date, PageNum = currentPage, IsForce = true }; Console.WriteLine($"正在请求第 {currentPage} 页..."); PagedResponse pageResponse = await GetPageAsync(pageinput); if (pageResponse?.Data.Rows != null && pageResponse.Data.Rows.Count > 0) { List pageList = new List(); if (readedcount > 0) { var listrows = pageResponse.Data.Rows.Where(p => !ids.Contains(p.Id)); foreach (var itm in pageResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; pageList.Add(entity); allData.Add(itm); } } else { foreach (var itm in pageResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; pageList.Add(entity); allData.Add(itm); } } if (pageList.Any()) { await InsertDataAsync(pageList); } //await _logger.AddInfo($"成功获取 {pageResponse.Data.Rows.Count} 条记录", TaskName); } else { await _logger.AddInfo($"第 {currentPage} 页未返回数据", TaskName); } // 简单的请求间隔,避免过于频繁 await Task.Delay(200); } await _logger.AddInfo($"所有数据获取完成,总共获取了 {allData.Count} 条记录", TaskName); } } // 首次请求获取总条数和分页信息 return allData; } private async Task> GetPageAsync(PAGE_DTO input) { try { var inputjson = JsonSerializer.Serialize(input, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true // 可选,用于格式化输出 } ); inputjson = RemoveWhitespace(inputjson); var content = await Post(Url, Path, inputjson); if (!string.IsNullOrEmpty(content)) { var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Converters = { new JsonStringEnumConverter(), // 枚举转换 new CustomDateTimeConverter("yyyy-MM-dd HH:mm:ss") // 日期转换 } }; return JsonSerializer.Deserialize>(content, options); } else { await _logger.AddError($"调用接口无返回值{Url}", TaskName); return null; } } catch (Exception ex) { await _logger.AddError($"调用接口无返回值错误{ex.Message}", TaskName); return null; } } /// /// 手工获取调用接口 /// /// 任务名称 /// 请求日期 /// 客户(Chery) /// [HttpGet] public virtual async Task CustomInvokeAsync(string taskName, string inputdate,string client) { var first= _jobDbContext.TaskConifgure.FirstOrDefault(p => p.TaskName == taskName && p.Client == client); if (first == null) { await _logger.AddError($"手工调用接口{taskName}没找到", taskName); return; } Url =first.Url; Path = first.Api; TaskName = taskName; await FetchAllDataAsync(inputdate); } protected override async Task DoExecutingAsync(string url, string path, string takName, string client) { Url = url; Path = path; TaskName = takName; Client = client; await FetchAllDataAsync(string.Empty); } /// /// 获取所有记录 /// /// [HttpGet] public async Task>> GetAll() { return await _repository.GetAllAsync() as List; } /// /// 获取实体通过ID /// /// /// [HttpGet("{id}")] public async Task> GetById(int id) { var entity = await _repository.GetByIdAsync(id); if (entity == null) return NotFound(); return entity; } [HttpPost] public async Task> Create(T entity) { entity.CreationTime = DateTime.Now; var createdEntity = await _repository.AddAsync(entity); return CreatedAtAction(nameof(GetById), new { id = createdEntity.Id }, createdEntity); } /// /// 修改 /// /// /// [HttpPut("{id}")] public async Task Update(T entity) { var _first = await _repository.GetByIdAsync(entity.UId); if (_first == null) { return new JsonResult(new { Code = 400, Message = "修改失败!" }); } await _repository.UpdateAsync(entity); return new JsonResult(new { Code = 200, Message = "修改成功!" }); } /// /// 删除 /// /// /// [HttpDelete("{id}")] public async Task Delete(int id) { await _repository.DeleteAsync(id); return new JsonResult(new { Code = 200, Message = "删除成功!" }); ; } /// /// 分页 /// /// 第几页 /// 每页条数 /// 排序字段 /// 正序还是倒序 /// 过滤条件 /// [HttpGet] public async Task GetPaged( [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(filter, pagingParams); return Ok(pagedResult); } /// /// 分页New /// /// /// [HttpPost] public async Task>> GetDataPaged(RequestInputBase input) { var pagingParams = new PagingParams { PageNumber = input.pageNumber, PageSize = input.pageSize, SortBy = input.sortBy, IsAscending = input.isAscending, }; // 可以在这里构建表达式树过滤条件 Expression> filter = null; var pagedResult = await _repository.GetDataPagedAsync(filter, pagingParams, input.Condition); return Ok(pagedResult); } /// /// 导出 /// /// /// 每页条数 /// 排序字段 /// 正序还是倒序 /// 过滤条件 /// [HttpGet] 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"); } /// /// 导出New /// /// /// [HttpPost] public async Task ExportData(RequestInputBase input) { var pagingParams = new PagingParams { PageNumber = input.pageNumber, PageSize = input.pageSize, SortBy = input.sortBy, IsAscending = input.isAscending, }; // 可以在这里构建表达式树过滤条件 //Expression> filter = null; var pagedResult = await _repository.GetDataPagedAsync(null, pagingParams, input.Condition); return await ExportFile(pagedResult.Data, Guid.NewGuid().ToString() + ".xlsx"); } protected async Task ExportFile(ICollection dtos, string fileName) { 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 }; } /// /// 获取导入模板 /// /// [HttpGet] public async Task GetImportTemplate() { try { // 创建导入模板生成器 var importer = new ExcelImporter(); // 生成导入模板流(这里假设使用 YourModel 作为导入模型) var bytes = await importer.GenerateTemplateBytes(); //using var stream = new MemoryStream(bytes); //stream.Seek(0, SeekOrigin.Begin); // 设置友好的文件名,例如:"导入模板_20250530.xlsx" var fileName = $"导入模板_{DateTime.Now:yyyyMMdd}.xlsx"; // 返回文件流结果 return new FileStreamResult(new MemoryStream(bytes), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "_" + fileName }; //return File( // fileStream: stream, // contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // fileDownloadName: fileName); } catch (Exception ex) { // 记录异常日志 Console.WriteLine($"生成导入模板时出错: {ex.Message}"); // 返回错误响应 return StatusCode(500, "生成导入模板时发生错误"); } } /// /// 导入 /// /// 选择文件 /// [HttpPost("Import")] public async virtual Task Import(IFormFile file) { if (file == null || file.Length <= 0) { return BadRequest("No file uploaded."); } try { var excelImporter = HttpContext.RequestServices.GetRequiredService(); var importResult = await excelImporter.Import(file.OpenReadStream()); //if (importResult.HasError) //{ // return BadRequest(importResult.ErrorMessage); //} // 处理导入的数据 List list = new List(); foreach (var item in importResult.Data) { list.Add(item); } await ImportBefore(list); 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 = "导入失败!" }); } } protected virtual async Task ImportBefore(List p_list) { } protected virtual async Task ImportAfter(List p_list) { } } public class CustomDateTimeConverter : JsonConverter { private readonly string _format; public CustomDateTimeConverter(string format) { _format = format; } public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return DateTime.ParseExact(reader.GetString(), _format, null); } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString(_format)); } } }