From 814074bb017eba80096dc07b1831921fb2547928 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AD=A6=20=E8=B5=B5?= <89237069@qq.com>
Date: Wed, 4 Jun 2025 14:43:22 +0800
Subject: [PATCH 01/12] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E6=9B=B4=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
... SUPPLIER_PRO_PROCESS_EQUIPMENT_DT_DTO.cs} | 2 +-
.../CheryRecurringJobInputPageController.cs | 6 +-
.../CherySupplierConMmrpService.cs | 67 ++++++++++++++++++-
.../CherySupplierMrpMonthService.cs | 16 +++--
4 files changed, 80 insertions(+), 11 deletions(-)
rename API/TaskManager.Contracts/Dtos/10_17/{SUPPLIER_PRO_PROCESS_EQUIPMENT_DT.cs => SUPPLIER_PRO_PROCESS_EQUIPMENT_DT_DTO.cs} (99%)
diff --git a/API/TaskManager.Contracts/Dtos/10_17/SUPPLIER_PRO_PROCESS_EQUIPMENT_DT.cs b/API/TaskManager.Contracts/Dtos/10_17/SUPPLIER_PRO_PROCESS_EQUIPMENT_DT_DTO.cs
similarity index 99%
rename from API/TaskManager.Contracts/Dtos/10_17/SUPPLIER_PRO_PROCESS_EQUIPMENT_DT.cs
rename to API/TaskManager.Contracts/Dtos/10_17/SUPPLIER_PRO_PROCESS_EQUIPMENT_DT_DTO.cs
index 3e0f034..0a63fd4 100644
--- a/API/TaskManager.Contracts/Dtos/10_17/SUPPLIER_PRO_PROCESS_EQUIPMENT_DT.cs
+++ b/API/TaskManager.Contracts/Dtos/10_17/SUPPLIER_PRO_PROCESS_EQUIPMENT_DT_DTO.cs
@@ -5,7 +5,7 @@ namespace TaskManager.Entity.Entitys
///
/// 工艺装备
///
- public class SUPPLIER_PRO_PROCESS_EQUIPMENT_DT
+ public class SUPPLIER_PRO_PROCESS_EQUIPMENT_DT_DTO
{
///
/// 供应商代码
diff --git a/API/Wood.Service/Controllers/CheryRecurringJobInputPageController.cs b/API/Wood.Service/Controllers/CheryRecurringJobInputPageController.cs
index 82fc756..f3a74de 100644
--- a/API/Wood.Service/Controllers/CheryRecurringJobInputPageController.cs
+++ b/API/Wood.Service/Controllers/CheryRecurringJobInputPageController.cs
@@ -145,13 +145,13 @@ namespace TaskManager.Controllers
await _logger.AddError("任务名称或客户端不能为空",taskName);
return;
}
- var sublist = _jobDbContext.TaskSub.Where(p => p.TaskName == taskName && p.WriteState == false && p.Subscriber == client).ToList();
+ var sublist = _jobDbContext.TaskSub.Where(p => p.TaskName == taskName && p.WriteState == false && p.Subscriber == client ).ToList();
int pageSize = 1000;
if (!sublist.Any())
{
foreach (var sub in sublist)
{
- string querystr = $"select * from {sub.TableName} where TaskId='{sub.TaskId}' and WriteState=0 order by uid";//任务表
+ 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())
@@ -164,7 +164,7 @@ namespace TaskManager.Controllers
var records = entites.Skip((i - 1) * pageSize)
.Take(pageSize).ToList();
- #region dto转换作为参数发给
+ #region dto转换作为参数发给客户API 因为实体比DTO字段多
List dtos = new List();
foreach (var itm in records)
{
diff --git a/API/Wood.Service/Controllers/CherySupplierConMmrpService.cs b/API/Wood.Service/Controllers/CherySupplierConMmrpService.cs
index 988869a..c1be7f4 100644
--- a/API/Wood.Service/Controllers/CherySupplierConMmrpService.cs
+++ b/API/Wood.Service/Controllers/CherySupplierConMmrpService.cs
@@ -1,4 +1,12 @@
-using TaskManager.Entity.Entitys;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Storage;
+using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
+using Org.BouncyCastle.Bcpg.Sig;
+using SkiaSharp;
+using System.Xml;
+using TaskManager.Entity;
+using TaskManager.Entity.Entitys;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
@@ -8,5 +16,62 @@ namespace TaskManager.Controllers
public CherySupplierConMmrpService(HttpClient httpClient, JobDbContext jobDbContext, LogController log, IRepository repository) : base(httpClient, jobDbContext, log, repository)
{
}
+ ///
+ /// 审批通过
+ ///
+ ///
+ ///
+ public async Task Confirm([FromBody] List entites)
+ {
+
+ var taskId = Guid.NewGuid();
+ var task = new TaskSub();
+ task.TaskId = taskId;
+ task.TaskName = TaskName;
+ task.Subscriber = Client;
+ task.TableName = "SUPPLIER_CON_MMRP";
+ task.DataCount = entites.Count;
+ task.Domain = "1";
+ task.Site = "1";
+ task.FailedCount = 0;
+ task.CreateTime = DateTime.Now;
+ task.CreateUser = "admin";
+ task.CreationTime = DateTime.Now;
+ task.SyncedPageCount = 0;
+
+ entites.ForEach(p =>
+ {
+ p.ReadState = true;
+ p.TaskId = taskId;
+
+
+ });
+
+ using (var transaction = await _jobDbContext.Database.BeginTransactionAsync())
+ {
+ var tran = transaction.GetDbTransaction();
+ try
+ {
+ await _jobDbContext.BulkUpdateAsync(entites, options => { options.Transaction = tran; });
+ await _jobDbContext.AddAsync(task);
+ _jobDbContext.SaveChanges();
+
+ // 提交事务
+ await transaction.CommitAsync();
+ }
+ catch (Exception ex)
+ {
+ await transaction.RollbackAsync();
+ new JsonResult(new { Code = 400, Message = ex.Message });
+ }
+ }
+
+ return new JsonResult(new { Code = 200, Message = "修改成功!" });
+
+
+ }
+
+
+
}
}
diff --git a/API/Wood.Service/Controllers/CherySupplierMrpMonthService.cs b/API/Wood.Service/Controllers/CherySupplierMrpMonthService.cs
index 150fc9d..7daf384 100644
--- a/API/Wood.Service/Controllers/CherySupplierMrpMonthService.cs
+++ b/API/Wood.Service/Controllers/CherySupplierMrpMonthService.cs
@@ -21,12 +21,8 @@ namespace TaskManager.Controllers
}
protected override async Task CreateTaskAsync(List plist, JobDbContext dbContext)
{
- var taskId = Guid.NewGuid();
- var task = new TaskSub();
- task.TaskId = taskId;
- task.TaskName = TaskName;
- task.Subscriber = Client;
- task.TableName = "SUPPLIER_CON_MMRP";
+
+
if (plist.Count > 0)
{
List list = new List();
@@ -56,8 +52,16 @@ namespace TaskManager.Controllers
con.QuantityMeet12 = p.QuantityDemand12;
list.Add(con);
});
+
dbContext.BulkInsert(list, new BulkOperationOptions() { UseTableLock = false });
}
+
+
+
+
+
+
+
return;
}
}
From ddfd6b5674a46f7d8e14dc16ca1c4ff6f0ff1f5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AD=A6=20=E8=B5=B5?= <89237069@qq.com>
Date: Wed, 4 Jun 2025 15:13:16 +0800
Subject: [PATCH 02/12] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../CheryRecurringJobOutPageController.cs | 86 ++++++++++++-------
.../CherySupplierMrpMonthService.cs | 19 ++--
2 files changed, 61 insertions(+), 44 deletions(-)
diff --git a/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs b/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs
index 397557b..f727f32 100644
--- a/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs
+++ b/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs
@@ -1,8 +1,4 @@
-using System.Data;
-using System.Linq.Expressions;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-using Magicodes.ExporterAndImporter.Core.Extension;
+using Magicodes.ExporterAndImporter.Core.Extension;
using Magicodes.ExporterAndImporter.Excel;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
@@ -11,11 +7,17 @@ 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;
@@ -31,10 +33,34 @@ namespace TaskManager.Controllers
{
_repository = repository;
}
- protected virtual async Task CreateTaskAsync(List plist,JobDbContext dbContext)
+ 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)
@@ -57,11 +83,11 @@ namespace TaskManager.Controllers
}
if (firstResponse.Data.Total == "0")
{
- await _logger.AddError("首次请求失败,Total为0是否已经全部读取过。", TaskName);
+ 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
@@ -93,8 +119,10 @@ namespace TaskManager.Controllers
}
}
- _jobDbContext.BulkInsert(pagefirstList);
- await CreateTaskAsync(pagefirstList,_jobDbContext);
+ if (pagefirstList.Any())
+ {
+ await InsertDataAsync(pagefirstList);
+ }
// 计算总页数
@@ -110,7 +138,6 @@ namespace TaskManager.Controllers
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));
@@ -121,12 +148,10 @@ namespace TaskManager.Controllers
entity.CreationTime = DateTime.Now;
pageList.Add(entity);
allData.Add(itm);
-
}
}
else
{
-
foreach (var itm in pageResponse.Data.Rows)
{
T entity = new T();
@@ -136,25 +161,22 @@ namespace TaskManager.Controllers
allData.Add(itm);
}
}
-
- _jobDbContext.BulkInsert(pageList);
- await CreateTaskAsync(pageList, _jobDbContext);
- await _logger.AddInfo($"成功获取 {pageResponse.Data.Rows.Count} 条记录", TaskName);
+ if (pageList.Any())
+ {
+ await InsertDataAsync(pageList);
+ }
}
else
{
- await _logger.AddError($"第 {currentPage} 页未返回数据", TaskName);
+ await _logger.AddInfo($"第 {currentPage} 页未返回数据", TaskName);
}
// 简单的请求间隔,避免过于频繁
await Task.Delay(200);
}
-
-
await _logger.AddInfo($"所有数据获取完成,总共获取了 {allData.Count} 条记录", TaskName);
}
-
}
else
{
@@ -191,7 +213,6 @@ namespace TaskManager.Controllers
}
else
{
-
foreach (var itm in firstResponse.Data.Rows)
{
T entity = new T();
@@ -201,8 +222,10 @@ namespace TaskManager.Controllers
allData.Add(itm);
}
}
- _jobDbContext.BulkInsert(pagefirstList);
- await CreateTaskAsync(pagefirstList, _jobDbContext);
+ if (pagefirstList.Any())
+ {
+ await InsertDataAsync(pagefirstList);
+ }
//Console.WriteLine($"总记录数: {totalItems}, 每页大小: {pageSize}");
// 计算总页数
int totalPages = (int)Math.Ceiling((double)totalItems / pageSize);
@@ -231,7 +254,6 @@ namespace TaskManager.Controllers
}
else
{
-
foreach (var itm in pageResponse.Data.Rows)
{
T entity = new T();
@@ -241,9 +263,12 @@ namespace TaskManager.Controllers
allData.Add(itm);
}
}
- _jobDbContext.BulkInsert(pageList);
- await CreateTaskAsync(pageList, _jobDbContext);
- await _logger.AddInfo($"成功获取 {pageResponse.Data.Rows.Count} 条记录", TaskName);
+ if (pageList.Any())
+ {
+ await InsertDataAsync(pageList);
+ }
+
+ //await _logger.AddInfo($"成功获取 {pageResponse.Data.Rows.Count} 条记录", TaskName);
}
else
{
@@ -256,11 +281,8 @@ namespace TaskManager.Controllers
}
}
-
// 首次请求获取总条数和分页信息
-
-
return allData;
}
diff --git a/API/Wood.Service/Controllers/CherySupplierMrpMonthService.cs b/API/Wood.Service/Controllers/CherySupplierMrpMonthService.cs
index 7daf384..b34f612 100644
--- a/API/Wood.Service/Controllers/CherySupplierMrpMonthService.cs
+++ b/API/Wood.Service/Controllers/CherySupplierMrpMonthService.cs
@@ -1,4 +1,5 @@
using Magicodes.ExporterAndImporter.Core;
+using System.Data.Common;
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
@@ -18,11 +19,10 @@ namespace TaskManager.Controllers
public CherySupplierMrpMonthService(HttpClient httpClient, JobDbContext jobDbContext, LogController log, IRepository repository) : base(httpClient, jobDbContext, log, repository)
{
+
}
- protected override async Task CreateTaskAsync(List plist, JobDbContext dbContext)
+ protected override async Task ConfirmDataInsertAsync(List plist, JobDbContext dbContext, DbTransaction dbTransaction)
{
-
-
if (plist.Count > 0)
{
List list = new List();
@@ -52,17 +52,12 @@ namespace TaskManager.Controllers
con.QuantityMeet12 = p.QuantityDemand12;
list.Add(con);
});
-
- dbContext.BulkInsert(list, new BulkOperationOptions() { UseTableLock = false });
- }
-
-
-
-
-
-
+ await dbContext.BulkInsertAsync(list, options=> { options.Transaction = dbTransaction; options.UseTableLock = false; });
+ }
return;
}
+
+
}
}
From e7fde7945acff98093ba697a30d04a981f56a764 Mon Sep 17 00:00:00 2001
From: zhouhongjun <565221961@qq.com>
Date: Wed, 4 Jun 2025 15:24:25 +0800
Subject: [PATCH 03/12] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Filter=E8=BF=87?=
=?UTF-8?q?=E6=BB=A4=E6=9D=A1=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IRepository/IRepository.cs | 5 +
.../Repository/Repository.cs | 44 ++-
.../CheryRecurringJobOutPageController.cs | 25 ++
API/Wood.Util/Filters/Condition.cs | 13 +
API/Wood.Util/Filters/EnumFilterAction.cs | 69 ++++
API/Wood.Util/Filters/EnumFilterLogic.cs | 21 ++
API/Wood.Util/Filters/Filter.cs | 48 +++
API/Wood.Util/Filters/FilterExtensions.cs | 337 ++++++++++++++++++
API/Wood.Util/Filters/RequestInputBase.cs | 23 ++
9 files changed, 583 insertions(+), 2 deletions(-)
create mode 100644 API/Wood.Util/Filters/Condition.cs
create mode 100644 API/Wood.Util/Filters/EnumFilterAction.cs
create mode 100644 API/Wood.Util/Filters/EnumFilterLogic.cs
create mode 100644 API/Wood.Util/Filters/Filter.cs
create mode 100644 API/Wood.Util/Filters/FilterExtensions.cs
create mode 100644 API/Wood.Util/Filters/RequestInputBase.cs
diff --git a/API/TaskManager.EntityFramework/IRepository/IRepository.cs b/API/TaskManager.EntityFramework/IRepository/IRepository.cs
index e6cfd74..2244f0e 100644
--- a/API/TaskManager.EntityFramework/IRepository/IRepository.cs
+++ b/API/TaskManager.EntityFramework/IRepository/IRepository.cs
@@ -7,6 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using TaskManager.Entity;
using TaskManager.EntityFramework.Repository;
+using Wood.Util.Filters;
namespace TaskManager.EntityFramework
{
@@ -25,5 +26,9 @@ namespace TaskManager.EntityFramework
Expression> filter = null,
PagingParams pagingParams = null);
+ Task> GetDataPagedAsync(
+ Expression> filter = null,
+ PagingParams pagingParams = null,Condition condition = null);
+
}
}
\ No newline at end of file
diff --git a/API/TaskManager.EntityFramework/Repository/Repository.cs b/API/TaskManager.EntityFramework/Repository/Repository.cs
index 406c071..6a34dfa 100644
--- a/API/TaskManager.EntityFramework/Repository/Repository.cs
+++ b/API/TaskManager.EntityFramework/Repository/Repository.cs
@@ -10,6 +10,7 @@ using System.Threading.Tasks;
using TaskManager.Entity;
using TaskManager.EntityFramework;
using Wood.Util;
+using Wood.Util.Filters;
namespace TaskManager.EntityFramework.Repository
{
@@ -82,7 +83,7 @@ namespace TaskManager.EntityFramework.Repository
// 应用动态过滤
if (pagingParams?.Filters != null && pagingParams.Filters.Any())
{
- query = query.ApplyFilters(pagingParams.Filters);
+ query = query.ApplyFilters(pagingParams.Filters);
}
// 应用分页和排序
@@ -94,6 +95,36 @@ namespace TaskManager.EntityFramework.Repository
return page;
}
+ public async Task> GetDataPagedAsync(
+ Expression> filter = null,
+ PagingParams pagingParams = null,Condition condition = null)
+ {
+ IQueryable query = _dbSet.AsNoTracking();
+
+ // 应用过滤条件
+ if (filter != null)
+ {
+ query = query.Where(filter);
+ }
+
+ // 应用动态过滤
+ if (condition?.Filters != null && condition.Filters.Any())
+ {
+ query = query.ApplyConditionFilters(condition);
+ }
+
+ // 应用分页和排序
+ pagingParams ??= new PagingParams();
+
+ var page = await query.ToPagedListAsync(pagingParams);
+
+
+ return page;
+ }
+
+
+
+
}
public class PagedResult
{
@@ -181,9 +212,18 @@ namespace TaskManager.EntityFramework.Repository
return query;
}
+ public static IQueryable ApplyConditionFilters(this IQueryable query, Condition condition)
+ {
+ if (condition.Filters == null || !condition.Filters.Any()) return query;
+
+ query = query.Where(condition.Filters.ToLambda());
+
+ return query;
+ }
+
- public static IQueryable ApplyStringFilter(this IQueryable query,
+ public static IQueryable ApplyStringFilter(this IQueryable query,
string propertyName, string value)
{
var property = typeof(T).GetProperty(propertyName,
diff --git a/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs b/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs
index 719c98d..862e7fd 100644
--- a/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs
+++ b/API/Wood.Service/Controllers/CheryRecurringJobOutPageController.cs
@@ -18,6 +18,7 @@ using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
using TaskManager.EntityFramework.Repository;
+using Wood.Util.Filters;
namespace TaskManager.Controllers
{
@@ -411,6 +412,30 @@ namespace TaskManager.Controllers
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);
+ }
+
+
///
/// 导出
///
diff --git a/API/Wood.Util/Filters/Condition.cs b/API/Wood.Util/Filters/Condition.cs
new file mode 100644
index 0000000..a3a1a59
--- /dev/null
+++ b/API/Wood.Util/Filters/Condition.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Wood.Util.Filters
+{
+ public class Condition
+ {
+ public ICollection Filters { get; set; } = new List();
+ }
+}
diff --git a/API/Wood.Util/Filters/EnumFilterAction.cs b/API/Wood.Util/Filters/EnumFilterAction.cs
new file mode 100644
index 0000000..385480f
--- /dev/null
+++ b/API/Wood.Util/Filters/EnumFilterAction.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Wood.Util.Filters
+{
+ ///
+ /// 过滤条件
+ ///
+ public enum EnumFilterAction
+ {
+ ///
+ /// equal
+ ///
+ [Description("等于")] Equal = 0,
+
+ ///
+ /// Not equal
+ ///
+ [Description("不等于")] NotEqual = 1,
+
+ ///
+ /// Bigger
+ ///
+ [Description("大于")] BiggerThan = 2,
+
+ ///
+ /// Smaller
+ ///
+ [Description("小于")] SmallThan = 3,
+
+ ///
+ /// Bigger or equal
+ ///
+ [Description("大于等于")] BiggerThanOrEqual = 4,
+
+ ///
+ /// Small or equal
+ ///
+ [Description("小于等于")] SmallThanOrEqual = 5,
+
+ ///
+ /// Like
+ ///
+ [Description("类似于")] Like = 6,
+
+ ///
+ /// Not like
+ ///
+ [Description("不类似于")] NotLike = 7,
+
+ ///
+ /// Contained in
+ /// List items = new List();
+ /// string value = JsonSerializer.Serialize(items);//转成Json字符串
+ ///FilterCondition filterCondition = new FilterCondition() { Column = "Name", Value = value, Action = EnumFilterAction.In, Logic = EnumFilterLogic.And };
+ ///
+ [Description("包含于")] In = 8,
+
+ ///
+ /// Not contained in
+ ///
+ [Description("不包含于")] NotIn = 9,
+ }
+
+}
diff --git a/API/Wood.Util/Filters/EnumFilterLogic.cs b/API/Wood.Util/Filters/EnumFilterLogic.cs
new file mode 100644
index 0000000..8075b69
--- /dev/null
+++ b/API/Wood.Util/Filters/EnumFilterLogic.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Wood.Util.Filters
+{
+ public enum EnumFilterLogic
+ {
+ ///
+ /// 与
+ ///
+ And = 0,
+
+ ///
+ /// 或
+ ///
+ Or = 1
+ }
+}
diff --git a/API/Wood.Util/Filters/Filter.cs b/API/Wood.Util/Filters/Filter.cs
new file mode 100644
index 0000000..ce792fc
--- /dev/null
+++ b/API/Wood.Util/Filters/Filter.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Wood.Util.Filters
+{
+ public class Filter
+ {
+ public Filter()
+ {
+ Logic = "And";
+ }
+
+ public Filter(string column, string value,
+ string action = "==",
+ string logic = "And")
+ {
+ Column = column;
+ Action = action;
+ Value = value;
+ Logic = logic;
+ }
+
+ ///
+ /// 过滤条件之间的逻辑关系:AND和OR
+ ///
+ public string Logic { get; set; } = "And";
+
+ ///
+ /// 过滤条件中使用的数据列
+ ///
+ public string Column { get; set; }
+
+ ///
+ /// 过滤条件中的操作:==,!=,>,<,>=,<=,In,NotIn,Like,NotLike
+ /// Equal、NotEqual、BiggerThan、SmallThan、BiggerThanOrEqual、SmallThanOrEqual、In、NotIn
+ ///
+ public string Action { get; set; } = "==";
+
+ ///
+ /// 过滤条件中的操作的值
+ ///
+ public string Value { get; set; }
+ }
+
+}
diff --git a/API/Wood.Util/Filters/FilterExtensions.cs b/API/Wood.Util/Filters/FilterExtensions.cs
new file mode 100644
index 0000000..b2ccfb6
--- /dev/null
+++ b/API/Wood.Util/Filters/FilterExtensions.cs
@@ -0,0 +1,337 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+
+namespace Wood.Util.Filters
+{
+ public static class FilterExtensions
+ {
+ public static Expression> ToLambda(this string jsonFilter)
+ {
+ if (string.IsNullOrWhiteSpace(jsonFilter))
+ {
+ return p => true;
+ }
+
+ var filterConditions = JsonSerializer.Deserialize>(jsonFilter);
+ return filterConditions.ToLambda();
+ }
+
+ public static Expression> ToLambda(this Filter filter)
+ {
+ var filterConditions = new List { filter };
+ return filterConditions.ToLambda();
+ }
+
+ public static Expression> ToLambda(this ICollection filterConditionList)
+ {
+ Expression> condition = null;
+ try
+ {
+ if (!filterConditionList.Any())
+ {
+ //创建默认表达式
+ return p => true;
+ }
+
+ foreach (var filterCondition in filterConditionList)
+ {
+ var tempCondition = CreateLambda(filterCondition);
+ if (condition == null)
+ {
+ condition = tempCondition;
+ }
+ else
+ {
+ condition = filterCondition.Logic switch
+ {
+ "And" => condition.And(tempCondition),
+ "Or" => condition.Or(tempCondition),
+ _ => condition
+ };
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"获取筛选条件异常:{ex.Message}");
+ }
+
+ return condition;
+ }
+
+ private static Expression> CreateLambda(Filter filter)
+ {
+ Expression> expression = p => false;
+ try
+ {
+ var parameter = Expression.Parameter(typeof(T), "p"); //创建参数p
+ var member = Expression.PropertyOrField(parameter, filter.Column); //创建表达式中的属性或字段
+ // var propertyType = member.Type; //取属性类型,常量constant按此类型进行转换
+ //var constant = Expression.Constant(filterCondition.Value);//创建常数
+
+ ConstantExpression constant = null;
+ if (filter.Action != "In" && filter.Action != "NotIn")
+ {
+ constant = CreateConstantExpression(member.Type, filter.Value);
+ }
+
+ switch (filter.Action.ToLower())
+ {
+ case "==":
+ expression = Expression.Lambda>(Expression.Equal(member, constant), parameter);
+ break;
+
+ case "!=":
+ expression = Expression.Lambda>(Expression.NotEqual(member, constant), parameter);
+ break;
+
+ case ">":
+ expression = Expression.Lambda>(Expression.GreaterThan(member, constant), parameter);
+ break;
+
+ case "<":
+ expression = Expression.Lambda>(Expression.LessThan(member, constant), parameter);
+ break;
+
+ case ">=":
+ expression = Expression.Lambda>(Expression.GreaterThanOrEqual(member, constant), parameter);
+ break;
+
+ case "<=":
+ expression = Expression.Lambda>(Expression.LessThanOrEqual(member, constant), parameter);
+ break;
+
+ case "like":
+ expression = GetExpressionLikeMethod("Contains", filter);
+ break;
+
+ case "notlike":
+ expression = GetExpressionNotLikeMethod("Contains", filter);
+ break;
+
+ case "in":
+ expression = GetExpressionInMethod("Contains", member.Type, filter);
+ break;
+
+ case "notin":
+ expression = GetExpressionNotInMethod("Contains", member.Type, filter);
+ break;
+
+ default:
+ break;
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception(ex.Message);
+ }
+
+ return expression;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static ConstantExpression CreateConstantExpression(Type propertyType, string value)
+ {
+ ConstantExpression constant;
+ try
+ {
+ if (propertyType.IsGenericType &&
+ propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
+ {
+ var objValue = Convert.ChangeType(value, propertyType.GetGenericArguments()[0], CultureInfo.InvariantCulture);
+ constant = Expression.Constant(objValue);
+ }
+ else if (propertyType.IsEnum)
+ {
+ var enumValue = (Enum)Enum.Parse(propertyType, value, true);
+ constant = Expression.Constant(enumValue);
+ }
+ else
+ {
+ constant = propertyType.Name switch
+ {
+ "Guid" => Expression.Constant(Guid.Parse(value)),
+ _ => Expression.Constant(Convert.ChangeType(value, propertyType, CultureInfo.InvariantCulture))
+ };
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"获取ConstantExpression异常:{ex.Message}");
+ }
+
+ return constant;
+ }
+
+ private static Expression> GetExpressionLikeMethod(string methodName, Filter filter)
+ {
+ var parameterExpression = Expression.Parameter(typeof(T), "p");
+ // MethodCallExpression methodExpression = GetMethodExpression(methodName, filterCondition.Column, filterCondition.Value, parameterExpression);
+ var methodExpression = GetMethodExpression(methodName, filter.Column, filter.Value,
+ parameterExpression);
+ return Expression.Lambda>(methodExpression, parameterExpression);
+ }
+
+ private static Expression> GetExpressionNotLikeMethod(string methodName, Filter filter)
+ {
+ var parameterExpression = Expression.Parameter(typeof(T), "p");
+ var methodExpression = GetMethodExpression(methodName, filter.Column, filter.Value,
+ parameterExpression);
+ var notMethodExpression = Expression.Not(methodExpression);
+ return Expression.Lambda>(notMethodExpression, parameterExpression);
+ }
+
+ ///
+ /// 生成guidList.Contains(p=>p.GUId);
+ /// 除String类型,其他类型涉及到类型转换.如GUID
+ ///
+ ///
+ /// Contains
+ /// PropertyType/typeof(GUId)
+ /// PropertyName/PropertyValue
+ ///
+ private static Expression> GetExpressionInMethod(string methodName, Type propertyType, Filter filter)
+ {
+ var parameterExpression = Expression.Parameter(typeof(T), "p");
+ Type lstType = typeof(List<>).MakeGenericType(propertyType);
+
+ //转换枚举
+ //if (propertyType.IsEnum)
+ //{
+ // var valueArrayStrings = JsonSerializer.Deserialize>(filter.Value);
+ // List