diff --git a/Tiobon.Core.Api/Controllers/DbFirst/DbFirstController.cs b/Tiobon.Core.Api/Controllers/DbFirst/DbFirstController.cs index 00b0f2ae..4d6f4fd7 100644 --- a/Tiobon.Core.Api/Controllers/DbFirst/DbFirstController.cs +++ b/Tiobon.Core.Api/Controllers/DbFirst/DbFirstController.cs @@ -160,7 +160,7 @@ namespace Tiobon.Core.Controllers data.response += $"库{ConnID}-Model层生成:{FrameSeed.CreateModels(_sqlSugarClient, ConnID, isMuti, tableNames)} || "; //data.response += $"库{ConnID}-IRepositorys层生成:{FrameSeed.CreateIRepositorys(_sqlSugarClient, ConnID, isMuti, tableNames)} || "; data.response += $"库{ConnID}-IServices层生成:{FrameSeed.CreateIServices(_sqlSugarClient, ConnID, isMuti, tableNames)} || "; - data.response += $"库{ConnID}-Repository层生成:{FrameSeed.CreateRepository(_sqlSugarClient, ConnID, isMuti, tableNames)} || "; + //data.response += $"库{ConnID}-Repository层生成:{FrameSeed.CreateRepository(_sqlSugarClient, ConnID, isMuti, tableNames)} || "; data.response += $"库{ConnID}-Services层生成:{FrameSeed.CreateServices(_sqlSugarClient, ConnID, isMuti, tableNames)} || "; // 切回主库 _sqlSugarClient.ChangeDatabase(MainDb.CurrentDbConnId.ToLower()); diff --git a/Tiobon.Core.Api/Controllers/Ghra_GradeController.cs b/Tiobon.Core.Api/Controllers/Ghra_GradeController.cs new file mode 100644 index 00000000..5d5bf019 --- /dev/null +++ b/Tiobon.Core.Api/Controllers/Ghra_GradeController.cs @@ -0,0 +1,100 @@ +namespace Tiobon.Core.Api.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + [Authorize(Permissions.Name)] + public class Ghra_GradeController : ControllerBase + { + #region 初始化 + /// + /// 服务器接口,因为是模板生成,所以首字母是大写的,自己可以重构下 + /// + private readonly IGhra_GradeServices _ghra_GradeServices; + + public Ghra_GradeController(IGhra_GradeServices Ghra_GradeServices) + { + _ghra_GradeServices = Ghra_GradeServices; + } + #endregion + + #region 基础接口 + + #region 查询 + [HttpGet] + public async Task>> Get([FromFilter] QueryFilter filter) + { + return new MessageModel>() + { + msg = "获取成功", + success = true, + response = await _ghra_GradeServices.QueryFilterPage(filter) + }; + } + + [HttpGet("{id}")] + public async Task> Get(string id) + { + return new MessageModel() + { + msg = "获取成功", + success = true, + response = await _ghra_GradeServices.QueryById(id) + }; + } + #endregion + + #region 新增 + [HttpPost] + public async Task> Post([FromBody] Ghra_Grade request) + { + var data = new MessageModel(); + + var id = await _ghra_GradeServices.Add(request); + data.success = id > 0; + if (data.success) + { + data.response = id.ObjToString(); + data.msg = "添加成功"; + } + + return data; + } + #endregion + + #region 新增 + [HttpPut] + public async Task> Put([FromBody] Ghra_Grade request) + { + var data = new MessageModel(); + data.success = await _ghra_GradeServices.Update(request); + if (data.success) + { + data.msg = "更新成功"; + data.response = request?.Id.ObjToString(); + } + + return data; + } + #endregion + + #region 删除 + [HttpDelete] + public async Task> Delete(int id) + { + var data = new MessageModel(); + var model = await _ghra_GradeServices.QueryById(id); + model.IsEnable = 1; + // data.success = await _departmentServices.Update(model); + if (data.success) + { + data.msg = "删除成功"; + data.response = model?.Id.ObjToString(); + } + + return data; + } + #endregion + + #endregion + } +} \ No newline at end of file diff --git a/Tiobon.Core.Api/GlobalUsings.cs b/Tiobon.Core.Api/GlobalUsings.cs index e1792547..cd7a8892 100644 --- a/Tiobon.Core.Api/GlobalUsings.cs +++ b/Tiobon.Core.Api/GlobalUsings.cs @@ -15,3 +15,4 @@ global using Tiobon.Core.Model; global using Tiobon.Core.Model.Models; global using Tiobon.Core.Model.ViewModels; global using Tiobon.Core.Repository.UnitOfWorks; +global using Microsoft.AspNetCore.Mvc; diff --git a/Tiobon.Core.Api/Tiobon.Core.Model.xml b/Tiobon.Core.Api/Tiobon.Core.Model.xml index b162395e..da2d9e18 100644 --- a/Tiobon.Core.Api/Tiobon.Core.Model.xml +++ b/Tiobon.Core.Api/Tiobon.Core.Model.xml @@ -34,165 +34,212 @@ 所有 - + - 以下model 来自ids4项目,多库模式,为了调取ids4数据 - 角色表 + - - - 排序 - + + + Desc: + Default: + Nullable:False + - + - 是否激活 + Desc: + Default: + Nullable:True - + - 创建ID + Desc: + Default: + Nullable:True - + - 创建者 + Desc: + Default: + Nullable:True - + - 创建时间 + Desc: + Default: + Nullable:True - + - 修改ID + Desc: + Default: + Nullable:True - + - 修改者 + Desc: + Default:1 + Nullable:False - + - 修改时间 + Desc: + Default:1 + Nullable:False - + - 以下model 来自ids4项目,多库模式,为了调取ids4数据 - 用户表 + Desc: + Default:1 + Nullable:False - + - 这是爱 + Desc: + Default:0 + Nullable:True - + - id + Desc: + Default:0 + Nullable:False - + - 姓名 + Desc: + Default:DateTime.Now + Nullable:False - + - 年龄 + Desc: + Default: + Nullable:True - + - 通用返回信息类 + Desc: + Default: + Nullable:True - + - 状态码 + Desc: + Default: + Nullable:True - + - 操作是否成功 + Desc: + Default: + Nullable:True - + - 返回信息 + Desc: + Default: + Nullable:True - + - 开发者信息 + Desc: + Default: + Nullable:True - + - 返回数据集合 + Desc: + Default: + Nullable:True - + - 返回成功 + Desc: + Default: + Nullable:True - 消息 - - + - 返回成功 + Desc: + Default: + Nullable:True - 消息 - 数据 - - + - 返回失败 + Desc: + Default: + Nullable:True - 消息 - - + - 返回失败 + Desc: + Default: + Nullable:True - 消息 - 数据 - - + - 返回消息 + Desc: + Default: + Nullable:True - 失败/成功 - 消息 - 数据 - - + - 状态码 + Desc: + Default: + Nullable:True - + - 操作是否成功 + Desc: + Default: + Nullable:True - + - 返回信息 + Desc: + Default: + Nullable:True - + - 返回数据集合 + Desc: + Default: + Nullable:True + + + + + Desc: + Default: + Nullable:True @@ -1790,6 +1837,167 @@ 修改时间 + + + 以下model 来自ids4项目,多库模式,为了调取ids4数据 + 角色表 + + + + + 排序 + + + + + 是否激活 + + + + + 创建ID + + + + + 创建者 + + + + + 创建时间 + + + + + 修改ID + + + + + 修改者 + + + + + 修改时间 + + + + + 以下model 来自ids4项目,多库模式,为了调取ids4数据 + 用户表 + + + + + 这是爱 + + + + + id + + + + + 姓名 + + + + + 年龄 + + + + + 通用返回信息类 + + + + + 状态码 + + + + + 操作是否成功 + + + + + 返回信息 + + + + + 开发者信息 + + + + + 返回数据集合 + + + + + 返回成功 + + 消息 + + + + + 返回成功 + + 消息 + 数据 + + + + + 返回失败 + + 消息 + + + + + 返回失败 + + 消息 + 数据 + + + + + 返回消息 + + 失败/成功 + 消息 + 数据 + + + + + 状态码 + + + + + 操作是否成功 + + + + + 返回信息 + + + + + 返回数据集合 + + 部门表 diff --git a/Tiobon.Core.Api/Tiobon.Core.xml b/Tiobon.Core.Api/Tiobon.Core.xml index 87e917fb..91b45fa3 100644 --- a/Tiobon.Core.Api/Tiobon.Core.xml +++ b/Tiobon.Core.Api/Tiobon.Core.xml @@ -1216,6 +1216,11 @@ + + + 服务器接口,因为是模板生成,所以首字母是大写的,自己可以重构下 + + 服务管理 diff --git a/Tiobon.Core.Common/Attribute/FromFilterAttribute.cs b/Tiobon.Core.Common/Attribute/FromFilterAttribute.cs new file mode 100644 index 00000000..67ac1cbb --- /dev/null +++ b/Tiobon.Core.Common/Attribute/FromFilterAttribute.cs @@ -0,0 +1,276 @@ +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Tiobon.Core.Common +{ + public class FilterHeaderBinder : IModelBinder + { + public Task BindModelAsync(ModelBindingContext bindingContext) + { + if (bindingContext == null) + { + throw new ArgumentNullException(nameof(bindingContext)); + } + + var name = bindingContext.FieldName; + + var headers = bindingContext.HttpContext.Request.Headers; + + QueryFilter queryFilter; + + if (!headers.ContainsKey(name)) + { + queryFilter = QueryFilter.Default; + bindingContext.Result = ModelBindingResult.Success(queryFilter); + return Task.CompletedTask; + } + + string filter = headers[name]; + + if (bindingContext.ModelType == typeof(string)) + { + bindingContext.Result = ModelBindingResult.Success(filter); + return Task.CompletedTask; + } + + try + { + if (string.IsNullOrEmpty(filter) || filter == "%22%22" || filter.ToLower() == "%7b%7d") + { + queryFilter = QueryFilter.Default; + } + else if (filter.Trim() == "undefined" || filter.Trim() == "null") + { + queryFilter = QueryFilter.Default; + //LoggerHelper.SendLogError($"QueryFilter 反序列化异常: {filter}\r\n请求地址: {bindingContext.HttpContext.Request.GetEncodedUrl()}"); + } + else + { + queryFilter = JsonConvert.DeserializeObject(System.Web.HttpUtility.UrlDecode(filter)); + SetPredicateValues(queryFilter, bindingContext); + } + + bindingContext.Result = ModelBindingResult.Success(queryFilter ?? QueryFilter.Default); + } + catch + { + //LoggerHelper.SendLogError($"QueryFilter 反序列化失败: {filter}\r\n请求地址: {bindingContext.HttpContext.Request.GetEncodedUrl()}"); + bindingContext.Result = ModelBindingResult.Success(QueryFilter.Default); + } + return Task.CompletedTask; + } + + /// + /// 设置 PredicateValues 的值类型 + /// + /// + /// + private static void SetPredicateValues(QueryFilter queryFilter, ModelBindingContext bindingContext) + { + if (queryFilter?.PredicateValues == null || queryFilter.PredicateValues.Length == 0) + { + return; + } + + for (int i = 0; i < queryFilter.PredicateValues.Length; i++) + { + if (queryFilter.PredicateValues[i] is JObject jObj) + { + var prop = jObj.Properties()?.FirstOrDefault(); + if (prop == null) + continue; + var type = StringConvertToType(prop.Name); + if (type == null) + continue; + try + { + var v = JsonConvert.DeserializeObject(prop.Value?.ToString(), type); + if (v != null) + { + queryFilter.PredicateValues[i] = v; + } + } + catch (Exception ex) + { + //LoggerHelper.SendLogError($"QueryFilter.PredicateValues[{i}] [{queryFilter.PredicateValues[i]}] 反序列化失败\r\n" + + // $"请求地址: {bindingContext.HttpContext.Request.GetEncodedUrl()}\r\n" + + // $"错误信息: {ex}"); + } + } + } + } + + + #region 字符串获取类型 + /// + /// 根据 获取 类型 + /// + /// + /// + public static Type StringConvertToType(string name) + { + if (string.IsNullOrEmpty(name)) + { + return default; + } + + switch (name.Trim().ToUpper()) + { + case "INT": + case "INT32": + return typeof(int); + case "INT?": + case "INT32?": + return typeof(int?); + case "INT[]": + case "INT32[]": + return typeof(int[]); + case "INT?[]": + case "INT32?[]": + return typeof(int?[]); + case "LIST": + case "LIST": + return typeof(List); + case "LIST": + case "LIST": + return typeof(List); + + case "LONG": + case "INT64": + return typeof(long); + case "LONG?": + case "INT64?": + return typeof(long?); + case "LONG[]": + case "INT64[]": + return typeof(long[]); + case "LONG?[]": + case "INT64?[]": + return typeof(long?[]); + case "LIST": + case "LIST": + return typeof(List); + case "LIST": + case "LIST": + return typeof(List); + + case "FLOAT": + case "SINGLE": + return typeof(float); + case "FLOAT?": + case "SINGLE?": + return typeof(float?); + case "FLOAT[]": + case "SINGLE[]": + return typeof(float[]); + case "FLOAT?[]": + case "SINGLE?[]": + return typeof(float?[]); + case "LIST": + case "LIST": + return typeof(List); + case "LIST": + case "LIST": + return typeof(List); + + case "DOUBLE": + return typeof(double); + case "DOUBLE?": + return typeof(double?); + case "DOUBLE[]": + return typeof(double[]); + case "DOUBLE?[]": + return typeof(double?[]); + case "LIST": + return typeof(List); + case "LIST": + return typeof(List); + + case "DECIMAL": + return typeof(decimal); + case "DECIMAL?": + return typeof(decimal?); + case "DECIMAL[]": + return typeof(decimal[]); + case "DECIMAL?[]": + return typeof(decimal?[]); + case "LIST": + return typeof(List); + case "LIST": + return typeof(List); + + case "DATETIME": + return typeof(DateTime); + case "DATETIME?": + return typeof(DateTime?); + case "DATETIME[]": + return typeof(DateTime[]); + case "DATETIME?[]": + return typeof(DateTime?[]); + case "LIST": + return typeof(List); + case "LIST": + return typeof(List); + + case "GUID": + return typeof(Guid); + case "GUID?": + return typeof(Guid?); + case "GUID[]": + return typeof(Guid[]); + case "GUID?[]": + return typeof(Guid?[]); + case "LIST": + return typeof(List); + case "LIST": + return typeof(List); + + case "BOOL": + return typeof(bool); + case "BOOL?": + return typeof(bool?); + case "BOOL[]": + return typeof(bool[]); + case "BOOL?[]": + return typeof(bool?[]); + case "LIST": + return typeof(List); + case "LIST": + return typeof(List); + + case "STRING": + return typeof(string); + case "STRING[]": + return typeof(string[]); + case "LIST": + return typeof(List); + + default: + break; + } + + return Type.GetType(name); + } + #endregion + } + + /// + /// 从 Header 自动反序列化 QueryFilter 并绑定 + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public class FromFilterAttribute : Attribute, IBindingSourceMetadata, IModelNameProvider, IBinderTypeProviderMetadata + { + public FromFilterAttribute() + { + } + + public BindingSource BindingSource => BindingSource.Header; + + public string Name { get; set; } + + public Type BinderType => typeof(FilterHeaderBinder); + } + + +} diff --git a/Tiobon.Core.Common/Attribute/QueryFilter.cs b/Tiobon.Core.Common/Attribute/QueryFilter.cs new file mode 100644 index 00000000..bfa45dc4 --- /dev/null +++ b/Tiobon.Core.Common/Attribute/QueryFilter.cs @@ -0,0 +1,89 @@ +using System.ComponentModel.DataAnnotations; + +namespace Tiobon.Core.Common +{ + /// + /// 动态查询条件 + /// + public class QueryFilter + { + private int _pageIndex; + /// + /// 起始位置(e.g. 0) + /// + [Required] + public int PageIndex + { + get { return _pageIndex; } + set + { + //前端默认从分页显示默认1开始,所以后端需要-1 + if (value >= 1) + value -= 1; + _pageIndex = value; + } + } + /// + /// 每页数量(e.g. 10) + /// + [Required] + public int PageSize { get; set; } + private string _predicate; + /// + /// 查询条件表达式(e.g. LoginName.Contains(@0)) + /// + public string Predicate + { + get { return _predicate; } + set + { + //前端默认从分页显示默认1开始,所以后端需要-1 + if (value == "1=1") + value = null; + _predicate = value; + } + } + /// + /// 查询条件表达式参数(e.g. LoginName) + /// + public object[] PredicateValues { get; set; } + /// + /// 排序条件表达式(e.g. LoginName ASC,Name DESC) + /// + public string Sorting { get; set; } + ///// + ///// 患者关键字(姓名、别名、拼音、五笔)模糊查询 + ///// + //public string PatientKey { get; set; } + ///// + ///// 报表患者过滤条件 + ///// + //public PatientFilter PatientFilter { get; set; } + ///// + ///// 分组条件(e.g. [10,20,30]) + ///// + //public List GroupValues { get; set; } + ///// + ///// 导出字段,按照顺序填写(e.g. [{ Key: 'PatientNameFull', Name: '患者姓名' }, { Key: 'DeviceCode', Name: '设备编号' }]) + ///// + //public List ExportFields { get; set; } + ///// + ///// 导出字段的宽度(默认20),按照顺序与字段一一对应填写(e.g. [20,50,20]) + ///// + //public List ExportFieldsWidth { get; set; } + /// + /// 缺省值 + /// + public static QueryFilter Default => new QueryFilter + { + PageIndex = 1, + PageSize = 100000, + Sorting = string.Empty, + Predicate = string.Empty, + PredicateValues = Array.Empty(), + //GroupValues = new List(), + //ExportFields = new List(), + //ExportFieldsWidth = new List() + }; + } +} diff --git a/Tiobon.Core.Common/Extensions/ExpressionCombiner.cs b/Tiobon.Core.Common/Extensions/ExpressionCombiner.cs new file mode 100644 index 00000000..c5eab14f --- /dev/null +++ b/Tiobon.Core.Common/Extensions/ExpressionCombiner.cs @@ -0,0 +1,56 @@ +using System.Linq.Expressions; + +namespace Tiobon.Core.Common.Helper; + +public static class ExpressionCombiner +{ + public static Expression> Combine(Expression> expression1, Expression> expression2) + { + if (expression1 == null && expression2 == null) + { + return null; + } + + if (expression1 == null) + { + return expression2; + } + + if (expression2 == null) + { + return expression1; + } + + var parameter = Expression.Parameter(typeof(T)); + + var leftVisitor = new ReplaceExpressionVisitor(expression1.Parameters[0], parameter); + var left = leftVisitor.Visit(expression1.Body); + + var rightVisitor = new ReplaceExpressionVisitor(expression2.Parameters[0], parameter); + var right = rightVisitor.Visit(expression2.Body); + + return Expression.Lambda>(Expression.AndAlso(left, right), parameter); + } + + class ReplaceExpressionVisitor : ExpressionVisitor + { + private readonly Expression _oldValue; + private readonly Expression _newValue; + + public ReplaceExpressionVisitor(Expression oldValue, Expression newValue) + { + _oldValue = oldValue; + _newValue = newValue; + } + + public override Expression Visit(Expression node) + { + if (node == _oldValue) + { + return _newValue; + } + + return base.Visit(node); + } + } +} \ No newline at end of file diff --git a/Tiobon.Core.Common/Seed/FrameSeed.cs b/Tiobon.Core.Common/Seed/FrameSeed.cs index 7aac5c52..34a4cae1 100644 --- a/Tiobon.Core.Common/Seed/FrameSeed.cs +++ b/Tiobon.Core.Common/Seed/FrameSeed.cs @@ -9,6 +9,7 @@ namespace Tiobon.Core.Common.Seed public class FrameSeed { + public static string path = AppDomain.CurrentDomain.BaseDirectory.Replace("Tiobon.Core.Api\\bin\\Debug\\net8.0\\", null); /// /// 生成Controller层 /// @@ -19,7 +20,7 @@ namespace Tiobon.Core.Common.Seed /// public static bool CreateControllers(SqlSugarScope sqlSugarClient, string ConnId = null, bool isMuti = false, string[] tableNames = null) { - Create_Controller_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Tiobon.Core.Api\Controllers", "Tiobon.Core.Api.Controllers", tableNames, "", isMuti); + Create_Controller_ClassFileByDBTalbe(sqlSugarClient, ConnId, path + $@"Tiobon.Core.Api\Controllers", "Tiobon.Core.Api.Controllers", tableNames, "", isMuti); return true; } @@ -33,7 +34,7 @@ namespace Tiobon.Core.Common.Seed /// public static bool CreateModels(SqlSugarScope sqlSugarClient, string ConnId, bool isMuti = false, string[] tableNames = null) { - Create_Model_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Tiobon.Core.Model", "Tiobon.Core.Model.Models", tableNames, "", isMuti); + Create_Model_ClassFileByDBTalbe(sqlSugarClient, ConnId, path + $@"Tiobon.Core.Model", "Tiobon.Core.Model.Models", tableNames, "", isMuti); return true; } @@ -47,7 +48,7 @@ namespace Tiobon.Core.Common.Seed /// public static bool CreateIRepositorys(SqlSugarScope sqlSugarClient, string ConnId, bool isMuti = false, string[] tableNames = null) { - Create_IRepository_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Tiobon.Core.IRepository", "Tiobon.Core.IRepository", tableNames, "", isMuti); + Create_IRepository_ClassFileByDBTalbe(sqlSugarClient, ConnId, path + $@"Tiobon.Core.IRepository", "Tiobon.Core.IRepository", tableNames, "", isMuti); return true; } @@ -63,7 +64,7 @@ namespace Tiobon.Core.Common.Seed /// public static bool CreateIServices(SqlSugarScope sqlSugarClient, string ConnId, bool isMuti = false, string[] tableNames = null) { - Create_IServices_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Tiobon.Core.IServices", "Tiobon.Core.IServices", tableNames, "", isMuti); + Create_IServices_ClassFileByDBTalbe(sqlSugarClient, ConnId, path + $@"Tiobon.Core.IServices", "Tiobon.Core.IServices", tableNames, "", isMuti); return true; } @@ -79,7 +80,7 @@ namespace Tiobon.Core.Common.Seed /// public static bool CreateRepository(SqlSugarScope sqlSugarClient, string ConnId, bool isMuti = false, string[] tableNames = null) { - Create_Repository_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Tiobon.Core.Repository", "Tiobon.Core.Repository", tableNames, "", isMuti); + Create_Repository_ClassFileByDBTalbe(sqlSugarClient, ConnId, path + $@"Tiobon.Core.Repository", "Tiobon.Core.Repository", tableNames, "", isMuti); return true; } @@ -95,7 +96,7 @@ namespace Tiobon.Core.Common.Seed /// public static bool CreateServices(SqlSugarScope sqlSugarClient, string ConnId, bool isMuti = false, string[] tableNames = null) { - Create_Services_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Tiobon.Core.Services", "Tiobon.Core.Services", tableNames, "", isMuti); + Create_Services_ClassFileByDBTalbe(sqlSugarClient, ConnId, path + $@"Tiobon.Core.Services", "Tiobon.Core.Services", tableNames, "", isMuti); return true; } @@ -155,7 +156,7 @@ namespace Tiobon.Core.Common.Seed #region 查询 [HttpGet] - public async Task>> Get(int page = 1, string key = """",int intPageSize = 50) + public async Task>> Get(int page = 1, string key = """",int pageSize = 50) { if (string.IsNullOrEmpty(key) || string.IsNullOrWhiteSpace(key)) key = """"; @@ -166,7 +167,7 @@ namespace Tiobon.Core.Common.Seed { msg = ""获取成功"", success = true, - response = await _{ClassName}Services.QueryPage(whereExpression, page, intPageSize) + response = await _{ClassName}Services.QueryPage(whereExpression, page, pageSize) }; } diff --git a/Tiobon.Core.IServices/BASE/IBaseServices.cs b/Tiobon.Core.IServices/BASE/IBaseServices.cs index f1210c8b..fabbe38d 100644 --- a/Tiobon.Core.IServices/BASE/IBaseServices.cs +++ b/Tiobon.Core.IServices/BASE/IBaseServices.cs @@ -1,6 +1,7 @@ using System.Data; using System.Linq.Expressions; using SqlSugar; +using Tiobon.Core.Common; using Tiobon.Core.Model; namespace Tiobon.Core.IServices.BASE @@ -51,6 +52,7 @@ namespace Tiobon.Core.IServices.BASE Task> QueryPage(Expression> whereExpression, int pageIndex = 1, int pageSize = 20, string orderByFields = null); + Task> QueryFilterPage([FromFilter] QueryFilter filter); Task> QueryMuch( Expression> joinExpression, diff --git a/Tiobon.Core.IServices/IGhra_GradeServices.cs b/Tiobon.Core.IServices/IGhra_GradeServices.cs new file mode 100644 index 00000000..d317996e --- /dev/null +++ b/Tiobon.Core.IServices/IGhra_GradeServices.cs @@ -0,0 +1,12 @@ +using Tiobon.Core.IServices.BASE; +using Tiobon.Core.Model.Models; + +namespace Tiobon.Core.IServices +{ + /// + /// IGhra_GradeServices + /// + public interface IGhra_GradeServices :IBaseServices + { + } +} \ No newline at end of file diff --git a/Tiobon.Core.Model/Ghra_Grade.cs b/Tiobon.Core.Model/Ghra_Grade.cs new file mode 100644 index 00000000..8297a392 --- /dev/null +++ b/Tiobon.Core.Model/Ghra_Grade.cs @@ -0,0 +1,194 @@ +using System; +using System.Linq; +using System.Text; +using SqlSugar; + + +namespace Tiobon.Core.Model.Models +{ + /// + /// + /// + [SugarTable( "Ghra_Grade", "wmtiobon_mssql_main")] + public class Ghra_Grade + { + public Ghra_Grade() + { + } + /// + /// Desc: + /// Default: + /// Nullable:False + /// + [SugarColumn(IsPrimaryKey=true,IsIdentity=true)] + public int Id { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string GradeNo { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string GradeName { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string MKey { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public int? DataBelongID { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string RemarkSz { get; set; } + /// + /// Desc: + /// Default:1 + /// Nullable:False + /// + public int SortNo { get; set; } + /// + /// Desc: + /// Default:1 + /// Nullable:False + /// + public int IsEnable { get; set; } + /// + /// Desc: + /// Default:1 + /// Nullable:False + /// + public int IsDefault { get; set; } + /// + /// Desc: + /// Default:0 + /// Nullable:True + /// + public long? OperateLogID { get; set; } + /// + /// Desc: + /// Default:0 + /// Nullable:False + /// + public int CreateBy { get; set; } + /// + /// Desc: + /// Default:DateTime.Now + /// Nullable:False + /// + public DateTime CreateTime { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string CreateProg { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string CreateIP { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public int? UpdateBy { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public DateTime? UpdateTime { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string UpdateProg { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string UpdateIP { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string Reverse1 { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string Reverse2 { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string Reverse3 { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string Reverse4 { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string Reverse5 { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string Reverse6 { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string Reverse7 { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string Reverse8 { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string Reverse9 { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public int? ReverseI1 { get; set; } + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public int? ReverseI2 { get; set; } + } +} \ No newline at end of file diff --git a/Tiobon.Core.Repository/BASE/BaseRepository.cs b/Tiobon.Core.Repository/BASE/BaseRepository.cs index 3227bab3..e4ef3be3 100644 --- a/Tiobon.Core.Repository/BASE/BaseRepository.cs +++ b/Tiobon.Core.Repository/BASE/BaseRepository.cs @@ -1,4 +1,5 @@ using System.Data; +using System.Linq.Dynamic.Core; using System.Linq.Expressions; using System.Reflection; using SqlSugar; @@ -9,6 +10,7 @@ using Tiobon.Core.Model; using Tiobon.Core.Model.Models; using Tiobon.Core.Model.Tenants; using Tiobon.Core.Repository.UnitOfWorks; +using static Org.BouncyCastle.Math.EC.ECCurve; namespace Tiobon.Core.Repository.Base { @@ -434,6 +436,33 @@ namespace Tiobon.Core.Repository.Base return new PageModel(pageIndex, totalCount, pageSize, list); } + /// + /// 分页查询[使用版本,其他分页未测试] + /// + /// 条件表达式 + /// 页码(下标0) + /// 页大小 + /// 排序字段,如name asc,age desc + /// + public async Task> QueryFilterPage([FromFilter] QueryFilter filter) + { + RefAsync totalCount = 0; + var query = _db.Queryable(); + if (!filter.Predicate.IsNullOrEmpty()) + { + for (int i = 0; i < filter.PredicateValues.Length; i++) + { + filter.Predicate = filter.Predicate.Replace($"@{i}", filter.PredicateValues[i].ToString()); + } + query = query.Where(filter.Predicate); + } + + var list = await query + .OrderByIF(!string.IsNullOrEmpty(filter.Sorting), filter.Sorting) + .ToPageListAsync(filter.PageIndex, filter.PageSize, totalCount); + + return new PageModel(filter.PageIndex, totalCount, filter.PageSize, list); + } /// @@ -616,6 +645,44 @@ namespace Tiobon.Core.Repository.Base return await _db.Queryable().In(objId).SplitTable(tabs => tabs).SingleAsync(); } + /// + /// 数据过滤用的查询表达式构建 + /// + /// + /// + protected Expression> CreateFilterExpression() + where TEntity : class + { + Expression> expression = null; + + //if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))) + //{ + // Expression> softDeleteFilter = e => !((ISoftDelete)e).IsDeleted; + // expression = expression == null ? softDeleteFilter : CombineExpressions(expression, softDeleteFilter); + //} + + if (typeof(IMayHaveTenant).IsAssignableFrom(typeof(TEntity)))// && IsMayHaveTenantFilterEnabled) + { + Expression> mayHaveTenantFilter = + e => ((IMayHaveTenant)e).IsEnable == 1; + expression = expression == null + ? mayHaveTenantFilter + : CombineExpressions(expression, mayHaveTenantFilter); + } + + return expression; + } + protected Expression> CombineExpressions( + Expression> expression1, Expression> expression2) + { + return Common.Helper.ExpressionCombiner.Combine(expression1, expression2); + } + #endregion } + + public interface IMayHaveTenant + { + int IsEnable { get; set; } + } } \ No newline at end of file diff --git a/Tiobon.Core.Repository/BASE/IBaseRepository.cs b/Tiobon.Core.Repository/BASE/IBaseRepository.cs index ca0be01f..f781ac71 100644 --- a/Tiobon.Core.Repository/BASE/IBaseRepository.cs +++ b/Tiobon.Core.Repository/BASE/IBaseRepository.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Data; using System.Linq.Expressions; using System.Threading.Tasks; +using Tiobon.Core.Common; namespace Tiobon.Core.IRepository.Base { @@ -155,6 +156,16 @@ namespace Tiobon.Core.IRepository.Base /// Task> QueryPage(Expression> whereExpression, int pageIndex = 1, int pageSize = 20, string orderByFields = null); + /// + /// 根据表达式,排序字段,分页查询 + /// + /// + /// + /// + /// + /// + Task> QueryFilterPage([FromFilter] QueryFilter filter); + /// /// 三表联查 /// diff --git a/Tiobon.Core.Services/BASE/BaseServices.cs b/Tiobon.Core.Services/BASE/BaseServices.cs index b0178d45..7e92ed25 100644 --- a/Tiobon.Core.Services/BASE/BaseServices.cs +++ b/Tiobon.Core.Services/BASE/BaseServices.cs @@ -1,6 +1,7 @@ using System.Data; using System.Linq.Expressions; using SqlSugar; +using Tiobon.Core.Common; using Tiobon.Core.Common.Helper; using Tiobon.Core.IRepository.Base; using Tiobon.Core.IServices.BASE; @@ -315,6 +316,11 @@ namespace Tiobon.Core.Services.BASE pageIndex, pageSize, orderByFileds); } + public async Task> QueryFilterPage([FromFilter] QueryFilter filter) + { + return await BaseDal.QueryFilterPage(filter); + } + public async Task> QueryMuch(Expression> joinExpression, Expression> selectExpression, Expression> whereLambda = null) where T : class, new() { return await BaseDal.QueryMuch(joinExpression, selectExpression, whereLambda); diff --git a/Tiobon.Core.Services/Ghra_GradeServices.cs b/Tiobon.Core.Services/Ghra_GradeServices.cs new file mode 100644 index 00000000..ce42ea2c --- /dev/null +++ b/Tiobon.Core.Services/Ghra_GradeServices.cs @@ -0,0 +1,18 @@ + +using Tiobon.Core.IServices; +using Tiobon.Core.Model.Models; +using Tiobon.Core.Services.BASE; +using Tiobon.Core.IRepository.Base; + +namespace Tiobon.Core.Services +{ + public class Ghra_GradeServices : BaseServices, IGhra_GradeServices + { + private readonly IBaseRepository _dal; + public Ghra_GradeServices(IBaseRepository dal) + { + this._dal = dal; + base.BaseDal = dal; + } + } +} \ No newline at end of file