diff --git a/API/Wood.Service/Controllers/CheryRecurringJobInputPageExtendController.cs b/API/Wood.Service/Controllers/CheryRecurringJobInputPageExtendController.cs new file mode 100644 index 0000000..69ae836 --- /dev/null +++ b/API/Wood.Service/Controllers/CheryRecurringJobInputPageExtendController.cs @@ -0,0 +1,606 @@ +using Azure.Core; +using Dapper; +using Magicodes.ExporterAndImporter.Core; +using Magicodes.ExporterAndImporter.Core.Extension; +using Magicodes.ExporterAndImporter.Excel; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime; +using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; +using Omu.ValueInjecter; +using SkiaSharp; +using System.Data; +using System.Drawing.Printing; +using System.Globalization; +using System.Linq.Expressions; +using System.Reflection; +using System.Security.Policy; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +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; + +namespace TaskManager.Controllers +{ + public class CheryRecurringJobInputPageExtendController : RecurringJobBaseController + where T : BaseEntity ,new() + where TDTO:class,new() + { + protected readonly IRepository _repository; + public CheryRecurringJobInputPageExtendController(HttpClient httpClient, JobDbContext jobDbContext, LogController log, IRepository repository) : base(httpClient, jobDbContext, log) + { + _repository = repository; + } + + /// + /// 手工发送调用接口 + /// + /// 任务名称 + /// 请求日期 + /// 客户(Chery) + /// + [HttpGet] + public virtual async Task CustomInvokeAsync(string taskName, string client) + { + var first = _jobDbContext.TaskConifgure.FirstOrDefault(p => p.TaskName == taskName && p.Client == client); + if (first == null) + { + + return; + } + Url = first.Url; + Path = first.Api; + TaskName = first.TaskName; + Client = client; + CPageSize = first.PageSize; + await SyncTaskSubTable(TaskName, Client); + } + + + protected override async Task DoExecutingAsync(string url, string path, string takName, string client, int pagesize) + { + Url = url; + Path = path; + TaskName = takName; + Client = client; + CPageSize = pagesize; + await SyncTaskSubTable(TaskName,Client); + + } + private async Task PostPageAsync(PagedRequest t,Guid taskId,string version) + { + try + { + var inputjson = JsonSerializer.Serialize(t, + new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + Converters = { new DecimalTrimConverter() }, + WriteIndented = false // 可选,用于格式化输出 + } + ); + //inputjson = RemoveWhitespace(inputjson); + var content = await Post(Url, Path, inputjson,taskId,version); + 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,taskId,version); + return null; + } + } + catch (Exception ex) + { + await _logger.AddError($"调用接口无返回值错误{ex.Message}", TaskName,taskId,version); + return null; + } + + } + + + public static string GenerateRandomStringWith8EG() + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + var random = new Random(); + var sb = new StringBuilder(32); + + // 随机生成 "8EG" 的插入位置 (0-29) + int position = random.Next(0, 30); + + // 生成前半部分随机字符串 + for (int i = 0; i < position; i++) + { + sb.Append(chars[random.Next(chars.Length)]); + } + + // 插入 "8EG" + sb.Append("8EG"); + + // 生成后半部分随机字符串,补足32位 + int remainingLength = 32 - sb.Length; + for (int i = 0; i < remainingLength; i++) + { + sb.Append(chars[random.Next(chars.Length)]); + } + + return sb.ToString(); + } + + + private async Task SyncTaskSubTable(string taskName, string client) + { + + + var task= _jobDbContext.TaskConifgure.FirstOrDefault(p => p.TaskName == taskName); + + var tableName = task.TableName; + var total =await _jobDbContext.Database.ExecuteSqlAsync($"select count(1) from {tableName} where writeState=0 and readState=1 "); + var pageSize = CPageSize; + + int totalPages = (int)Math.Ceiling((double)total / pageSize); + + for (int i= 1; i <= totalPages; i++) + { + _jobDbContext.Database.SqlQuery($"Select TOP 1000 * from {tableName} where writeState=0 and readerstate=1 order by uid"); + + + + + + + } + + + + + + + + //if (string.IsNullOrEmpty(taskName) || string.IsNullOrEmpty(client)) + //{ + // await _logger.AddError("任务名称或客户端不能为空",taskName,Guid.NewGuid(),DateTime.Now.ToString("yyyyMMdd")); + // return; + //} + //var sublist = _jobDbContext.TaskSub.Where(p => taskName.Contains(p.TaskName) && p.WriteState == false && p.Subscriber == client ).ToList(); + //int pageSize = CPageSize; + //if (sublist.Any()) + //{ + // foreach (var sub in sublist) + // { + + // string querystr = $"select * from {sub.TableName} where TaskId='{sub.TaskId}' and WriteState=0 and ReadState=1 order by uid";//任务表 + + // var entites = _jobDbContext.Database.GetDbConnection().Query(querystr);//明细表 + // if (entites.Any()) + // { + // var total = entites.Count(); + // sub.DataCount = total; + // int totalPages = (int)Math.Ceiling((double)total / pageSize); + + // for (int i = sub.SyncedPageCount; i <= totalPages; i++) + // { + + // var records = entites.Skip((i - 1) * pageSize) + // .Take(pageSize).ToList(); + // #region dto转换作为参数发给客户API 因为实体比DTO字段多 + // List dtos = new List(); + // foreach (var itm in records) + // { + // TDTO dto = new TDTO(); + // dto.InjectFrom(itm); + // dtos.Add(dto); + // } + // PagedRequest pagedRequest = new PagedRequest() + // { + // batchNo = GenerateRandomStringWith8EG(), + // total = entites.Count(), + // pageSize = pageSize, + // list = dtos, + // pageNum = i + // }; + // #endregion + // foreach (var itm in records) + // { + // itm.WriteState = true; + // } + // var result = await PostPageAsync(pagedRequest,sub.TaskId, DateTime.Now.ToString("yyyyMMdd")); + // if(result.code == 200) + // { + // _jobDbContext.BulkUpdate(records); + // sub.SyncedPageCount = i; + // if (i == totalPages) + // { + // sub.WriteState = true; + // _jobDbContext.Set().Update(sub); + // _jobDbContext.SaveChanges(); + // } + // } + // else + // { + // sub.FailedCount = i*pageSize; + // sub.FailedInfo = $"第 {i} 页奇瑞数据保存失败 {result.message}。"; + + // await _logger.AddError($"第 {i} 页奇瑞数据保存失败 {result.message}。", TaskName,sub.TaskId, DateTime.Now.ToString("yyyyMMdd")); + // } + // } + + // } + + // } + //} + + } + + [HttpGet] + public async Task>> GetAll() + { + return await _repository.GetAllAsync() as List; + } + + [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 new JsonResult(new { Code = 200, Message = "创建成功!" }); ; + } + + [HttpPut("{id}")] + public async Task Update(T entity) + { + if (entity.UId == 0) + { + throw new Exception("更新时,实体主键UId不能为空或0"); + } + var target = await _repository.GetByIdAsync(entity.UId); + if (target == null) + { + throw new Exception($"CheryRecurringJobInputPageController.Update报错:根据UId{entity.UId}没有找到记录"); + return new JsonResult(new { Code = 400, Message = "修改失败!" }); + } + EntityMapper.Trans(entity, target, "UId"); + + await _repository.UpdateAsync(target); + 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, + }; + + + var json= JsonSerializer.Serialize(input); + + + + // 可以在这里构建表达式树过滤条件 + Expression> filter = null; + + var pagedResult = await _repository.GetDataPagedAsync(filter, pagingParams, input.Condition); + return Ok(pagedResult); + } + + public async Task> GetTaskDataPaged(RequestInputBase input) + { + var pagingParams = new PagingParams + { + PageNumber = input.pageNumber, + PageSize = input.pageSize, + SortBy = input.sortBy, + IsAscending = input.isAscending, + }; + + + var json = JsonSerializer.Serialize(input); + + + + // 可以在这里构建表达式树过滤条件 + Expression> filter = null; + + var pagedResult = await _repository.GetDataPagedAsync(filter, pagingParams, input.Condition); + return pagedResult; + } + + /// + /// 导出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"); + } + + // [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"); + + + // } + 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 NotFound("No file uploaded."); + } + try + { + var excelImporter = HttpContext.RequestServices.GetRequiredService(); + var importResult = await excelImporter.Import(file.OpenReadStream()); + 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 = 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 = "导入失败:" + ex.Message }); + } + } + + /// + /// 重写插入前进行操作,如校验等 + /// + /// + /// + protected virtual async Task ImportBefore(List p_list) + { + + } + + /// + /// 重写插入后进行操作如 + /// + /// + /// + protected virtual async Task ImportAfter(List p_list) + { + + } + + + + + + + + + public class DecimalTrimConverter : JsonConverter + { + public override decimal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.GetDecimal(); + } + + public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerOptions options) + { + // 关键步骤:使用 TrimTrailingZeros() 去掉末尾的 0 + writer.WriteStringValue(value.ToString("0.########################", CultureInfo.InvariantCulture)); + } + } + /// + /// 高级查询字段 + /// + /// + + [HttpGet("fields")] + public IActionResult GetQueryFields() + { + // 获取实体类的所有属性 + Type entityType = typeof(T); + var properties = entityType.GetProperties(); + + // 构建字段信息列表 + var fields = new List(); + + foreach (var property in properties) + { + // 获取ExporterHeader特性中的DisplayName + var exporterHeader = property.GetCustomAttribute(); + string displayName = exporterHeader?.DisplayName ?? property.Name; + + // 获取属性类型 + string dataType = property.PropertyType.Name; + + // 添加到字段列表 + fields.Add(new QueryFieldInfo + { + FieldName = property.Name, + DisplayName = displayName, + DataType = dataType + }); + } + + return Ok(fields); + } + + + + + } +} diff --git a/API/Wood.Service/Controllers/CherySupplierConDateService.cs b/API/Wood.Service/Controllers/CherySupplierConDateService.cs index ff3f455..89c3e23 100644 --- a/API/Wood.Service/Controllers/CherySupplierConDateService.cs +++ b/API/Wood.Service/Controllers/CherySupplierConDateService.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; using TaskManager.Contracts.Dtos; using TaskManager.Entity; @@ -15,6 +16,22 @@ namespace TaskManager.Controllers public CherySupplierConDateService(HttpClient httpClient, JobDbContext jobDbContext, LogController log, IRepository repository) : base(httpClient, jobDbContext, log, repository) { } + + [HttpGet] + public async Task GetDetialByID(String id) + { + + SUPPLIER_CON_DATE first = new SUPPLIER_CON_DATE(); + var m = await _jobDbContext.SUPPLIER_CON_DATE.FirstOrDefaultAsync(p => p.Id == id); + if (m != null) + { + return m; + } + return first; + + } + + /// /// 确认提交 /// @@ -70,6 +87,24 @@ namespace TaskManager.Controllers return new JsonResult(new { Code = 200, Message = "修改成功!" }); + } + /// + /// 批量修改 + /// + /// + /// + [HttpPost] + public async Task BatchUpdate([FromBody] List entites) + { + foreach (var item in entites) + { + await Update(item); + } + + return new JsonResult(new { Code = 200, Message = "批量修改成功!" }); + + + } diff --git a/API/Wood.Service/Controllers/CherySupplierConMmrpService.cs b/API/Wood.Service/Controllers/CherySupplierConMmrpService.cs index 7a12d94..3fdd697 100644 --- a/API/Wood.Service/Controllers/CherySupplierConMmrpService.cs +++ b/API/Wood.Service/Controllers/CherySupplierConMmrpService.cs @@ -89,6 +89,24 @@ namespace TaskManager.Controllers return new JsonResult(new { Code = 200, Message = "修改成功!" }); + } + /// + /// 批量修改 + /// + /// + /// + [HttpPost] + public async Task BatchUpdate([FromBody] List entites) + { + foreach (var item in entites) + { + await Update(item); + } + + return new JsonResult(new { Code = 200, Message = "批量修改成功!" }); + + + } diff --git a/API/Wood.Service/Controllers/CherySupplierConPoService.cs b/API/Wood.Service/Controllers/CherySupplierConPoService.cs index 162e573..9633ec3 100644 --- a/API/Wood.Service/Controllers/CherySupplierConPoService.cs +++ b/API/Wood.Service/Controllers/CherySupplierConPoService.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; using TaskManager.Contracts.Dtos; using TaskManager.Entity; @@ -15,6 +16,23 @@ namespace TaskManager.Controllers public CherySupplierConPoService(HttpClient httpClient, JobDbContext jobDbContext, LogController log, IRepository repository) : base(httpClient, jobDbContext, log, repository) { } + + [HttpGet] + public async Task GetDetialByID(String id) + { + + SUPPLIER_CON_DATE first = new SUPPLIER_CON_DATE(); + var m = await _jobDbContext.SUPPLIER_CON_DATE.FirstOrDefaultAsync(p => p.Id == id); + if (m != null) + { + return m; + } + return first; + + } + + + /// /// 确认提交 /// @@ -64,8 +82,29 @@ namespace TaskManager.Controllers return new JsonResult(new { Code = 400, Message = ex.Message }); } } - return new JsonResult(new { Code = 200, Message = "修改成功!" }); + return new JsonResult(new { Code = 200, Message = "确认成功!" }); } + /// + /// 批量修改 + /// + /// + /// + [HttpPost] + public async Task BatchUpdate([FromBody] List entites) + { + foreach (var item in entites) + { + await Update(item); + } + + return new JsonResult(new { Code = 200, Message = "批量修改成功!" }); + + + + } + + + diff --git a/API/Wood.Service/Controllers/TaskConifgureController.cs b/API/Wood.Service/Controllers/TaskConifgureController.cs index eae14d6..149ff82 100644 --- a/API/Wood.Service/Controllers/TaskConifgureController.cs +++ b/API/Wood.Service/Controllers/TaskConifgureController.cs @@ -90,7 +90,10 @@ namespace TaskManager.Controllers var client = task.Client; await AddOrUpdateTask(task); int result=_context.SaveChanges(); - return new JsonResult("200", $"{task.TaskName}设置为自动执行!"); + + + return new JsonResult(new { Code = 200, Message = $"{task.TaskName}设置为自动执行!" }); ; + //return new JsonResult("200", $"{task.TaskName}设置为自动执行!"); } else { @@ -100,14 +103,15 @@ namespace TaskManager.Controllers var client = task.Client; await RemoveTask(task); int result = _context.SaveChanges(); - return new JsonResult("200", $"{task.TaskName}设置为手动执行!"); + return new JsonResult(new { Code = 200, Message = $"{task.TaskName}设置为手动执行!" }); ; + //return new JsonResult("200", $"{task.TaskName}设置为手动执行!"); } } catch (Exception ex) { - - return new JsonResult("200", $"执行报错!"); + return new JsonResult(new { Code = 400, Message = $"执行报错!" }); ; + // return new JsonResult("200", $"执行报错!"); }