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 @@