diff --git a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj index ae198a5b..0781edd6 100644 --- a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj +++ b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj @@ -37,7 +37,7 @@ - + diff --git a/Admin.NET/Admin.NET.Core/Attribute/OwnerOrgAttribute.cs b/Admin.NET/Admin.NET.Core/Attribute/OwnerOrgAttribute.cs new file mode 100644 index 00000000..468272cb --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Attribute/OwnerOrgAttribute.cs @@ -0,0 +1,16 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 所属机构数据权限 +/// +[SuppressSniffer] +[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)] +public class OwnerOrgAttribute : Attribute +{ +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Attribute/OwnerUserAttribute.cs b/Admin.NET/Admin.NET.Core/Attribute/OwnerUserAttribute.cs new file mode 100644 index 00000000..4fc7c69f --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Attribute/OwnerUserAttribute.cs @@ -0,0 +1,16 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 所属用户数据权限 +/// +[SuppressSniffer] +[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)] +public class OwnerUserAttribute : Attribute +{ +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Const/CommonConst.cs b/Admin.NET/Admin.NET.Core/Const/CommonConst.cs index dd0ba083..bfecf5e7 100644 --- a/Admin.NET/Admin.NET.Core/Const/CommonConst.cs +++ b/Admin.NET/Admin.NET.Core/Const/CommonConst.cs @@ -87,6 +87,11 @@ public class CommonConst /// public const string SysValidationLog = "sys_validation_log"; + /// + /// 行政区域同步层级 1-省级,2-市级,3-区县级,4-街道级,5-村级 + /// + public const string SysRegionSyncLevel = "sys_region_sync_level"; + /// /// 日志保留天数 /// diff --git a/Admin.NET/Admin.NET.Core/Const/ConfigConst.cs b/Admin.NET/Admin.NET.Core/Const/ConfigConst.cs new file mode 100644 index 00000000..ec33dabb --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Const/ConfigConst.cs @@ -0,0 +1,58 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 配置常量 +/// +public class ConfigConst +{ + /// + /// WebConfig 分组 + /// + public const string SysWebConfigGroup = "WebConfig"; + + /// + /// 系统图标 + /// + public const string SysWebLogo = "sys_web_logo"; + + /// + /// 系统主标题 + /// + public const string SysWebTitle = "sys_web_title"; + + /// + /// 系统副标题 + /// + public const string SysWebViceTitle = "sys_web_viceTitle"; + + /// + /// 系统描述 + /// + public const string SysWebViceDesc = "sys_web_viceDesc"; + + /// + /// 水印内容 + /// + public const string SysWebWatermark = "sys_web_watermark"; + + /// + /// 版权说明 + /// + public const string SysWebCopyright = "sys_web_copyright"; + + /// + /// ICP备案号 + /// + public const string SysWebIcp = "sys_web_icp"; + + /// + /// ICP地址 + /// + public const string SysWebIcpUrl = "sys_web_icpUrl"; +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Entity/EntityBase.cs b/Admin.NET/Admin.NET.Core/Entity/EntityBase.cs index d000be13..56c2fa70 100644 --- a/Admin.NET/Admin.NET.Core/Entity/EntityBase.cs +++ b/Admin.NET/Admin.NET.Core/Entity/EntityBase.cs @@ -40,6 +40,7 @@ public abstract class EntityBase : EntityBaseId, IDeletedFilter /// 创建者Id /// [SugarColumn(ColumnDescription = "创建者Id", IsOnlyIgnoreUpdate = true)] + [OwnerUser] public virtual long? CreateUserId { get; set; } ///// @@ -92,6 +93,7 @@ public abstract class EntityBaseData : EntityBase, IOrgIdFilter /// 创建者部门Id /// [SugarColumn(ColumnDescription = "创建者部门Id", IsOnlyIgnoreUpdate = true)] + [OwnerOrg] public virtual long? CreateOrgId { get; set; } /// diff --git a/Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs b/Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs index 3bf74c86..61e5016b 100644 --- a/Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs +++ b/Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs @@ -679,6 +679,24 @@ public enum ErrorCodeEnum [ErrorCodeItemMetadata("已有相同编码或名称")] R2002, + /// + /// 行政区代码只能为6、9或12位 + /// + [ErrorCodeItemMetadata("行政区代码只能为6、9或12位")] + R2003, + + /// + /// 父节点不能为自己的子节点 + /// + [ErrorCodeItemMetadata("父节点不能为自己的子节点")] + R2004, + + /// + /// 同步国家统计局数据异常,请稍后重试 + /// + [ErrorCodeItemMetadata("同步国家统计局数据异常,请稍后重试")] + R2005, + /// /// 默认租户状态禁止修改 /// diff --git a/Admin.NET/Admin.NET.Core/Enum/FilterLogicEnum.cs b/Admin.NET/Admin.NET.Core/Enum/FilterLogicEnum.cs new file mode 100644 index 00000000..5e898f2f --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Enum/FilterLogicEnum.cs @@ -0,0 +1,32 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 过滤条件 +/// +[Description("过滤条件")] +public enum FilterLogicEnum +{ + /// + /// 并且 + /// + [Description("并且")] + And, + + /// + /// 或者 + /// + [Description("或者")] + Or, + + /// + /// 异或 + /// + [Description("异或")] + Xor +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Enum/FilterOperatorEnum.cs b/Admin.NET/Admin.NET.Core/Enum/FilterOperatorEnum.cs new file mode 100644 index 00000000..892619b8 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Enum/FilterOperatorEnum.cs @@ -0,0 +1,68 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 过滤逻辑运算符 +/// +[Description("过滤逻辑运算符")] +public enum FilterOperatorEnum +{ + /// + /// 等于(=) + /// + [Description("等于")] + EQ, + + /// + /// 不等于(!=) + /// + [Description("不等于")] + NEQ, + + /// + /// 小于(<) + /// + [Description("小于")] + LT, + + /// + /// 小于等于(<=) + /// + [Description("小于等于")] + LTE, + + /// + /// 大于(>) + /// + [Description("大于")] + GT, + + /// + /// 大于等于(>=) + /// + [Description("大于等于")] + GTE, + + /// + /// 开始包含 + /// + [Description("开始包含")] + StartsWith, + + /// + /// 末尾包含 + /// + [Description("末尾包含")] + EndsWith, + + /// + /// 包含 + /// + [Description("包含")] + Contains +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/EventBus/AppEventSubscriber.cs b/Admin.NET/Admin.NET.Core/EventBus/AppEventSubscriber.cs index 2a438056..92f27f51 100644 --- a/Admin.NET/Admin.NET.Core/EventBus/AppEventSubscriber.cs +++ b/Admin.NET/Admin.NET.Core/EventBus/AppEventSubscriber.cs @@ -42,7 +42,8 @@ public class AppEventSubscriber : IEventSubscriber, ISingleton, IDisposable //var mailTemp = File.ReadAllText(mailTempPath); //var mail = await _serviceScope.ServiceProvider.GetRequiredService().RunCompileFromCachedAsync(mailTemp, ); - var title = "Admin.NET 系统异常"; + var webTitle = await _serviceScope.ServiceProvider.GetRequiredService().GetConfigValue(ConfigConst.SysWebTitle); + var title = $"{webTitle} 系统异常"; await _serviceScope.ServiceProvider.GetRequiredService().SendEmail(JSON.Serialize(context.Source.Payload), title); } diff --git a/Admin.NET/Admin.NET.Core/Extension/HttpContextExtension.cs b/Admin.NET/Admin.NET.Core/Extension/HttpContextExtension.cs new file mode 100644 index 00000000..88074a71 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Extension/HttpContextExtension.cs @@ -0,0 +1,94 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using Microsoft.AspNetCore.Authentication; + +namespace Admin.NET.Core; + +public static class HttpContextExtension +{ + public static async Task GetExternalProvidersAsync(this HttpContext context) + { + ArgumentNullException.ThrowIfNull(context); + + var schemes = context.RequestServices.GetRequiredService(); + + return (from scheme in await schemes.GetAllSchemesAsync() + where !string.IsNullOrEmpty(scheme.DisplayName) + select scheme).ToArray(); + } + + public static async Task IsProviderSupportedAsync(this HttpContext context, string provider) + { + ArgumentNullException.ThrowIfNull(context); + + return (from scheme in await context.GetExternalProvidersAsync() + where string.Equals(scheme.Name, provider, StringComparison.OrdinalIgnoreCase) + select scheme).Any(); + } + + /// + /// 获取设备信息 + /// + /// + /// + public static string GetClientDeviceInfo(this HttpContext context) + { + ArgumentNullException.ThrowIfNull(context); + + return CommonUtil.GetClientDeviceInfo(context.Request.Headers.UserAgent); + } + + /// + /// 获取浏览器信息 + /// + /// + /// + public static string GetClientBrowser(this HttpContext context) + { + ArgumentNullException.ThrowIfNull(context); + + string userAgent = context.Request.Headers.UserAgent; + try + { + if (userAgent != null) + { + var client = Parser.GetDefault().Parse(userAgent); + if (client.Device.IsSpider) + return "爬虫"; + return $"{client.UA.Family} {client.UA.Major}.{client.UA.Minor} / {client.Device.Family}"; + } + } + catch + { } + return "未知"; + } + + /// + /// 获取操作系统信息 + /// + /// + /// + public static string GetClientOs(this HttpContext context) + { + ArgumentNullException.ThrowIfNull(context); + + string userAgent = context.Request.Headers.UserAgent; + try + { + if (userAgent != null) + { + var client = Parser.GetDefault().Parse(userAgent); + if (client.Device.IsSpider) + return "爬虫"; + return $"{client.OS.Family} {client.OS.Major} {client.OS.Minor}"; + } + } + catch + { } + return "未知"; + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Extension/SqlSugarExtension.cs b/Admin.NET/Admin.NET.Core/Extension/SqlSugarExtension.cs new file mode 100644 index 00000000..7b9a7af5 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Extension/SqlSugarExtension.cs @@ -0,0 +1,294 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using System.Text.Json; + +namespace Admin.NET.Core; + +/// +/// Sqlsugar 动态查询扩展方法 +/// +public static class SqlSugarExtension +{ + public static ISugarQueryable SearchBy(this ISugarQueryable queryable, BaseFilter filter) + { + return queryable.SearchByKeyword(filter.Keyword) + .AdvancedSearch(filter.Search) + .AdvancedFilter(filter.Filter); + } + + public static ISugarQueryable SearchByKeyword(this ISugarQueryable queryable, string keyword) + { + return queryable.AdvancedSearch(new Search { Keyword = keyword }); + } + + public static ISugarQueryable AdvancedSearch(this ISugarQueryable queryable, Search search) + { + if (!string.IsNullOrWhiteSpace(search?.Keyword)) + { + var paramExpr = Expression.Parameter(typeof(T)); + + Expression right = Expression.Constant(false); + + if (search.Fields?.Any() is true) + { + foreach (string field in search.Fields) + { + MemberExpression propertyExpr = GetPropertyExpression(field, paramExpr); + + var left = AddSearchPropertyByKeyword(propertyExpr, search.Keyword); + + right = Expression.Or(left, right); + } + } + else + { + var properties = typeof(T).GetProperties() + .Where(prop => Nullable.GetUnderlyingType(prop.PropertyType) == null + && !prop.PropertyType.IsEnum + && Type.GetTypeCode(prop.PropertyType) != TypeCode.Object); + + foreach (var property in properties) + { + var propertyExpr = Expression.Property(paramExpr, property); + + var left = AddSearchPropertyByKeyword(propertyExpr, search.Keyword); + + right = Expression.Or(left, right); + } + } + + var lambda = Expression.Lambda>(right, paramExpr); + + return queryable.Where(lambda); + } + + return queryable; + } + + public static ISugarQueryable AdvancedFilter(this ISugarQueryable queryable, Filter filter) + { + if (filter is not null) + { + var parameter = Expression.Parameter(typeof(T)); + + Expression binaryExpresioFilter; + + if (filter.Logic.HasValue) + { + if (filter.Filters is null) throw new ArgumentException("The Filters attribute is required when declaring a logic"); + binaryExpresioFilter = CreateFilterExpression(filter.Logic.Value, filter.Filters, parameter); + } + else + { + var filterValid = GetValidFilter(filter); + binaryExpresioFilter = CreateFilterExpression(filterValid.Field!, filterValid.Operator.Value, filterValid.Value, parameter); + } + + var lambda = Expression.Lambda>(binaryExpresioFilter, parameter); + + return queryable.Where(lambda); + } + return queryable; + } + + private static Expression CombineFilter( + FilterLogicEnum filterLogic, + Expression bExpresionBase, + Expression bExpresion) + { + return filterLogic switch + { + FilterLogicEnum.And => Expression.And(bExpresionBase, bExpresion), + FilterLogicEnum.Or => Expression.Or(bExpresionBase, bExpresion), + FilterLogicEnum.Xor => Expression.ExclusiveOr(bExpresionBase, bExpresion), + _ => throw new ArgumentException("FilterLogic is not valid.", nameof(filterLogic)), + }; + } + + private static Filter GetValidFilter(Filter filter) + { + if (string.IsNullOrEmpty(filter.Field)) throw new ArgumentException("The field attribute is required when declaring a filter"); + if (filter.Operator.IsNullOrEmpty()) throw new ArgumentException("The Operator attribute is required when declaring a filter"); + return filter; + } + + private static Expression CreateFilterExpression( + FilterLogicEnum filterLogic, + IEnumerable filters, + ParameterExpression parameter) + { + Expression filterExpression = default!; + + foreach (var filter in filters) + { + Expression bExpresionFilter; + + if (filter.Logic.HasValue) + { + if (filter.Filters is null) throw new ArgumentException("The Filters attribute is required when declaring a logic"); + bExpresionFilter = CreateFilterExpression(filter.Logic.Value, filter.Filters, parameter); + } + else + { + var filterValid = GetValidFilter(filter); + bExpresionFilter = CreateFilterExpression(filterValid.Field!, filterValid.Operator.Value, filterValid.Value, parameter); + } + + filterExpression = filterExpression is null ? bExpresionFilter : CombineFilter(filterLogic, filterExpression, bExpresionFilter); + } + + return filterExpression; + } + + private static Expression CreateFilterExpression( + string field, + FilterOperatorEnum filterOperator, + object? value, + ParameterExpression parameter) + { + var propertyExpresion = GetPropertyExpression(field, parameter); + var valueExpresion = GeValuetExpression(field, value, propertyExpresion.Type); + return CreateFilterExpression(propertyExpresion, valueExpresion, filterOperator); + } + + private static Expression CreateFilterExpression( + MemberExpression memberExpression, + ConstantExpression constantExpression, + FilterOperatorEnum filterOperator) + { + return filterOperator switch + { + FilterOperatorEnum.EQ => Expression.Equal(memberExpression, constantExpression), + FilterOperatorEnum.NEQ => Expression.NotEqual(memberExpression, constantExpression), + FilterOperatorEnum.LT => Expression.LessThan(memberExpression, constantExpression), + FilterOperatorEnum.LTE => Expression.LessThanOrEqual(memberExpression, constantExpression), + FilterOperatorEnum.GT => Expression.GreaterThan(memberExpression, constantExpression), + FilterOperatorEnum.GTE => Expression.GreaterThanOrEqual(memberExpression, constantExpression), + FilterOperatorEnum.Contains => Expression.Call(memberExpression, nameof(FilterOperatorEnum.Contains), null, constantExpression), + FilterOperatorEnum.StartsWith => Expression.Call(memberExpression, nameof(FilterOperatorEnum.StartsWith), null, constantExpression), + FilterOperatorEnum.EndsWith => Expression.Call(memberExpression, nameof(FilterOperatorEnum.EndsWith), null, constantExpression), + _ => throw new ArgumentException("Filter Operator is not valid."), + }; + } + + private static string GetStringFromJsonElement(object value) + { + if (value is JsonElement) return ((JsonElement)value).GetString()!; + if (value is string) return (string)value; + return value?.ToString(); + } + + private static ConstantExpression GeValuetExpression( + string field, + object? value, + Type propertyType) + { + if (value == null) return Expression.Constant(null, propertyType); + + if (propertyType.IsEnum) + { + string? stringEnum = GetStringFromJsonElement(value); + + if (!Enum.TryParse(propertyType, stringEnum, true, out object? valueparsed)) throw new ArgumentException(string.Format("Value {0} is not valid for {1}", value, field)); + + return Expression.Constant(valueparsed, propertyType); + } + if (propertyType == typeof(long)) + { + string? stringLong = GetStringFromJsonElement(value); + + if (!long.TryParse(stringLong, out long valueparsed)) throw new ArgumentException(string.Format("Value {0} is not valid for {1}", value, field)); + + return Expression.Constant(valueparsed, propertyType); + } + + if (propertyType == typeof(Guid)) + { + string? stringGuid = GetStringFromJsonElement(value); + + if (!Guid.TryParse(stringGuid, out Guid valueparsed)) throw new ArgumentException(string.Format("Value {0} is not valid for {1}", value, field)); + + return Expression.Constant(valueparsed, propertyType); + } + + if (propertyType == typeof(string)) + { + string? text = GetStringFromJsonElement(value); + + return Expression.Constant(text, propertyType); + } + + if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?)) + { + string? text = GetStringFromJsonElement(value); + return Expression.Constant(ChangeType(text, propertyType), propertyType); + } + + return Expression.Constant(ChangeType(((JsonElement)value).GetRawText(), propertyType), propertyType); + } + + private static dynamic? ChangeType(object value, Type conversion) + { + var t = conversion; + + if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) + { + if (value == null) + { + return null; + } + + t = Nullable.GetUnderlyingType(t); + } + + return Convert.ChangeType(value, t!); + } + + private static MemberExpression GetPropertyExpression( + string propertyName, + ParameterExpression parameter) + { + Expression propertyExpression = parameter; + foreach (string member in propertyName.Split('.')) + { + propertyExpression = Expression.PropertyOrField(propertyExpression, member); + } + + return (MemberExpression)propertyExpression; + } + + private static Expression AddSearchPropertyByKeyword( + Expression propertyExpr, + string keyword, + FilterOperatorEnum operatorSearch = FilterOperatorEnum.Contains) + { + if (propertyExpr is not MemberExpression memberExpr || memberExpr.Member is not PropertyInfo property) + { + throw new ArgumentException("propertyExpr must be a property expression.", nameof(propertyExpr)); + } + + ConstantExpression constant = Expression.Constant(keyword); + + MethodInfo method = operatorSearch switch + { + FilterOperatorEnum.Contains => typeof(string).GetMethod(nameof(FilterOperatorEnum.Contains), new Type[] { typeof(string) }), + FilterOperatorEnum.StartsWith => typeof(string).GetMethod(nameof(FilterOperatorEnum.StartsWith), new Type[] { typeof(string) }), + FilterOperatorEnum.EndsWith => typeof(string).GetMethod(nameof(FilterOperatorEnum.EndsWith), new Type[] { typeof(string) }), + _ => throw new ArgumentException("Filter Operator is not valid."), + }; + + Expression selectorExpr = + property.PropertyType == typeof(string) + ? propertyExpr + : Expression.Condition( + Expression.Equal(Expression.Convert(propertyExpr, typeof(object)), Expression.Constant(null, typeof(object))), + Expression.Constant(null, typeof(string)), + Expression.Call(propertyExpr, "ToString", null, null)); + + return Expression.Call(selectorExpr, method, constant); + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Extension/SqlSugarFilterExtension.cs b/Admin.NET/Admin.NET.Core/Extension/SqlSugarFilterExtension.cs new file mode 100644 index 00000000..4018db49 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Extension/SqlSugarFilterExtension.cs @@ -0,0 +1,55 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +public static class SqlSugarFilterExtension +{ + /// + /// 根据指定Attribute获取属性 + /// + /// + /// + /// + private static List GetPropertyNames(this Type type) + where T : Attribute + { + var allProperties = type.GetProperties(); + + var properties = allProperties.Where(x => x.CustomAttributes.Any(a => a.AttributeType == typeof(T))); + + return properties.Select(x => x.Name).ToList(); + } + + /// + /// 获取过滤表达式 + /// + /// + /// + /// + /// + public static LambdaExpression GetConditionExpression(this Type type, List owners) + where T : Attribute + { + var fieldNames = type.GetPropertyNames(); + + ParameterExpression parameter = Expression.Parameter(type, "c"); + Expression right = Expression.Constant(false); + fieldNames.ForEach(filedName => + { + owners.ForEach(owner => + { + Expression left = Expression.Equal( + Expression.Property(parameter, type.GetProperty(filedName)), + Expression.Constant(owner) + ); + right = Expression.Or(left, right); + }); + }); + var finalExpression = Expression.Lambda(right, new ParameterExpression[] { parameter }); + return finalExpression; + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Hub/OnlineUserHub.cs b/Admin.NET/Admin.NET.Core/Hub/OnlineUserHub.cs index 7973e694..6e1d583e 100644 --- a/Admin.NET/Admin.NET.Core/Hub/OnlineUserHub.cs +++ b/Admin.NET/Admin.NET.Core/Hub/OnlineUserHub.cs @@ -17,6 +17,7 @@ public class OnlineUserHub : Hub { private const string GROUP_ONLINE = "GROUP_ONLINE_"; // 租户分组前缀 + private readonly UserManager _userManager; private readonly SqlSugarRepository _sysOnlineUerRep; private readonly SysMessageService _sysMessageService; private readonly IHubContext _onlineUserHubContext; @@ -27,13 +28,15 @@ public class OnlineUserHub : Hub SysMessageService sysMessageService, IHubContext onlineUserHubContext, SysCacheService sysCacheService, - SysConfigService sysConfigService) + SysConfigService sysConfigService, + UserManager userManager) { _sysOnlineUerRep = sysOnlineUerRep; _sysMessageService = sysMessageService; _onlineUserHubContext = onlineUserHubContext; _sysCacheService = sysCacheService; _sysConfigService = sysConfigService; + _userManager = userManager; } /// @@ -43,23 +46,17 @@ public class OnlineUserHub : Hub public override async Task OnConnectedAsync() { var httpContext = Context.GetHttpContext(); - var token = httpContext.Request.Query["access_token"]; - var claims = JWTEncryption.ReadJwtToken(token)?.Claims; - var client = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]); - - var userId = claims?.FirstOrDefault(u => u.Type == ClaimConst.UserId)?.Value; - var tenantId = claims?.FirstOrDefault(u => u.Type == ClaimConst.TenantId)?.Value; var user = new SysOnlineUser { ConnectionId = Context.ConnectionId, - UserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId), - UserName = claims?.FirstOrDefault(u => u.Type == ClaimConst.Account)?.Value, - RealName = claims?.FirstOrDefault(u => u.Type == ClaimConst.RealName)?.Value, + UserId = _userManager.UserId, + UserName = _userManager.Account, + RealName = _userManager.RealName, Time = DateTime.Now, - Ip = httpContext.Connection.RemoteIpAddress.MapToIPv4().ToString(), - Browser = client.UA.Family + client.UA.Major, - Os = client.OS.Family + client.OS.Major, - TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : Convert.ToInt64(tenantId), + Ip = httpContext.GetRemoteIpAddressToIPv4(true), + Browser = httpContext.GetClientBrowser(), + Os = httpContext.GetClientOs(), + TenantId = _userManager.TenantId, }; await _sysOnlineUerRep.InsertAsync(user); @@ -70,7 +67,7 @@ public class OnlineUserHub : Hub } else { - var device = (client.UA.Family + client.UA.Major + client.OS.Family + client.OS.Major).Trim(); + var device = httpContext.GetClientDeviceInfo().Trim(); _sysCacheService.Set(CacheConst.KeyUserOnline + user.UserId + device, user); } @@ -98,7 +95,6 @@ public class OnlineUserHub : Hub if (string.IsNullOrEmpty(Context.ConnectionId)) return; var httpContext = Context.GetHttpContext(); - var client = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]); var user = await _sysOnlineUerRep.AsQueryable().Filter("", true).FirstAsync(u => u.ConnectionId == Context.ConnectionId); if (user == null) return; @@ -112,7 +108,7 @@ public class OnlineUserHub : Hub } else { - var device = (client.UA.Family + client.UA.Major + client.OS.Family + client.OS.Major).Trim(); + var device = httpContext.GetClientDeviceInfo().Trim(); _sysCacheService.Remove(CacheConst.KeyUserOnline + user.UserId + device); } diff --git a/Admin.NET/Admin.NET.Core/Job/LogJob.cs b/Admin.NET/Admin.NET.Core/Job/LogJob.cs index 752791e0..f29036d2 100644 --- a/Admin.NET/Admin.NET.Core/Job/LogJob.cs +++ b/Admin.NET/Admin.NET.Core/Job/LogJob.cs @@ -36,12 +36,13 @@ public class LogJob : IJob await logOpRep.CopyNew().AsDeleteable().Where(u => (DateTime)u.CreateTime < DateTime.Now.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除操作日志 await logDiffRep.CopyNew().AsDeleteable().Where(u => (DateTime)u.CreateTime < DateTime.Now.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除差异日志 + string msg = $"【{DateTime.Now}】清理系统日志成功,删除 {daysAgo} 天前的日志数据!"; var originColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Yellow; - Console.WriteLine($"【{DateTime.Now}】清理系统日志({daysAgo}天前)"); + Console.WriteLine(msg); Console.ForegroundColor = originColor; // 自定义日志 - _logger.LogInformation($"【{DateTime.Now}】清理系统日志..."); + _logger.LogInformation(msg); } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Job/OnlineUserJob.cs b/Admin.NET/Admin.NET.Core/Job/OnlineUserJob.cs index e1e929ea..e5c333c2 100644 --- a/Admin.NET/Admin.NET.Core/Job/OnlineUserJob.cs +++ b/Admin.NET/Admin.NET.Core/Job/OnlineUserJob.cs @@ -31,15 +31,16 @@ public class OnlineUserJob : IJob var rep = serviceScope.ServiceProvider.GetRequiredService>(); await rep.CopyNew().AsDeleteable().ExecuteCommandAsync(stoppingToken); - var originColor = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine($"【{DateTime.Now}】清空在线用户列表"); - Console.ForegroundColor = originColor; - // 缓存租户列表 await serviceScope.ServiceProvider.GetRequiredService().CacheTenant(); + string msg = $"【{DateTime.Now}】清理在线用户成功!服务已重启..."; + var originColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(msg); + Console.ForegroundColor = originColor; + // 自定义日志 - _logger.LogInformation($"【{DateTime.Now}】服务已重启..."); + _logger.LogInformation(msg); } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs b/Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs index a0928390..53b97a0e 100644 --- a/Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs +++ b/Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs @@ -32,6 +32,7 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData new SysConfig{ Id=1300000000201, Name="发送异常日志邮件", Code="sys_error_mail", Value="True", SysFlag=YesNoEnum.Y, Remark="是否发送异常日志邮件", OrderNo=110, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, new SysConfig{ Id=1300000000211, Name="开启域登录验证", Code="sys_domain_login", Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启域登录验证", OrderNo=120, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, new SysConfig{ Id=1300000000221, Name="开启数据校验日志", Code="sys_validation_log", Value="True", SysFlag=YesNoEnum.Y, Remark="是否数据校验日志", OrderNo=130, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, + new SysConfig{ Id=1300000000231, Name="行政区域同步层级", Code="sys_region_sync_level", Value="3", SysFlag=YesNoEnum.Y, Remark="行政区域同步层级 1-省级,2-市级,3-区县级,4-街道级,5-村级", OrderNo=140, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, new SysConfig{ Id=1300000000301, Name="系统主标题", Code="sys_web_title", Value="Admin.NET.Pro", SysFlag=YesNoEnum.Y, Remark="系统主标题", OrderNo=300, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, new SysConfig{ Id=1300000000311, Name="系统副标题", Code="sys_web_viceTitle", Value="Admin.NET.Pro", SysFlag=YesNoEnum.Y, Remark="系统副标题", OrderNo=310, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, new SysConfig{ Id=1300000000321, Name="系统描述", Code="sys_web_viceDesc", Value="站在巨人肩膀上的 .NET 通用权限开发框架", SysFlag=YesNoEnum.Y, Remark="系统描述", OrderNo=320, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, diff --git a/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs b/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs index 4d4af392..38013046 100644 --- a/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs @@ -275,7 +275,7 @@ public class SysAuthService : IDynamicApiController, ITransient var roleIds = await _sysUserRep.ChangeRepository>().AsQueryable() .Where(u => u.UserId == user.Id).Select(u => u.RoleId).ToListAsync(); // 获取水印文字(若系统水印为空则全局为空) - var watermarkText = await _sysConfigService.GetConfigValue("sys_web_watermark"); + var watermarkText = await _sysConfigService.GetConfigValue(ConfigConst.SysWebWatermark); if (!string.IsNullOrWhiteSpace(watermarkText)) watermarkText += $"-{user.RealName}"; // $"-{user.RealName}-{_httpContextAccessor.HttpContext.GetRemoteIp()}-{DateTime.Now}"; diff --git a/Admin.NET/Admin.NET.Core/Service/Config/Dto/InfoInput.cs b/Admin.NET/Admin.NET.Core/Service/Config/Dto/InfoInput.cs index 83813159..32df0fdf 100644 --- a/Admin.NET/Admin.NET.Core/Service/Config/Dto/InfoInput.cs +++ b/Admin.NET/Admin.NET.Core/Service/Config/Dto/InfoInput.cs @@ -16,6 +16,11 @@ public class InfoSaveInput /// public string SysLogoBase64 { get; set; } + /// + /// 系统图标文件名 + /// + public string SysLogoFileName { get; set; } + /// /// 系统主标题 /// diff --git a/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs b/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs index 3a0b1b12..ecb4f26b 100644 --- a/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs @@ -14,15 +14,12 @@ public class SysConfigService : IDynamicApiController, ITransient { private readonly SysCacheService _sysCacheService; private readonly SqlSugarRepository _sysConfigRep; - private readonly UserManager _userManager; public SysConfigService(SysCacheService sysCacheService, - SqlSugarRepository sysConfigRep, - UserManager userManager) + SqlSugarRepository sysConfigRep) { _sysCacheService = sysCacheService; _sysConfigRep = sysConfigRep; - _userManager = userManager; } /// @@ -34,7 +31,7 @@ public class SysConfigService : IDynamicApiController, ITransient public async Task> Page(PageConfigInput input) { return await _sysConfigRep.AsQueryable() - .WhereIF(!_userManager.SuperAdmin, u => u.GroupCode != "WebConfig") // 若非超管,不显示 WebConfig 分组 + .Where(u => u.GroupCode != ConfigConst.SysWebConfigGroup) // 不显示 WebConfig 分组 .WhereIF(!string.IsNullOrWhiteSpace(input.Name?.Trim()), u => u.Name.Contains(input.Name)) .WhereIF(!string.IsNullOrWhiteSpace(input.Code?.Trim()), u => u.Code.Contains(input.Code)) .WhereIF(!string.IsNullOrWhiteSpace(input.GroupCode?.Trim()), u => u.GroupCode.Equals(input.GroupCode)) @@ -186,7 +183,7 @@ public class SysConfigService : IDynamicApiController, ITransient public async Task> GetGroupList() { return await _sysConfigRep.AsQueryable() - .Where(u => u.GroupCode != "WebConfig") // 不显示 WebConfig 分组 + .Where(u => u.GroupCode != ConfigConst.SysWebConfigGroup) // 不显示 WebConfig 分组 .GroupBy(u => u.GroupCode) .Select(u => u.GroupCode).ToListAsync(); } @@ -240,14 +237,14 @@ public class SysConfigService : IDynamicApiController, ITransient [DisplayName("获取系统信息")] public async Task GetSysInfo() { - var sysLogo = await GetConfigValue("sys_web_logo"); - var sysTitle = await GetConfigValue("sys_web_title"); - var sysViceTitle = await GetConfigValue("sys_web_viceTitle"); - var sysViceDesc = await GetConfigValue("sys_web_viceDesc"); - var sysWatermark = await GetConfigValue("sys_web_watermark"); - var sysCopyright = await GetConfigValue("sys_web_copyright"); - var sysIcp = await GetConfigValue("sys_web_icp"); - var sysIcpUrl = await GetConfigValue("sys_web_icpUrl"); + var sysLogo = await GetConfigValue(ConfigConst.SysWebLogo); + var sysTitle = await GetConfigValue(ConfigConst.SysWebTitle); + var sysViceTitle = await GetConfigValue(ConfigConst.SysWebViceTitle); + var sysViceDesc = await GetConfigValue(ConfigConst.SysWebViceDesc); + var sysWatermark = await GetConfigValue(ConfigConst.SysWebWatermark); + var sysCopyright = await GetConfigValue(ConfigConst.SysWebCopyright); + var sysIcp = await GetConfigValue(ConfigConst.SysWebIcp); + var sysIcpUrl = await GetConfigValue(ConfigConst.SysWebIcpUrl); return new { @@ -266,6 +263,7 @@ public class SysConfigService : IDynamicApiController, ITransient /// 保存系统信息 🔖 /// /// + [UnitOfWork] [DisplayName("保存系统信息")] public async Task SaveSysInfo(InfoSaveInput input) { @@ -273,17 +271,18 @@ public class SysConfigService : IDynamicApiController, ITransient if (!string.IsNullOrEmpty(input.SysLogoBase64)) { // 旧图标文件相对路径 - var oldSysLogoRelativeFilePath = await GetConfigValue("sys_web_logo") ?? ""; + var oldSysLogoRelativeFilePath = await GetConfigValue(ConfigConst.SysWebLogo) ?? ""; var oldSysLogoAbsoluteFilePath = Path.Combine(App.WebHostEnvironment.WebRootPath, oldSysLogoRelativeFilePath.TrimStart('/')); var groups = Regex.Match(input.SysLogoBase64, @"data:image/(?.+?);base64,(?.+)").Groups; - var type = groups["type"].Value; + //var type = groups["type"].Value; var base64Data = groups["data"].Value; var binData = Convert.FromBase64String(base64Data); - + // 根据文件名取扩展名 + var ext = string.IsNullOrWhiteSpace(input.SysLogoFileName) ? ".png" : Path.GetExtension(input.SysLogoFileName); // 本地图标保存路径 var path = "Upload"; - var absoluteFilePath = Path.Combine(App.WebHostEnvironment.WebRootPath, path, $"logo.{type}"); + var absoluteFilePath = Path.Combine(App.WebHostEnvironment.WebRootPath, path, $"logo{ext}"); // 删除已存在文件 if (File.Exists(oldSysLogoAbsoluteFilePath)) @@ -298,16 +297,16 @@ public class SysConfigService : IDynamicApiController, ITransient await File.WriteAllBytesAsync(absoluteFilePath, binData); // 保存图标配置 - var relativeUrl = $"/{path}/logo.{type}"; - await UpdateConfigValue("sys_web_logo", relativeUrl); + var relativeUrl = $"/{path}/logo{ext}"; + await UpdateConfigValue(ConfigConst.SysWebLogo, relativeUrl); } - await UpdateConfigValue("sys_web_title", input.SysTitle); - await UpdateConfigValue("sys_web_viceTitle", input.SysViceTitle); - await UpdateConfigValue("sys_web_viceDesc", input.SysViceDesc); - await UpdateConfigValue("sys_web_watermark", input.SysWatermark); - await UpdateConfigValue("sys_web_copyright", input.SysCopyright); - await UpdateConfigValue("sys_web_icp", input.SysIcp); - await UpdateConfigValue("sys_web_icpUrl", input.SysIcpUrl); + await UpdateConfigValue(ConfigConst.SysWebTitle, input.SysTitle); + await UpdateConfigValue(ConfigConst.SysWebViceTitle, input.SysViceTitle); + await UpdateConfigValue(ConfigConst.SysWebViceDesc, input.SysViceDesc); + await UpdateConfigValue(ConfigConst.SysWebWatermark, input.SysWatermark); + await UpdateConfigValue(ConfigConst.SysWebCopyright, input.SysCopyright); + await UpdateConfigValue(ConfigConst.SysWebIcp, input.SysIcp); + await UpdateConfigValue(ConfigConst.SysWebIcpUrl, input.SysIcpUrl); } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Job/JobMonitor.cs b/Admin.NET/Admin.NET.Core/Service/Job/JobMonitor.cs index eaffcb17..5dcb02ed 100644 --- a/Admin.NET/Admin.NET.Core/Service/Job/JobMonitor.cs +++ b/Admin.NET/Admin.NET.Core/Service/Job/JobMonitor.cs @@ -33,7 +33,7 @@ public class JobMonitor : IJobMonitor if (await _sysConfigService.GetConfigValue(CommonConst.SysErrorMail) && context.Exception != null) { var errorInfo = $"【{context.Trigger.Description}】定时任务错误:{context.Exception}"; - await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, errorInfo); + await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, errorInfo, stoppingToken); } } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Message/SysEmailService.cs b/Admin.NET/Admin.NET.Core/Service/Message/SysEmailService.cs index e136ab2e..8bcdd313 100644 --- a/Admin.NET/Admin.NET.Core/Service/Message/SysEmailService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Message/SysEmailService.cs @@ -16,10 +16,12 @@ namespace Admin.NET.Core.Service; public class SysEmailService : IDynamicApiController, ITransient { private readonly EmailOptions _emailOptions; + private readonly SysConfigService _sysConfigService; - public SysEmailService(IOptions emailOptions) + public SysEmailService(IOptions emailOptions, SysConfigService sysConfigService) { _emailOptions = emailOptions.Value; + _sysConfigService = sysConfigService; } /// @@ -29,8 +31,10 @@ public class SysEmailService : IDynamicApiController, ITransient /// /// [DisplayName("发送邮件")] - public async Task SendEmail([Required] string content, string title = "Admin.NET 系统邮件") + public async Task SendEmail([Required] string content, string title = "") { + var webTitle = await _sysConfigService.GetConfigValue(ConfigConst.SysWebTitle); + title = string.IsNullOrWhiteSpace(title) ? $"{webTitle} 系统邮件" : title; var message = new MimeMessage(); message.From.Add(new MailboxAddress(_emailOptions.DefaultFromEmail, _emailOptions.DefaultFromEmail)); message.To.Add(new MailboxAddress(_emailOptions.DefaultToEmail, _emailOptions.DefaultToEmail)); diff --git a/Admin.NET/Admin.NET.Core/Service/OAuth/HttpContextExtension.cs b/Admin.NET/Admin.NET.Core/Service/OAuth/HttpContextExtension.cs deleted file mode 100644 index b210421e..00000000 --- a/Admin.NET/Admin.NET.Core/Service/OAuth/HttpContextExtension.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 -// -// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 -// -// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! - -using Microsoft.AspNetCore.Authentication; - -namespace Admin.NET.Core.Service; - -public static class HttpContextExtension -{ - public static async Task GetExternalProvidersAsync(this HttpContext context) - { - ArgumentNullException.ThrowIfNull(context); - - var schemes = context.RequestServices.GetRequiredService(); - - return (from scheme in await schemes.GetAllSchemesAsync() - where !string.IsNullOrEmpty(scheme.DisplayName) - select scheme).ToArray(); - } - - public static async Task IsProviderSupportedAsync(this HttpContext context, string provider) - { - ArgumentNullException.ThrowIfNull(context); - - return (from scheme in await context.GetExternalProvidersAsync() - where string.Equals(scheme.Name, provider, StringComparison.OrdinalIgnoreCase) - select scheme).Any(); - } -} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Region/SysRegionService.cs b/Admin.NET/Admin.NET.Core/Service/Region/SysRegionService.cs index bf0ca92d..332a82be 100644 --- a/Admin.NET/Admin.NET.Core/Service/Region/SysRegionService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Region/SysRegionService.cs @@ -4,6 +4,9 @@ // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! +using AngleSharp; +using AngleSharp.Html.Dom; + namespace Admin.NET.Core.Service; /// @@ -13,13 +16,15 @@ namespace Admin.NET.Core.Service; public class SysRegionService : IDynamicApiController, ITransient { private readonly SqlSugarRepository _sysRegionRep; + private readonly SysConfigService _sysConfigService; - //// Url地址-国家统计局行政区域2023年 - //private readonly string _url = "http://www.stats.gov.cn/sj/tjbz/tjyqhdmhcxhfdm/2023/index.html"; + // Url地址-国家统计局行政区域2023年 + private readonly string _url = "http://www.stats.gov.cn/sj/tjbz/tjyqhdmhcxhfdm/2023/index.html"; - public SysRegionService(SqlSugarRepository sysRegionRep) + public SysRegionService(SqlSugarRepository sysRegionRep, SysConfigService sysConfigService) { _sysRegionRep = sysRegionRep; + _sysConfigService = sysConfigService; } /// @@ -59,7 +64,7 @@ public class SysRegionService : IDynamicApiController, ITransient { input.Code = input.Code.Trim(); if (input.Code.Length != 12 && input.Code.Length != 9 && input.Code.Length != 6) - throw Oops.Oh("行政区代码只能为6、9或12位"); + throw Oops.Oh(ErrorCodeEnum.R2003); if (input.Pid != 0) { @@ -90,7 +95,7 @@ public class SysRegionService : IDynamicApiController, ITransient { input.Code = input.Code.Trim(); if (input.Code.Length != 12 && input.Code.Length != 9 && input.Code.Length != 6) - throw Oops.Oh("行政区代码只能为6、9或12位"); + throw Oops.Oh(ErrorCodeEnum.R2003); if (input.Pid != input.Pid && input.Pid != 0) { @@ -103,7 +108,7 @@ public class SysRegionService : IDynamicApiController, ITransient var regionTreeList = await _sysRegionRep.AsQueryable().ToChildListAsync(u => u.Pid, input.Id, true); var childIdList = regionTreeList.Select(u => u.Id).ToList(); if (childIdList.Contains(input.Pid)) - throw Oops.Oh("父节点不能为自己的子节点"); + throw Oops.Oh(ErrorCodeEnum.R2004); } if (input.Id == input.Pid) @@ -144,93 +149,117 @@ public class SysRegionService : IDynamicApiController, ITransient [DisplayName("同步行政区域")] public async Task Sync() { + var syncLevel = await _sysConfigService.GetConfigValue(CommonConst.SysRegionSyncLevel); + if (syncLevel < 1 || syncLevel > 5) + syncLevel = 3;//默认区县级 + var context = BrowsingContext.New(AngleSharp.Configuration.Default.WithDefaultLoader()); + var dom = await context.OpenAsync(_url); + + // 省级 + var itemList = dom.QuerySelectorAll("table.provincetable tr.provincetr td a"); + if (itemList.Length == 0) + throw Oops.Oh(ErrorCodeEnum.R2005); + await _sysRegionRep.DeleteAsync(u => u.Id > 0); - //var context = BrowsingContext.New(AngleSharp.Configuration.Default.WithDefaultLoader()); - //var dom = await context.OpenAsync(_url); + foreach (IHtmlAnchorElement item in itemList) + { + var list = new List(); - //// 省级 - //var itemList = dom.QuerySelectorAll("table.provincetable tr.provincetr td a"); - //foreach (IHtmlAnchorElement item in itemList) - //{ - // var region = await _sysRegionRep.InsertReturnEntityAsync(new SysRegion - // { - // Pid = 0, - // Name = item.TextContent, - // Remark = item.Href, - // Level = 1, - // }); + var region = new SysRegion + { + Id = YitIdHelper.NextId(), + Pid = 0, + Name = item.TextContent, + Remark = item.Href, + Level = 1, + }; + list.Add(region); - // // 市级 - // if (string.IsNullOrEmpty(item.Href)) - // continue; - // var dom1 = await context.OpenAsync(item.Href); - // var itemList1 = dom1.QuerySelectorAll("table.citytable tr.citytr td a"); - // for (var i1 = 0; i1 < itemList1.Length; i1 += 2) - // { - // var item1 = (IHtmlAnchorElement)itemList1[i1 + 1]; - // var region1 = await _sysRegionRep.InsertReturnEntityAsync(new SysRegion - // { - // Pid = region.Id, - // Name = item1.TextContent, - // Code = itemList1[i1].TextContent, - // Remark = item1.Href, - // Level = 2, - // }); + // 市级 + if (!string.IsNullOrEmpty(item.Href) && syncLevel > 1) + { + var dom1 = await context.OpenAsync(item.Href); + var itemList1 = dom1.QuerySelectorAll("table.citytable tr.citytr td a"); + for (var i1 = 0; i1 < itemList1.Length; i1 += 2) + { + var item1 = (IHtmlAnchorElement)itemList1[i1 + 1]; + var region1 = new SysRegion + { + Id = YitIdHelper.NextId(), + Pid = region.Id, + Name = item1.TextContent, + Code = itemList1[i1].TextContent, + Remark = item1.Href, + Level = 2, + }; + list.Add(region1); - // // 区县级 - // if (string.IsNullOrEmpty(item1.Href)) - // continue; - // var dom2 = await context.OpenAsync(item1.Href); - // var itemList2 = dom2.QuerySelectorAll("table.countytable tr.countytr td a"); - // for (var i2 = 0; i2 < itemList2.Length; i2 += 2) - // { - // var item2 = (IHtmlAnchorElement)itemList2[i2 + 1]; - // var region2 = await _sysRegionRep.InsertReturnEntityAsync(new SysRegion - // { - // Pid = region1.Id, - // Name = item2.TextContent, - // Code = itemList2[i2].TextContent, - // Remark = item2.Href, - // Level = 3, - // }); + // 区县级 + if (!string.IsNullOrEmpty(item1.Href) && syncLevel > 2) + { + var dom2 = await context.OpenAsync(item1.Href); + var itemList2 = dom2.QuerySelectorAll("table.countytable tr.countytr td a"); + for (var i2 = 0; i2 < itemList2.Length; i2 += 2) + { + var item2 = (IHtmlAnchorElement)itemList2[i2 + 1]; + var region2 = new SysRegion + { + Id = YitIdHelper.NextId(), + Pid = region1.Id, + Name = item2.TextContent, + Code = itemList2[i2].TextContent, + Remark = item2.Href, + Level = 3, + }; + list.Add(region2); - // // 街道级 - // if (string.IsNullOrEmpty(item2.Href)) - // continue; - // var dom3 = await context.OpenAsync(item2.Href); - // var itemList3 = dom3.QuerySelectorAll("table.towntable tr.towntr td a"); - // for (var i3 = 0; i3 < itemList3.Length; i3 += 2) - // { - // var item3 = (IHtmlAnchorElement)itemList3[i3 + 1]; - // var region3 = await _sysRegionRep.InsertReturnEntityAsync(new SysRegion - // { - // Pid = region2.Id, - // Name = item3.TextContent, - // Code = itemList3[i3].TextContent, - // Remark = item3.Href, - // Level = 4, - // }); + // 街道级 + if (!string.IsNullOrEmpty(item2.Href) && syncLevel > 3) + { + var dom3 = await context.OpenAsync(item2.Href); + var itemList3 = dom3.QuerySelectorAll("table.towntable tr.towntr td a"); + for (var i3 = 0; i3 < itemList3.Length; i3 += 2) + { + var item3 = (IHtmlAnchorElement)itemList3[i3 + 1]; + var region3 = new SysRegion + { + Id = YitIdHelper.NextId(), + Pid = region2.Id, + Name = item3.TextContent, + Code = itemList3[i3].TextContent, + Remark = item3.Href, + Level = 4, + }; + list.Add(region3); - // // 村级 - // if (string.IsNullOrEmpty(item3.Href)) - // continue; - // var dom4 = await context.OpenAsync(item3.Href); - // var itemList4 = dom4.QuerySelectorAll("table.villagetable tr.villagetr td"); - // for (var i4 = 0; i4 < itemList4.Length; i4 += 3) - // { - // await _sysRegionRep.InsertAsync(new SysRegion - // { - // Pid = region3.Id, - // Name = itemList4[i4 + 2].TextContent, - // Code = itemList4[i4].TextContent, - // CityCode = itemList4[i4 + 1].TextContent, - // Level = 5, - // }); - // } - // } - // } - // } - //} + // 村级 + if (!string.IsNullOrEmpty(item3.Href) && syncLevel > 4) + { + var dom4 = await context.OpenAsync(item3.Href); + var itemList4 = dom4.QuerySelectorAll("table.villagetable tr.villagetr td"); + for (var i4 = 0; i4 < itemList4.Length; i4 += 3) + { + list.Add(new SysRegion + { + Id = YitIdHelper.NextId(), + Pid = region3.Id, + Name = itemList4[i4 + 2].TextContent, + Code = itemList4[i4].TextContent, + CityCode = itemList4[i4 + 1].TextContent, + Level = 5, + }); + } + } + } + } + } + } + } + } + + //按省份同步快速写入提升同步效率,全部一次性写入容易出现从统计局获取数据失败 + _sysRegionRep.Context.Fastest().BulkCopy(list); + } } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WxOpenInput.cs b/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WxOpenInput.cs index dca1cef4..ed73300e 100644 --- a/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WxOpenInput.cs +++ b/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WxOpenInput.cs @@ -122,19 +122,21 @@ public class AddSubscribeMessageTemplateInput /// public class VerifySignatureInput { - /// /// 签名 /// public string signature { get; set; } + /// /// 时间戳 /// public string timestamp { get; set; } + /// /// 随机数 /// public string nonce { get; set; } + /// /// 随机字符串 /// diff --git a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWxOpenService.cs b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWxOpenService.cs index 1383910a..29d6dc53 100644 --- a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWxOpenService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWxOpenService.cs @@ -123,7 +123,6 @@ public class SysWxOpenService : IDynamicApiController, ITransient [DisplayName("验证签名")] public string VerifySignature([FromQuery] VerifySignatureInput input) { - bool valid = _wechatApiClient.VerifyEventSignatureForEcho(input.timestamp, input.nonce, input.signature); if (!valid) { diff --git a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs index 05a9b022..db75b699 100644 --- a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs +++ b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs @@ -68,8 +68,10 @@ public static class SqlSugarFilter if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString())) continue; - var lambda = DynamicExpressionParser.ParseLambda(new[] { - Expression.Parameter(entityType, "u") }, typeof(bool), $"@0.Contains(u.{nameof(EntityBaseData.CreateOrgId)}??{default(long)})", orgIds); + //var lambda = DynamicExpressionParser.ParseLambda(new[] { + // Expression.Parameter(entityType, "u") }, typeof(bool), $"@0.Contains(u.{nameof(EntityBaseData.CreateOrgId)}??{default(long)})", orgIds); + var lambda = entityType.GetConditionExpression(orgIds); + db.QueryFilter.AddTableFilter(entityType, lambda); orgFilter.TryAdd(entityType, lambda); } @@ -114,8 +116,10 @@ public static class SqlSugarFilter if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString())) continue; - var lambda = DynamicExpressionParser.ParseLambda(new[] { - Expression.Parameter(entityType, "u") }, typeof(bool), $"u.{nameof(EntityBaseData.CreateUserId)}=@0", userId); + //var lambda = DynamicExpressionParser.ParseLambda(new[] { + // Expression.Parameter(entityType, "u") }, typeof(bool), $"u.{nameof(EntityBaseData.CreateUserId)}=@0", userId); + var lambda = entityType.GetConditionExpression(new List { long.Parse(userId) }); + db.QueryFilter.AddTableFilter(entityType, lambda); dataScopeFilter.TryAdd(entityType, lambda); } diff --git a/Admin.NET/Admin.NET.Core/Util/BaseFilter.cs b/Admin.NET/Admin.NET.Core/Util/BaseFilter.cs new file mode 100644 index 00000000..5ab7d4ac --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Util/BaseFilter.cs @@ -0,0 +1,75 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 模糊查询条件 +/// +public class Search +{ + /// + /// 字段名称集合 + /// + public List Fields { get; set; } + + /// + /// 关键字 + /// + public string? Keyword { get; set; } +} + +/// +/// 筛选过滤条件 +/// +public class Filter +{ + /// + /// 过滤条件 + /// + public FilterLogicEnum? Logic { get; set; } + + /// + /// 筛选过滤条件子项 + /// + public IEnumerable? Filters { get; set; } + + /// + /// 字段名称 + /// + public string? Field { get; set; } + + /// + /// 逻辑运算符 + /// + public FilterOperatorEnum? Operator { get; set; } + + /// + /// 字段值 + /// + public object? Value { get; set; } +} + +/// +/// 过滤条件基类 +/// +public abstract class BaseFilter +{ + /// + /// 模糊查询条件 + /// + public Search? Search { get; set; } + + /// + /// 模糊查询关键字 + /// + public string? Keyword { get; set; } + + /// + /// 筛选过滤条件 + /// + public Filter? Filter { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Util/BasePageInput.cs b/Admin.NET/Admin.NET.Core/Util/BasePageInput.cs index 88203f6a..d8bea2f0 100644 --- a/Admin.NET/Admin.NET.Core/Util/BasePageInput.cs +++ b/Admin.NET/Admin.NET.Core/Util/BasePageInput.cs @@ -9,7 +9,7 @@ namespace Admin.NET.Core; /// /// 全局分页查询输入参数 /// -public class BasePageInput +public class BasePageInput : BaseFilter { /// /// 当前页码 diff --git a/Web/src/api-services/apis/sys-common-api.ts b/Web/src/api-services/apis/sys-common-api.ts index b3bdd82c..65aed958 100644 --- a/Web/src/api-services/apis/sys-common-api.ts +++ b/Web/src/api-services/apis/sys-common-api.ts @@ -17,6 +17,7 @@ import { Configuration } from '../configuration'; // Some imports not used depending on template conditions // @ts-ignore import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base'; +import { AdminResultIActionResult } from '../models'; import { AdminResultListApiOutput } from '../models'; import { AdminResultSmKeyPairOutput } from '../models'; import { AdminResultString } from '../models'; @@ -74,6 +75,54 @@ export const SysCommonApiAxiosParamCreator = function (configuration?: Configura options: localVarRequestOptions, }; }, + /** + * + * @summary 下载标记错误的临时 Excel(全局) + * @param {string} [fileName] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysCommonDownloadErrorExcelTempPost: async (fileName?: string, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysCommon/downloadErrorExcelTemp`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + if (fileName !== undefined) { + localVarQueryParameter['fileName'] = fileName; + } + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, /** * * @summary 获取MD5加密字符串 🏆 @@ -195,6 +244,20 @@ export const SysCommonApiFp = function(configuration?: Configuration) { return axios.request(axiosRequestArgs); }; }, + /** + * + * @summary 下载标记错误的临时 Excel(全局) + * @param {string} [fileName] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysCommonDownloadErrorExcelTempPost(fileName?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysCommonApiAxiosParamCreator(configuration).apiSysCommonDownloadErrorExcelTempPost(fileName, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, /** * * @summary 获取MD5加密字符串 🏆 @@ -242,6 +305,16 @@ export const SysCommonApiFactory = function (configuration?: Configuration, base async apiSysCommonApiListGet(groupName?: string, options?: AxiosRequestConfig): Promise> { return SysCommonApiFp(configuration).apiSysCommonApiListGet(groupName, options).then((request) => request(axios, basePath)); }, + /** + * + * @summary 下载标记错误的临时 Excel(全局) + * @param {string} [fileName] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysCommonDownloadErrorExcelTempPost(fileName?: string, options?: AxiosRequestConfig): Promise> { + return SysCommonApiFp(configuration).apiSysCommonDownloadErrorExcelTempPost(fileName, options).then((request) => request(axios, basePath)); + }, /** * * @summary 获取MD5加密字符串 🏆 @@ -283,6 +356,17 @@ export class SysCommonApi extends BaseAPI { public async apiSysCommonApiListGet(groupName?: string, options?: AxiosRequestConfig) : Promise> { return SysCommonApiFp(this.configuration).apiSysCommonApiListGet(groupName, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary 下载标记错误的临时 Excel(全局) + * @param {string} [fileName] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysCommonApi + */ + public async apiSysCommonDownloadErrorExcelTempPost(fileName?: string, options?: AxiosRequestConfig) : Promise> { + return SysCommonApiFp(this.configuration).apiSysCommonDownloadErrorExcelTempPost(fileName, options).then((request) => request(this.axios, this.basePath)); + } /** * * @summary 获取MD5加密字符串 🏆 diff --git a/Web/src/api-services/apis/sys-notice-api.ts b/Web/src/api-services/apis/sys-notice-api.ts index 88d9bd17..446f6b12 100644 --- a/Web/src/api-services/apis/sys-notice-api.ts +++ b/Web/src/api-services/apis/sys-notice-api.ts @@ -22,6 +22,9 @@ import { AdminResultListSysNotice } from '../models'; import { AdminResultSqlSugarPagedListSysNotice } from '../models'; import { AdminResultSqlSugarPagedListSysNoticeUser } from '../models'; import { DeleteNoticeInput } from '../models'; +import { Filter } from '../models'; +import { FilterLogicEnum } from '../models'; +import { FilterOperatorEnum } from '../models'; import { NoticeInput } from '../models'; import { NoticeTypeEnum } from '../models'; import { PageNoticeInput } from '../models'; @@ -186,10 +189,18 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura * @param {string} [field] 排序字段 * @param {string} [order] 排序方向 * @param {string} [descStr] 降序排序 + * @param {Array} [searchFields] 字段名称集合 + * @param {string} [searchKeyword] 关键字 + * @param {string} [keyword] 模糊查询关键字 + * @param {FilterLogicEnum} [filterLogic] 过滤条件 + * @param {Array} [filterFilters] 筛选过滤条件子项 + * @param {string} [filterField] 字段名称 + * @param {FilterOperatorEnum} [filterOperator] 逻辑运算符 + * @param {any} [filterValue] 字段值 * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiSysNoticePageReceivedGet: async (title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options: AxiosRequestConfig = {}): Promise => { + apiSysNoticePageReceivedGet: async (title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, searchFields?: Array, searchKeyword?: string, keyword?: string, filterLogic?: FilterLogicEnum, filterFilters?: Array, filterField?: string, filterOperator?: FilterOperatorEnum, filterValue?: any, options: AxiosRequestConfig = {}): Promise => { const localVarPath = `/api/sysNotice/pageReceived`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, 'https://example.com'); @@ -238,6 +249,38 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura localVarQueryParameter['DescStr'] = descStr; } + if (searchFields) { + localVarQueryParameter['Search.Fields'] = searchFields; + } + + if (searchKeyword !== undefined) { + localVarQueryParameter['Search.Keyword'] = searchKeyword; + } + + if (keyword !== undefined) { + localVarQueryParameter['Keyword'] = keyword; + } + + if (filterLogic !== undefined) { + localVarQueryParameter['Filter.Logic'] = filterLogic; + } + + if (filterFilters) { + localVarQueryParameter['Filter.Filters'] = filterFilters; + } + + if (filterField !== undefined) { + localVarQueryParameter['Filter.Field'] = filterField; + } + + if (filterOperator !== undefined) { + localVarQueryParameter['Filter.Operator'] = filterOperator; + } + + if (filterValue !== undefined) { + localVarQueryParameter['Filter.Value'] = filterValue; + } + const query = new URLSearchParams(localVarUrlObj.search); for (const key in localVarQueryParameter) { query.set(key, localVarQueryParameter[key]); @@ -502,11 +545,19 @@ export const SysNoticeApiFp = function(configuration?: Configuration) { * @param {string} [field] 排序字段 * @param {string} [order] 排序方向 * @param {string} [descStr] 降序排序 + * @param {Array} [searchFields] 字段名称集合 + * @param {string} [searchKeyword] 关键字 + * @param {string} [keyword] 模糊查询关键字 + * @param {FilterLogicEnum} [filterLogic] 过滤条件 + * @param {Array} [filterFilters] 筛选过滤条件子项 + * @param {string} [filterField] 字段名称 + * @param {FilterOperatorEnum} [filterOperator] 逻辑运算符 + * @param {any} [filterValue] 字段值 * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { - const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, options); + async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, searchFields?: Array, searchKeyword?: string, keyword?: string, filterLogic?: FilterLogicEnum, filterFilters?: Array, filterField?: string, filterOperator?: FilterOperatorEnum, filterValue?: any, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, searchFields, searchKeyword, keyword, filterLogic, filterFilters, filterField, filterOperator, filterValue, options); return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; return axios.request(axiosRequestArgs); @@ -616,11 +667,19 @@ export const SysNoticeApiFactory = function (configuration?: Configuration, base * @param {string} [field] 排序字段 * @param {string} [order] 排序方向 * @param {string} [descStr] 降序排序 + * @param {Array} [searchFields] 字段名称集合 + * @param {string} [searchKeyword] 关键字 + * @param {string} [keyword] 模糊查询关键字 + * @param {FilterLogicEnum} [filterLogic] 过滤条件 + * @param {Array} [filterFilters] 筛选过滤条件子项 + * @param {string} [filterField] 字段名称 + * @param {FilterOperatorEnum} [filterOperator] 逻辑运算符 + * @param {any} [filterValue] 字段值 * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise> { - return SysNoticeApiFp(configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, options).then((request) => request(axios, basePath)); + async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, searchFields?: Array, searchKeyword?: string, keyword?: string, filterLogic?: FilterLogicEnum, filterFilters?: Array, filterField?: string, filterOperator?: FilterOperatorEnum, filterValue?: any, options?: AxiosRequestConfig): Promise> { + return SysNoticeApiFp(configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, searchFields, searchKeyword, keyword, filterLogic, filterFilters, filterField, filterOperator, filterValue, options).then((request) => request(axios, basePath)); }, /** * @@ -714,12 +773,20 @@ export class SysNoticeApi extends BaseAPI { * @param {string} [field] 排序字段 * @param {string} [order] 排序方向 * @param {string} [descStr] 降序排序 + * @param {Array} [searchFields] 字段名称集合 + * @param {string} [searchKeyword] 关键字 + * @param {string} [keyword] 模糊查询关键字 + * @param {FilterLogicEnum} [filterLogic] 过滤条件 + * @param {Array} [filterFilters] 筛选过滤条件子项 + * @param {string} [filterField] 字段名称 + * @param {FilterOperatorEnum} [filterOperator] 逻辑运算符 + * @param {any} [filterValue] 字段值 * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SysNoticeApi */ - public async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig) : Promise> { - return SysNoticeApiFp(this.configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, options).then((request) => request(this.axios, this.basePath)); + public async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, searchFields?: Array, searchKeyword?: string, keyword?: string, filterLogic?: FilterLogicEnum, filterFilters?: Array, filterField?: string, filterOperator?: FilterOperatorEnum, filterValue?: any, options?: AxiosRequestConfig) : Promise> { + return SysNoticeApiFp(this.configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, searchFields, searchKeyword, keyword, filterLogic, filterFilters, filterField, filterOperator, filterValue, options).then((request) => request(this.axios, this.basePath)); } /** * diff --git a/Web/src/api-services/apis/sys-wx-open-api.ts b/Web/src/api-services/apis/sys-wx-open-api.ts index 04e39e18..dd2c9b66 100644 --- a/Web/src/api-services/apis/sys-wx-open-api.ts +++ b/Web/src/api-services/apis/sys-wx-open-api.ts @@ -168,6 +168,69 @@ export const SysWxOpenApiAxiosParamCreator = function (configuration?: Configura options: localVarRequestOptions, }; }, + /** + * + * @summary 验证签名 🔖 + * @param {string} [signature] 签名 + * @param {string} [timestamp] 时间戳 + * @param {string} [nonce] 随机数 + * @param {string} [echostr] 随机字符串 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysWxOpenVerifySignatureGet: async (signature?: string, timestamp?: string, nonce?: string, echostr?: string, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysWxOpen/verifySignature`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + if (signature !== undefined) { + localVarQueryParameter['signature'] = signature; + } + + if (timestamp !== undefined) { + localVarQueryParameter['timestamp'] = timestamp; + } + + if (nonce !== undefined) { + localVarQueryParameter['nonce'] = nonce; + } + + if (echostr !== undefined) { + localVarQueryParameter['echostr'] = echostr; + } + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, /** * * @summary 获取微信用户OpenId 🔖 @@ -379,6 +442,23 @@ export const SysWxOpenApiFp = function(configuration?: Configuration) { return axios.request(axiosRequestArgs); }; }, + /** + * + * @summary 验证签名 🔖 + * @param {string} [signature] 签名 + * @param {string} [timestamp] 时间戳 + * @param {string} [nonce] 随机数 + * @param {string} [echostr] 随机字符串 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysWxOpenVerifySignatureGet(signature?: string, timestamp?: string, nonce?: string, echostr?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysWxOpenApiAxiosParamCreator(configuration).apiSysWxOpenVerifySignatureGet(signature, timestamp, nonce, echostr, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, /** * * @summary 获取微信用户OpenId 🔖 @@ -460,6 +540,19 @@ export const SysWxOpenApiFactory = function (configuration?: Configuration, base async apiSysWxOpenSendSubscribeMessagePost(body?: SendSubscribeMessageInput, options?: AxiosRequestConfig): Promise> { return SysWxOpenApiFp(configuration).apiSysWxOpenSendSubscribeMessagePost(body, options).then((request) => request(axios, basePath)); }, + /** + * + * @summary 验证签名 🔖 + * @param {string} [signature] 签名 + * @param {string} [timestamp] 时间戳 + * @param {string} [nonce] 随机数 + * @param {string} [echostr] 随机字符串 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysWxOpenVerifySignatureGet(signature?: string, timestamp?: string, nonce?: string, echostr?: string, options?: AxiosRequestConfig): Promise> { + return SysWxOpenApiFp(configuration).apiSysWxOpenVerifySignatureGet(signature, timestamp, nonce, echostr, options).then((request) => request(axios, basePath)); + }, /** * * @summary 获取微信用户OpenId 🔖 @@ -533,6 +626,20 @@ export class SysWxOpenApi extends BaseAPI { public async apiSysWxOpenSendSubscribeMessagePost(body?: SendSubscribeMessageInput, options?: AxiosRequestConfig) : Promise> { return SysWxOpenApiFp(this.configuration).apiSysWxOpenSendSubscribeMessagePost(body, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary 验证签名 🔖 + * @param {string} [signature] 签名 + * @param {string} [timestamp] 时间戳 + * @param {string} [nonce] 随机数 + * @param {string} [echostr] 随机字符串 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysWxOpenApi + */ + public async apiSysWxOpenVerifySignatureGet(signature?: string, timestamp?: string, nonce?: string, echostr?: string, options?: AxiosRequestConfig) : Promise> { + return SysWxOpenApiFp(this.configuration).apiSysWxOpenVerifySignatureGet(signature, timestamp, nonce, echostr, options).then((request) => request(this.axios, this.basePath)); + } /** * * @summary 获取微信用户OpenId 🔖 diff --git a/Web/src/api-services/models/add-code-gen-input.ts b/Web/src/api-services/models/add-code-gen-input.ts index a79ea25f..85a1d0de 100644 --- a/Web/src/api-services/models/add-code-gen-input.ts +++ b/Web/src/api-services/models/add-code-gen-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface AddCodeGenInput { + /** + * @type {Search} + * @memberof AddCodeGenInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof AddCodeGenInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof AddCodeGenInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/filter-logic-enum.ts b/Web/src/api-services/models/filter-logic-enum.ts new file mode 100644 index 00000000..b535525a --- /dev/null +++ b/Web/src/api-services/models/filter-logic-enum.ts @@ -0,0 +1,25 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/** + * 过滤条件
 并且 And = 0
 或者 Or = 1
 异或 Xor = 2
+ * @export + * @enum {string} + */ +export enum FilterLogicEnum { + NUMBER_0 = 0, + NUMBER_1 = 1, + NUMBER_2 = 2 +} + diff --git a/Web/src/api-services/models/filter-operator-enum.ts b/Web/src/api-services/models/filter-operator-enum.ts new file mode 100644 index 00000000..ed0a3e7c --- /dev/null +++ b/Web/src/api-services/models/filter-operator-enum.ts @@ -0,0 +1,31 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/** + * 过滤逻辑运算符
 等于 EQ = 0
 不等于 NEQ = 1
 小于 LT = 2
 小于等于 LTE = 3
 大于 GT = 4
 大于等于 GTE = 5
 开始包含 StartsWith = 6
 末尾包含 EndsWith = 7
 包含 Contains = 8
+ * @export + * @enum {string} + */ +export enum FilterOperatorEnum { + NUMBER_0 = 0, + NUMBER_1 = 1, + NUMBER_2 = 2, + NUMBER_3 = 3, + NUMBER_4 = 4, + NUMBER_5 = 5, + NUMBER_6 = 6, + NUMBER_7 = 7, + NUMBER_8 = 8 +} + diff --git a/Web/src/api-services/models/filter.ts b/Web/src/api-services/models/filter.ts new file mode 100644 index 00000000..60d9216e --- /dev/null +++ b/Web/src/api-services/models/filter.ts @@ -0,0 +1,61 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { Filter } from './filter'; +import { FilterLogicEnum } from './filter-logic-enum'; +import { FilterOperatorEnum } from './filter-operator-enum'; + /** + * 筛选过滤条件 + * + * @export + * @interface Filter + */ +export interface Filter { + + /** + * @type {FilterLogicEnum} + * @memberof Filter + */ + logic?: FilterLogicEnum; + + /** + * 筛选过滤条件子项 + * + * @type {Array} + * @memberof Filter + */ + filters?: Array | null; + + /** + * 字段名称 + * + * @type {string} + * @memberof Filter + */ + field?: string | null; + + /** + * @type {FilterOperatorEnum} + * @memberof Filter + */ + operator?: FilterOperatorEnum; + + /** + * 字段值 + * + * @type {any} + * @memberof Filter + */ + value?: any | null; +} diff --git a/Web/src/api-services/models/gender-enum.ts b/Web/src/api-services/models/gender-enum.ts index 8a3d9898..170584f1 100644 --- a/Web/src/api-services/models/gender-enum.ts +++ b/Web/src/api-services/models/gender-enum.ts @@ -13,13 +13,14 @@ */ /** - * 性别枚举
 男 Male = 1
 女 Female = 2
 其他 Other = 3
+ * 性别枚举(GB/T 2261.1-2003)
 未知的性别 Unknown = 0
 男性 Male = 1
 女性 Female = 2
 未说明的性别 Unspecified = 9
* @export * @enum {string} */ export enum GenderEnum { + NUMBER_0 = 0, NUMBER_1 = 1, NUMBER_2 = 2, - NUMBER_3 = 3 + NUMBER_9 = 9 } diff --git a/Web/src/api-services/models/index.ts b/Web/src/api-services/models/index.ts index 3dd72fd3..d1f06166 100644 --- a/Web/src/api-services/models/index.ts +++ b/Web/src/api-services/models/index.ts @@ -183,6 +183,9 @@ export * from './field-attributes'; export * from './field-info'; export * from './file-input'; export * from './file-output'; +export * from './filter'; +export * from './filter-logic-enum'; +export * from './filter-operator-enum'; export * from './from'; export * from './gen-auth-url-input'; export * from './gender-enum'; @@ -274,6 +277,7 @@ export * from './runtime-field-handle'; export * from './runtime-method-handle'; export * from './runtime-type-handle'; export * from './schema-serialization-mode'; +export * from './search'; export * from './security-rule-set'; export * from './send-subscribe-message-input'; export * from './serialization-format'; diff --git a/Web/src/api-services/models/info-save-input.ts b/Web/src/api-services/models/info-save-input.ts index 198f63e9..e07b3ef6 100644 --- a/Web/src/api-services/models/info-save-input.ts +++ b/Web/src/api-services/models/info-save-input.ts @@ -28,6 +28,14 @@ export interface InfoSaveInput { */ sysLogoBase64?: string | null; + /** + * 系统图标文件名 + * + * @type {string} + * @memberof InfoSaveInput + */ + sysLogoFileName?: string | null; + /** * 系统主标题 * diff --git a/Web/src/api-services/models/oauth-user-input.ts b/Web/src/api-services/models/oauth-user-input.ts index 81a8ab1f..03ac9324 100644 --- a/Web/src/api-services/models/oauth-user-input.ts +++ b/Web/src/api-services/models/oauth-user-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface OAuthUserInput { + /** + * @type {Search} + * @memberof OAuthUserInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof OAuthUserInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof OAuthUserInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-code-gen-input.ts b/Web/src/api-services/models/page-code-gen-input.ts index 40b58fed..010e2cea 100644 --- a/Web/src/api-services/models/page-code-gen-input.ts +++ b/Web/src/api-services/models/page-code-gen-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * 代码生成参数类 * @@ -20,6 +22,26 @@ */ export interface PageCodeGenInput { + /** + * @type {Search} + * @memberof PageCodeGenInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageCodeGenInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageCodeGenInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-config-input.ts b/Web/src/api-services/models/page-config-input.ts index f8f36b7e..ed065e99 100644 --- a/Web/src/api-services/models/page-config-input.ts +++ b/Web/src/api-services/models/page-config-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageConfigInput { + /** + * @type {Search} + * @memberof PageConfigInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageConfigInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageConfigInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-dict-data-input.ts b/Web/src/api-services/models/page-dict-data-input.ts index 448fd305..12bed662 100644 --- a/Web/src/api-services/models/page-dict-data-input.ts +++ b/Web/src/api-services/models/page-dict-data-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageDictDataInput { + /** + * @type {Search} + * @memberof PageDictDataInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageDictDataInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageDictDataInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-dict-type-input.ts b/Web/src/api-services/models/page-dict-type-input.ts index e722cc36..138860bd 100644 --- a/Web/src/api-services/models/page-dict-type-input.ts +++ b/Web/src/api-services/models/page-dict-type-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageDictTypeInput { + /** + * @type {Search} + * @memberof PageDictTypeInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageDictTypeInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageDictTypeInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-file-input.ts b/Web/src/api-services/models/page-file-input.ts index 06353cba..1ca5f868 100644 --- a/Web/src/api-services/models/page-file-input.ts +++ b/Web/src/api-services/models/page-file-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageFileInput { + /** + * @type {Search} + * @memberof PageFileInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageFileInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageFileInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-job-detail-input.ts b/Web/src/api-services/models/page-job-detail-input.ts index 8f41ca3f..1934cbb7 100644 --- a/Web/src/api-services/models/page-job-detail-input.ts +++ b/Web/src/api-services/models/page-job-detail-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageJobDetailInput { + /** + * @type {Search} + * @memberof PageJobDetailInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageJobDetailInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageJobDetailInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-job-trigger-record-input.ts b/Web/src/api-services/models/page-job-trigger-record-input.ts index 56b0bcb0..c38afda9 100644 --- a/Web/src/api-services/models/page-job-trigger-record-input.ts +++ b/Web/src/api-services/models/page-job-trigger-record-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageJobTriggerRecordInput { + /** + * @type {Search} + * @memberof PageJobTriggerRecordInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageJobTriggerRecordInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageJobTriggerRecordInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-log-input.ts b/Web/src/api-services/models/page-log-input.ts index d98381b1..b0bdfb57 100644 --- a/Web/src/api-services/models/page-log-input.ts +++ b/Web/src/api-services/models/page-log-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageLogInput { + /** + * @type {Search} + * @memberof PageLogInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageLogInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageLogInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-notice-input.ts b/Web/src/api-services/models/page-notice-input.ts index 80e5dfea..f99944e9 100644 --- a/Web/src/api-services/models/page-notice-input.ts +++ b/Web/src/api-services/models/page-notice-input.ts @@ -12,7 +12,9 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; import { NoticeTypeEnum } from './notice-type-enum'; +import { Search } from './search'; /** * * @@ -21,6 +23,26 @@ import { NoticeTypeEnum } from './notice-type-enum'; */ export interface PageNoticeInput { + /** + * @type {Search} + * @memberof PageNoticeInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageNoticeInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageNoticeInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-online-user-input.ts b/Web/src/api-services/models/page-online-user-input.ts index 2c26e022..0cc039e8 100644 --- a/Web/src/api-services/models/page-online-user-input.ts +++ b/Web/src/api-services/models/page-online-user-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageOnlineUserInput { + /** + * @type {Search} + * @memberof PageOnlineUserInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageOnlineUserInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageOnlineUserInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-open-access-input.ts b/Web/src/api-services/models/page-open-access-input.ts index 5bd7749c..189d5bcd 100644 --- a/Web/src/api-services/models/page-open-access-input.ts +++ b/Web/src/api-services/models/page-open-access-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * 开放接口身份输入参数 * @@ -20,6 +22,26 @@ */ export interface PageOpenAccessInput { + /** + * @type {Search} + * @memberof PageOpenAccessInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageOpenAccessInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageOpenAccessInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-plugin-input.ts b/Web/src/api-services/models/page-plugin-input.ts index ea139ea0..e841f3e5 100644 --- a/Web/src/api-services/models/page-plugin-input.ts +++ b/Web/src/api-services/models/page-plugin-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PagePluginInput { + /** + * @type {Search} + * @memberof PagePluginInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PagePluginInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PagePluginInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-pos-input.ts b/Web/src/api-services/models/page-pos-input.ts index fd15aa05..8784fcce 100644 --- a/Web/src/api-services/models/page-pos-input.ts +++ b/Web/src/api-services/models/page-pos-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PagePosInput { + /** + * @type {Search} + * @memberof PagePosInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PagePosInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PagePosInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-print-input.ts b/Web/src/api-services/models/page-print-input.ts index 8caa9026..1c3b5a48 100644 --- a/Web/src/api-services/models/page-print-input.ts +++ b/Web/src/api-services/models/page-print-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PagePrintInput { + /** + * @type {Search} + * @memberof PagePrintInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PagePrintInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PagePrintInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-region-input.ts b/Web/src/api-services/models/page-region-input.ts index b713fcd2..f368cc32 100644 --- a/Web/src/api-services/models/page-region-input.ts +++ b/Web/src/api-services/models/page-region-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageRegionInput { + /** + * @type {Search} + * @memberof PageRegionInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageRegionInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageRegionInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-role-input.ts b/Web/src/api-services/models/page-role-input.ts index d2053394..271e2275 100644 --- a/Web/src/api-services/models/page-role-input.ts +++ b/Web/src/api-services/models/page-role-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageRoleInput { + /** + * @type {Search} + * @memberof PageRoleInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageRoleInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageRoleInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-sys-ldap-input.ts b/Web/src/api-services/models/page-sys-ldap-input.ts index 0aa366b9..b6037d7c 100644 --- a/Web/src/api-services/models/page-sys-ldap-input.ts +++ b/Web/src/api-services/models/page-sys-ldap-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * 系统域登录信息配置输入参数 * @@ -20,6 +22,26 @@ */ export interface PageSysLdapInput { + /** + * @type {Search} + * @memberof PageSysLdapInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageSysLdapInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageSysLdapInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-sys-wechat-pay-input.ts b/Web/src/api-services/models/page-sys-wechat-pay-input.ts index 83363150..63a8ce1c 100644 --- a/Web/src/api-services/models/page-sys-wechat-pay-input.ts +++ b/Web/src/api-services/models/page-sys-wechat-pay-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageSysWechatPayInput { + /** + * @type {Search} + * @memberof PageSysWechatPayInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageSysWechatPayInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageSysWechatPayInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-tenant-input.ts b/Web/src/api-services/models/page-tenant-input.ts index e7f5edf3..e63adbed 100644 --- a/Web/src/api-services/models/page-tenant-input.ts +++ b/Web/src/api-services/models/page-tenant-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface PageTenantInput { + /** + * @type {Search} + * @memberof PageTenantInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageTenantInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageTenantInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/page-user-input.ts b/Web/src/api-services/models/page-user-input.ts index 35610565..6e85de61 100644 --- a/Web/src/api-services/models/page-user-input.ts +++ b/Web/src/api-services/models/page-user-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * 获取用户分页列表输入参数 * @@ -20,6 +22,26 @@ */ export interface PageUserInput { + /** + * @type {Search} + * @memberof PageUserInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageUserInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageUserInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/api-services/models/search.ts b/Web/src/api-services/models/search.ts new file mode 100644 index 00000000..afa1712f --- /dev/null +++ b/Web/src/api-services/models/search.ts @@ -0,0 +1,38 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 模糊查询条件 + * + * @export + * @interface Search + */ +export interface Search { + + /** + * 字段名称集合 + * + * @type {Array} + * @memberof Search + */ + fields?: Array | null; + + /** + * 关键字 + * + * @type {string} + * @memberof Search + */ + keyword?: string | null; +} diff --git a/Web/src/api-services/models/update-code-gen-input.ts b/Web/src/api-services/models/update-code-gen-input.ts index fdb84a08..887afb4b 100644 --- a/Web/src/api-services/models/update-code-gen-input.ts +++ b/Web/src/api-services/models/update-code-gen-input.ts @@ -12,6 +12,8 @@ * Do not edit the class manually. */ +import { Filter } from './filter'; +import { Search } from './search'; /** * * @@ -20,6 +22,26 @@ */ export interface UpdateCodeGenInput { + /** + * @type {Search} + * @memberof UpdateCodeGenInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof UpdateCodeGenInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof UpdateCodeGenInput + */ + filter?: Filter; + /** * 当前页码 * diff --git a/Web/src/views/system/infoSetting/index.vue b/Web/src/views/system/infoSetting/index.vue index a4491d1a..eb6adc0b 100644 --- a/Web/src/views/system/infoSetting/index.vue +++ b/Web/src/views/system/infoSetting/index.vue @@ -11,7 +11,7 @@ 系统图标 --> - + @@ -46,18 +46,21 @@