commit 8553df5dd210175506b8722f51b50e449bee4dfd
Author: fuenmao <980740792@qq.com>
Date: Mon Sep 21 14:08:22 2026 +0800
feat: initialize Evergreen Health backend
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..3729ff0
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,25 @@
+**/.classpath
+**/.dockerignore
+**/.env
+**/.git
+**/.gitignore
+**/.project
+**/.settings
+**/.toolstarget
+**/.vs
+**/.vscode
+**/*.*proj.user
+**/*.dbmdl
+**/*.jfm
+**/azds.yaml
+**/bin
+**/charts
+**/docker-compose*
+**/Dockerfile*
+**/node_modules
+**/npm-debug.log
+**/obj
+**/secrets.dev.yaml
+**/values.dev.yaml
+LICENSE
+README.md
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..989c702
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,177 @@
+[*.cs]
+#### 命名样式 ####
+
+# 命名规则
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# 符号规范
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# 命名样式
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+csharp_using_directive_placement = outside_namespace:silent
+csharp_style_expression_bodied_methods = false:silent
+csharp_style_expression_bodied_constructors = false:silent
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_properties = true:silent
+csharp_style_expression_bodied_indexers = true:silent
+csharp_style_expression_bodied_accessors = true:silent
+csharp_style_expression_bodied_lambdas = true:silent
+csharp_style_expression_bodied_local_functions = false:silent
+csharp_style_conditional_delegate_call = true:suggestion
+csharp_style_var_for_built_in_types = false:silent
+csharp_style_var_when_type_is_apparent = false:silent
+csharp_style_var_elsewhere = false:silent
+csharp_prefer_simple_using_statement = true:suggestion
+csharp_prefer_braces = true:silent
+csharp_style_namespace_declarations = file_scoped:silent
+csharp_style_prefer_top_level_statements = true:silent
+csharp_style_prefer_method_group_conversion = true:silent
+csharp_prefer_static_local_function = true:suggestion
+csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
+csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
+csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
+csharp_style_prefer_switch_expression = true:suggestion
+csharp_style_prefer_pattern_matching = true:silent
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+csharp_style_prefer_not_pattern = true:suggestion
+csharp_style_prefer_extended_property_pattern = true:suggestion
+csharp_style_throw_expression = true:suggestion
+csharp_style_prefer_null_check_over_type_check = true:suggestion
+csharp_prefer_simple_default_expression = true:suggestion
+csharp_style_prefer_local_over_anonymous_function = true:suggestion
+csharp_style_prefer_index_operator = true:suggestion
+csharp_style_prefer_range_operator = true:suggestion
+csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
+csharp_style_prefer_tuple_swap = true:suggestion
+csharp_style_prefer_utf8_string_literals = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+csharp_style_deconstructed_variable_declaration = true:suggestion
+csharp_style_unused_value_assignment_preference = discard_variable:suggestion
+csharp_style_unused_value_expression_statement_preference = discard_variable:silent
+csharp_space_around_binary_operators = before_and_after
+csharp_indent_labels = one_less_than_current
+
+[*.vb]
+#### 命名样式 ####
+
+# 命名规则
+
+dotnet_naming_rule.interface_should_be_以_i_开始.severity = suggestion
+dotnet_naming_rule.interface_should_be_以_i_开始.symbols = interface
+dotnet_naming_rule.interface_should_be_以_i_开始.style = 以_i_开始
+
+dotnet_naming_rule.类型_should_be_帕斯卡拼写法.severity = suggestion
+dotnet_naming_rule.类型_should_be_帕斯卡拼写法.symbols = 类型
+dotnet_naming_rule.类型_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
+
+dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.severity = suggestion
+dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.symbols = 非字段成员
+dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
+
+# 符号规范
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.类型.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.类型.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
+dotnet_naming_symbols.类型.required_modifiers =
+
+dotnet_naming_symbols.非字段成员.applicable_kinds = property, event, method
+dotnet_naming_symbols.非字段成员.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
+dotnet_naming_symbols.非字段成员.required_modifiers =
+
+# 命名样式
+
+dotnet_naming_style.以_i_开始.required_prefix = I
+dotnet_naming_style.以_i_开始.required_suffix =
+dotnet_naming_style.以_i_开始.word_separator =
+dotnet_naming_style.以_i_开始.capitalization = pascal_case
+
+dotnet_naming_style.帕斯卡拼写法.required_prefix =
+dotnet_naming_style.帕斯卡拼写法.required_suffix =
+dotnet_naming_style.帕斯卡拼写法.word_separator =
+dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
+
+dotnet_naming_style.帕斯卡拼写法.required_prefix =
+dotnet_naming_style.帕斯卡拼写法.required_suffix =
+dotnet_naming_style.帕斯卡拼写法.word_separator =
+dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
+
+[*.{cs,vb}]
+end_of_line = crlf
+dotnet_style_qualification_for_field = false:silent
+dotnet_style_qualification_for_property = false:silent
+dotnet_style_qualification_for_method = false:silent
+dotnet_style_qualification_for_event = false:silent
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
+dotnet_code_quality_unused_parameters = all:suggestion
+dotnet_style_readonly_field = true:suggestion
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
+dotnet_style_allow_multiple_blank_lines_experimental = true:silent
+dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_auto_properties = true:silent
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:silent
+dotnet_style_prefer_conditional_expression_over_return = true:silent
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_compound_assignment = true:suggestion
+dotnet_style_prefer_simplified_interpolation = true:suggestion
+dotnet_style_namespace_match_folder = true:suggestion
+dotnet_style_predefined_type_for_locals_parameters_members = true:silent
+dotnet_style_predefined_type_for_member_access = true:silent
+indent_size = 4
+tab_width = 4
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+
+# Add copyright file header
+file_header_template = Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。\n\n本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。\n\n不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1911d33
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,23 @@
+# Build output
+**/bin/
+**/obj/
+publish/
+logs/
+
+# IDE and user settings
+.vs/
+.idea/
+.vscode/
+*.user
+*.suo
+
+# Local secrets and runtime files
+**/Configuration/Database.local.json
+**/wwwroot/upload/
+*.db
+*.db-shm
+*.db-wal
+
+# OS files
+.DS_Store
+Thumbs.db
diff --git a/Admin.NET.Core/Admin.NET.Core.csproj b/Admin.NET.Core/Admin.NET.Core.csproj
new file mode 100644
index 0000000..0524b16
--- /dev/null
+++ b/Admin.NET.Core/Admin.NET.Core.csproj
@@ -0,0 +1,74 @@
+
+
+
+ net8.0
+ 1701;1702;1591;8632
+
+ enable
+ true
+ disable
+ True
+ Admin.NET
+ Admin.NET 通用权限开发平台
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Admin.NET.Core/Attribute/CommonValidationAttribute.cs b/Admin.NET.Core/Attribute/CommonValidationAttribute.cs
new file mode 100644
index 0000000..e58d08a
--- /dev/null
+++ b/Admin.NET.Core/Attribute/CommonValidationAttribute.cs
@@ -0,0 +1,92 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 通用接口参数验证特性类
+///
+[AttributeUsage(AttributeTargets.Property)]
+public class CommonValidationAttribute : ValidationAttribute
+{
+ private readonly Dictionary _conditions;
+ private static readonly Dictionary CompiledConditions = new();
+
+ ///
+ ///
+ /// 条件对参数,长度必须为偶数
+ /// 奇数字符串参数:动态条件
+ /// 偶数字符串参数:提示消息
+ ///
+ ///
+ ///
+ /// public class ModelInput {
+ ///
+ ///
+ /// public string A { get; set; }
+ ///
+ ///
+ /// [CommonValidation(
+ /// "A == 1 && B == null", "当 A == 1时,B不能为空",
+ /// "C == 2 && B == null", "当 C == 2时,B不能为空"
+ /// )]
+ /// public string B { get; set; }
+ /// }
+ ///
+ ///
+ public CommonValidationAttribute(params string[] conditionPairs)
+ {
+ if (conditionPairs.Length % 2 != 0) throw new ArgumentException("条件对必须以偶数个字符串的形式提供。");
+
+ var conditions = new Dictionary();
+ for (int i = 0; i < conditionPairs.Length; i += 2)
+ conditions.Add(conditionPairs[i], conditionPairs[i + 1]);
+
+ _conditions = conditions;
+ }
+
+ protected override ValidationResult IsValid(object value, ValidationContext validationContext)
+ {
+ foreach (var (expr, errorMessage) in _conditions)
+ {
+ var conditionKey = $"{validationContext.ObjectType.FullName}.{expr}";
+ if (!CompiledConditions.TryGetValue(conditionKey, out var condition))
+ {
+ condition = CreateCondition(validationContext.ObjectType, expr);
+ CompiledConditions[conditionKey] = condition;
+ }
+
+ if ((bool)condition.DynamicInvoke(validationContext.ObjectInstance)!)
+ {
+ return new ValidationResult(errorMessage ?? $"[{validationContext.MemberName}]校验失败");
+ }
+ }
+
+ return ValidationResult.Success;
+ }
+
+ private Delegate CreateCondition(Type modelType, string expression)
+ {
+ try
+ {
+ // 创建参数表达式
+ var parameter = Expression.Parameter(typeof(object), "x");
+
+ // 构建 Lambda 表达式
+ var lambda = DynamicExpressionParser.ParseLambda(new[] { Expression.Parameter(modelType, "x") }, typeof(bool), expression);
+
+ // 创建新的 Lambda 表达式,接受 object 参数并调用编译后的表达式
+ var invokeExpression = Expression.Invoke(lambda, Expression.Convert(parameter, modelType));
+ var finalLambda = Expression.Lambda>(invokeExpression, parameter);
+
+ return finalLambda.Compile();
+ }
+ catch (Exception ex)
+ {
+ throw new ArgumentException($"无法解析表达式 '{expression}': {ex.Message}", ex);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/ConstAttribute.cs b/Admin.NET.Core/Attribute/ConstAttribute.cs
new file mode 100644
index 0000000..baf5a60
--- /dev/null
+++ b/Admin.NET.Core/Attribute/ConstAttribute.cs
@@ -0,0 +1,22 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 常量特性
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
+public class ConstAttribute : Attribute
+{
+ public string Name { get; set; }
+
+ public ConstAttribute(string name)
+ {
+ Name = name;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/CustomJsonPropertyAttribute.cs b/Admin.NET.Core/Attribute/CustomJsonPropertyAttribute.cs
new file mode 100644
index 0000000..a5895f4
--- /dev/null
+++ b/Admin.NET.Core/Attribute/CustomJsonPropertyAttribute.cs
@@ -0,0 +1,21 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 自定义Json转换字段名
+///
+[AttributeUsage(AttributeTargets.Property)]
+public class CustomJsonPropertyAttribute : Attribute
+{
+ public string Name { get; }
+
+ public CustomJsonPropertyAttribute(string name)
+ {
+ Name = name;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/CustomUnifyResultAttribute.cs b/Admin.NET.Core/Attribute/CustomUnifyResultAttribute.cs
new file mode 100644
index 0000000..0543422
--- /dev/null
+++ b/Admin.NET.Core/Attribute/CustomUnifyResultAttribute.cs
@@ -0,0 +1,22 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 自定义规范化结果特性
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
+public class CustomUnifyResultAttribute : Attribute
+{
+ public string Name { get; set; }
+
+ public CustomUnifyResultAttribute(string name)
+ {
+ Name = name;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/DataMaskAttribute.cs b/Admin.NET.Core/Attribute/DataMaskAttribute.cs
new file mode 100644
index 0000000..d7eafc2
--- /dev/null
+++ b/Admin.NET.Core/Attribute/DataMaskAttribute.cs
@@ -0,0 +1,59 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 数据脱敏特性(支持自定义脱敏位置和脱敏字符)
+///
+[AttributeUsage(AttributeTargets.Property)]
+public class DataMaskAttribute : Attribute
+{
+ ///
+ /// 脱敏起始位置(从0开始)
+ ///
+ private int StartIndex { get; }
+
+ ///
+ /// 脱敏长度
+ ///
+ private int Length { get; }
+
+ ///
+ /// 脱敏字符(默认*)
+ ///
+ private char MaskChar { get; set; } = '*';
+
+ ///
+ /// 是否保留原始长度(默认true)
+ ///
+ private bool KeepLength { get; set; } = true;
+
+ public DataMaskAttribute(int startIndex, int length)
+ {
+ if (startIndex < 0) throw new ArgumentOutOfRangeException(nameof(startIndex));
+ if (length <= 0) throw new ArgumentOutOfRangeException(nameof(length));
+
+ StartIndex = startIndex;
+ Length = length;
+ }
+
+ ///
+ /// 执行脱敏处理
+ ///
+ public string Mask(string input)
+ {
+ if (string.IsNullOrEmpty(input) || input.Length <= StartIndex)
+ return input;
+
+ var maskedLength = Math.Min(Length, input.Length - StartIndex);
+ var maskStr = new string(MaskChar, KeepLength ? maskedLength : Math.Min(4, maskedLength));
+
+ return input.Substring(0, StartIndex) + maskStr +
+ (StartIndex + maskedLength < input.Length ?
+ input.Substring(StartIndex + maskedLength) : "");
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/DictAttribute.cs b/Admin.NET.Core/Attribute/DictAttribute.cs
new file mode 100644
index 0000000..2a1fae8
--- /dev/null
+++ b/Admin.NET.Core/Attribute/DictAttribute.cs
@@ -0,0 +1,138 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 字典值合规性校验特性
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true, Inherited = true)]
+public class DictAttribute : ValidationAttribute, ITransient
+{
+ ///
+ /// 字典编码
+ ///
+ public string DictTypeCode { get; }
+
+ ///
+ /// 是否允许空字符串
+ ///
+ public bool AllowEmptyStrings { get; set; } = false;
+
+ ///
+ /// 允许空值,有值才验证,默认 false
+ ///
+ public bool AllowNullValue { get; set; } = false;
+
+ ///
+ /// 字典值合规性校验特性
+ ///
+ ///
+ ///
+ public DictAttribute(string dictTypeCode = "", string errorMessage = "字典值不合法!")
+ {
+ DictTypeCode = dictTypeCode;
+ ErrorMessage = errorMessage;
+ }
+
+ ///
+ /// 字典值合规性校验
+ ///
+ ///
+ ///
+ ///
+ protected override ValidationResult IsValid(object? value, ValidationContext validationContext)
+ {
+ // 判断是否允许空值
+ if (AllowNullValue && value == null) return ValidationResult.Success;
+
+ // 获取属性的类型
+ var property = validationContext.ObjectType.GetProperty(validationContext.MemberName!);
+ if (property == null) return new ValidationResult($"未知属性: {validationContext.MemberName}");
+
+ string importHeaderName = GetImporterHeaderName(property, validationContext.MemberName);
+
+ var propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
+
+ // 先尝试从 ValidationContext 的依赖注入容器中拿服务,拿不到或类型不匹配时,再从全局的 App 容器中获取
+ if (validationContext.GetService(typeof(SysDictDataService)) is not SysDictDataService sysDictDataService)
+ sysDictDataService = App.GetRequiredService();
+
+ // 获取字典值列表
+ var dictDataList = sysDictDataService.GetDataList(DictTypeCode).GetAwaiter().GetResult();
+
+ // 使用 HashSet 来提高查找效率
+ var dictHash = new HashSet(dictDataList.Select(u => u.Value));
+
+ // 判断是否为集合类型
+ if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>))
+ {
+ // 如果是空集合并且允许空值,则直接返回成功
+ if (value == null && AllowNullValue) return ValidationResult.Success;
+
+ // 处理集合为空的情况
+ var collection = value as IEnumerable;
+ if (collection == null) return ValidationResult.Success;
+
+ // 获取集合的元素类型
+ var elementType = propertyType.GetGenericArguments()[0];
+ var underlyingElementType = Nullable.GetUnderlyingType(elementType) ?? elementType;
+
+ // 如果元素类型是枚举,则逐个验证
+ if (underlyingElementType.IsEnum)
+ {
+ foreach (var item in collection)
+ {
+ if (item == null && AllowNullValue) continue;
+
+ if (!Enum.IsDefined(underlyingElementType, item!))
+ return new ValidationResult($"提示:{ErrorMessage}|枚举值【{item}】不是有效的【{underlyingElementType.Name}】枚举类型值!", [importHeaderName]);
+ }
+ return ValidationResult.Success;
+ }
+
+ foreach (var item in collection)
+ {
+ if (item == null && AllowNullValue) continue;
+
+ var itemString = item?.ToString();
+ if (!dictHash.Contains(itemString))
+ return new ValidationResult($"提示:{ErrorMessage}|字典【{DictTypeCode}】不包含【{itemString}】!", [importHeaderName]);
+ }
+
+ return ValidationResult.Success;
+ }
+
+ var valueAsString = value?.ToString();
+
+ // 是否忽略空字符串
+ if (AllowEmptyStrings && string.IsNullOrEmpty(valueAsString)) return ValidationResult.Success;
+
+ // 枚举类型验证
+ if (propertyType.IsEnum)
+ {
+ if (!Enum.IsDefined(propertyType, value!)) return new ValidationResult($"提示:{ErrorMessage}|枚举值【{value}】不是有效的【{propertyType.Name}】枚举类型值!", [importHeaderName]);
+ return ValidationResult.Success;
+ }
+
+ if (!dictHash.Contains(valueAsString))
+ return new ValidationResult($"提示:{ErrorMessage}|字典【{DictTypeCode}】不包含【{valueAsString}】!", [importHeaderName]);
+
+ return ValidationResult.Success;
+ }
+
+ ///
+ /// 获取本字段上 [ImporterHeader(Name = "xxx")] 里的Name,如果没有则使用defaultName.
+ /// 用于在从excel导入数据时,能让调用者知道是哪个字段验证失败,而不是抛异常
+ ///
+ private static string GetImporterHeaderName(PropertyInfo property, string defaultName)
+ {
+ var importerHeader = property.GetCustomAttribute();
+ string importerHeaderName = importerHeader?.Name ?? defaultName;
+ return importerHeaderName;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/EnumAttribute.cs b/Admin.NET.Core/Attribute/EnumAttribute.cs
new file mode 100644
index 0000000..96e3295
--- /dev/null
+++ b/Admin.NET.Core/Attribute/EnumAttribute.cs
@@ -0,0 +1,53 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 枚举值合规性校验特性
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Property | AttributeTargets.Enum | AttributeTargets.Field, AllowMultiple = true)]
+public class EnumAttribute : ValidationAttribute, ITransient
+{
+ ///
+ /// 枚举值合规性校验特性
+ ///
+ ///
+ public EnumAttribute(string errorMessage = "枚举值不合法!")
+ {
+ ErrorMessage = errorMessage;
+ }
+
+ ///
+ /// 枚举值合规性校验
+ ///
+ ///
+ ///
+ ///
+ protected override ValidationResult IsValid(object value, ValidationContext validationContext)
+ {
+ // 获取属性的类型
+ var property = validationContext.ObjectType.GetProperty(validationContext.MemberName);
+ if (property == null)
+ return new ValidationResult($"未知属性: {validationContext.MemberName}");
+
+ var propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
+
+ // 检查属性类型是否为枚举或可空枚举类型
+ if (!propertyType.IsEnum)
+ return new ValidationResult($"属性类型'{validationContext.MemberName}'不是有效的枚举类型!");
+
+ // 检查枚举值是否有效
+ if (value == null && Nullable.GetUnderlyingType(property.PropertyType) == null)
+ return new ValidationResult($"提示:{ErrorMessage}|枚举值不能为 null!");
+
+ if (value != null && !Enum.IsDefined(propertyType, value))
+ return new ValidationResult($"提示:{ErrorMessage}|枚举值【{value}】不是有效的【{propertyType.Name}】枚举类型值!");
+
+ return ValidationResult.Success;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/IdempotentAttribute.cs b/Admin.NET.Core/Attribute/IdempotentAttribute.cs
new file mode 100644
index 0000000..ed692a4
--- /dev/null
+++ b/Admin.NET.Core/Attribute/IdempotentAttribute.cs
@@ -0,0 +1,112 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using Newtonsoft.Json;
+using System.Security.Claims;
+
+namespace Admin.NET.Core;
+
+///
+/// 防止重复请求过滤器特性(此特性使用了分布式锁,需确保系统支持分布式锁)
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
+public class IdempotentAttribute : Attribute, IAsyncActionFilter
+{
+ ///
+ /// 请求间隔时间/秒
+ ///
+ public int IntervalTime { get; set; } = 5;
+
+ ///
+ /// 错误提示内容
+ ///
+ public string Message { get; set; } = "你操作频率过快,请稍后重试!";
+
+ ///
+ /// 缓存前缀: Key+请求路由+用户Id+请求参数
+ ///
+ public string CacheKey { get; set; } = CacheConst.KeyIdempotent;
+
+ ///
+ /// 是否直接抛出异常:Ture是,False返回上次请求结果
+ ///
+ public bool ThrowBah { get; set; }
+
+ ///
+ /// 锁前缀
+ ///
+ public string LockPrefix { get; set; } = "lock_";
+
+ public IdempotentAttribute()
+ {
+ }
+
+ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
+ {
+ var httpContext = context.HttpContext;
+ var path = httpContext.Request.Path.Value.ToString();
+ var userId = httpContext.User?.FindFirstValue(ClaimConst.UserId);
+ var cacheExpireTime = TimeSpan.FromSeconds(IntervalTime);
+
+ var parameters = JsonConvert.SerializeObject(context.ActionArguments, Formatting.None, new JsonSerializerSettings
+ {
+ NullValueHandling = NullValueHandling.Include,
+ DefaultValueHandling = DefaultValueHandling.Include
+ });
+
+ var cacheKey = CacheKey + MD5Encryption.Encrypt($"{path}{userId}{parameters}");
+ var sysCacheService = httpContext.RequestServices.GetService();
+ try
+ {
+ // 分布式锁
+ using var distributedLock = sysCacheService.BeginCacheLock($"{LockPrefix}{cacheKey}") ?? throw Oops.Oh(Message);
+
+ var cacheValue = sysCacheService.Get(cacheKey);
+ if (cacheValue != null)
+ {
+ if (ThrowBah) throw Oops.Oh(Message);
+ context.Result = new ObjectResult(cacheValue.Value);
+ return;
+ }
+ else
+ {
+ var resultContext = await next();
+ // 缓存请求结果,null值不缓存
+ if (resultContext.Result is ObjectResult { Value: { } } objectResult)
+ {
+ var typeName = objectResult.Value.GetType().Name;
+ var responseData = new ResponseData
+ {
+ Type = typeName,
+ Value = objectResult.Value
+ };
+ sysCacheService.Set(cacheKey, responseData, cacheExpireTime);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ throw Oops.Oh($"{Message}-{ex}");
+ }
+ }
+
+ ///
+ /// 请求结果数据
+ ///
+ private class ResponseData
+ {
+ ///
+ /// 结果类型
+ ///
+ public string Type { get; set; }
+
+ ///
+ /// 请求结果
+ ///
+ public dynamic Value { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/IgnoreEnumToDictAttribute.cs b/Admin.NET.Core/Attribute/IgnoreEnumToDictAttribute.cs
new file mode 100644
index 0000000..067dc0a
--- /dev/null
+++ b/Admin.NET.Core/Attribute/IgnoreEnumToDictAttribute.cs
@@ -0,0 +1,16 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 忽略枚举类型转字典特性(标记在枚举类型)
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Enum, AllowMultiple = true, Inherited = true)]
+public class IgnoreEnumToDictAttribute : Attribute
+{
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/IgnoreTableAttribute.cs b/Admin.NET.Core/Attribute/IgnoreTableAttribute.cs
new file mode 100644
index 0000000..5fb65b9
--- /dev/null
+++ b/Admin.NET.Core/Attribute/IgnoreTableAttribute.cs
@@ -0,0 +1,16 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 忽略表结构初始化特性(标记在实体)
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+public class IgnoreTableAttribute : Attribute
+{
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/IgnoreUpdateSeedAttribute.cs b/Admin.NET.Core/Attribute/IgnoreUpdateSeedAttribute.cs
new file mode 100644
index 0000000..9ea18da
--- /dev/null
+++ b/Admin.NET.Core/Attribute/IgnoreUpdateSeedAttribute.cs
@@ -0,0 +1,16 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 忽略更新种子特性(标记在种子类)
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+public class IgnoreUpdateSeedAttribute : Attribute
+{
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/IgnoreUpdateSeedColumnAttribute.cs b/Admin.NET.Core/Attribute/IgnoreUpdateSeedColumnAttribute.cs
new file mode 100644
index 0000000..1bccc81
--- /dev/null
+++ b/Admin.NET.Core/Attribute/IgnoreUpdateSeedColumnAttribute.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 IgnoreUpdateSeedColumnAttribute : Attribute
+{
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/ImportDictAttribute.cs b/Admin.NET.Core/Attribute/ImportDictAttribute.cs
new file mode 100644
index 0000000..552df72
--- /dev/null
+++ b/Admin.NET.Core/Attribute/ImportDictAttribute.cs
@@ -0,0 +1,24 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 属性字典配置
+///
+[AttributeUsage(AttributeTargets.Property)]
+public class ImportDictAttribute : Attribute
+{
+ ///
+ /// 字典Code
+ ///
+ public string TypeCode { get; set; }
+
+ ///
+ /// 目标对象名称
+ ///
+ public string TargetPropName { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/IncreSeedAttribute.cs b/Admin.NET.Core/Attribute/IncreSeedAttribute.cs
new file mode 100644
index 0000000..9ab1f02
--- /dev/null
+++ b/Admin.NET.Core/Attribute/IncreSeedAttribute.cs
@@ -0,0 +1,16 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 增量种子特性
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+public class IncreSeedAttribute : Attribute
+{
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/IncreTableAttribute.cs b/Admin.NET.Core/Attribute/IncreTableAttribute.cs
new file mode 100644
index 0000000..31f31b7
--- /dev/null
+++ b/Admin.NET.Core/Attribute/IncreTableAttribute.cs
@@ -0,0 +1,16 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 增量表特性
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+public class IncreTableAttribute : Attribute
+{
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/LogTableAttribute.cs b/Admin.NET.Core/Attribute/LogTableAttribute.cs
new file mode 100644
index 0000000..aa07fd4
--- /dev/null
+++ b/Admin.NET.Core/Attribute/LogTableAttribute.cs
@@ -0,0 +1,16 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 日志表特性
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+public class LogTableAttribute : Attribute
+{
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/MaskNewtonsoftJsonConverter.cs b/Admin.NET.Core/Attribute/MaskNewtonsoftJsonConverter.cs
new file mode 100644
index 0000000..a09c801
--- /dev/null
+++ b/Admin.NET.Core/Attribute/MaskNewtonsoftJsonConverter.cs
@@ -0,0 +1,60 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using Newtonsoft.Json;
+
+namespace Admin.NET.Core;
+
+///
+/// 字符串掩码
+///
+[SuppressSniffer]
+public class MaskNewtonsoftJsonConverter : JsonConverter
+{
+ public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ return reader.Value.ToString();
+ }
+
+ public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer)
+ {
+ writer.WriteValue(value?.ToString().Mask());
+ }
+}
+
+///
+/// 身份证掩码
+///
+[SuppressSniffer]
+public class MaskIdCardNewtonsoftJsonConverter : JsonConverter
+{
+ public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ return reader.Value.ToString();
+ }
+
+ public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer)
+ {
+ writer.WriteValue(value?.ToString().MaskIdCard());
+ }
+}
+
+///
+/// 邮箱掩码
+///
+[SuppressSniffer]
+public class MaskEmailNewtonsoftJsonConverter : JsonConverter
+{
+ public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ return reader.Value.ToString();
+ }
+
+ public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer)
+ {
+ writer.WriteValue(value?.ToString().MaskEmail());
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/MaskSystemTextJsonConverter.cs b/Admin.NET.Core/Attribute/MaskSystemTextJsonConverter.cs
new file mode 100644
index 0000000..6b1a12f
--- /dev/null
+++ b/Admin.NET.Core/Attribute/MaskSystemTextJsonConverter.cs
@@ -0,0 +1,61 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Admin.NET.Core;
+
+///
+/// 字符串掩码
+///
+[SuppressSniffer]
+public class MaskSystemTextJsonConverter : JsonConverter
+{
+ public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ return reader.GetString();
+ }
+
+ public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
+ {
+ writer.WriteStringValue(value?.ToString().Mask());
+ }
+}
+
+///
+/// 身份证掩码
+///
+[SuppressSniffer]
+public class MaskIdCardSystemTextJsonConverter : JsonConverter
+{
+ public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ return reader.GetString();
+ }
+
+ public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
+ {
+ writer.WriteStringValue(value?.ToString().MaskIdCard());
+ }
+}
+
+///
+/// 邮箱掩码
+///
+[SuppressSniffer]
+public class MaskEmailSystemTextJsonConverter : JsonConverter
+{
+ public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ return reader.GetString();
+ }
+
+ public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
+ {
+ writer.WriteStringValue(value?.ToString().MaskEmail());
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/MaxValueAttribute.cs b/Admin.NET.Core/Attribute/MaxValueAttribute.cs
new file mode 100644
index 0000000..8132890
--- /dev/null
+++ b/Admin.NET.Core/Attribute/MaxValueAttribute.cs
@@ -0,0 +1,39 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 最大值校验
+///
+[SuppressSniffer]
+public class MaxValueAttribute : ValidationAttribute
+{
+ private double MaxValue { get; }
+
+ ///
+ /// 最大值
+ ///
+ ///
+ public MaxValueAttribute(double value) => this.MaxValue = value;
+
+ ///
+ /// 最大值校验
+ ///
+ ///
+ ///
+ public override bool IsValid(object value)
+ {
+ return value == null || Convert.ToDouble(value) <= this.MaxValue;
+ }
+
+ ///
+ /// 错误信息
+ ///
+ ///
+ ///
+ public override string FormatErrorMessage(string name) => base.FormatErrorMessage(name);
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/MinValueAttribute.cs b/Admin.NET.Core/Attribute/MinValueAttribute.cs
new file mode 100644
index 0000000..40c7378
--- /dev/null
+++ b/Admin.NET.Core/Attribute/MinValueAttribute.cs
@@ -0,0 +1,39 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 最小值校验
+///
+[SuppressSniffer]
+public class MinValueAttribute : ValidationAttribute
+{
+ private double MinValue { get; set; }
+
+ ///
+ /// 最小值
+ ///
+ ///
+ public MinValueAttribute(double value) => this.MinValue = value;
+
+ ///
+ /// 最小值校验
+ ///
+ ///
+ ///
+ public override bool IsValid(object value)
+ {
+ return value == null || Convert.ToDouble(value) > this.MinValue;
+ }
+
+ ///
+ /// 错误信息
+ ///
+ ///
+ ///
+ public override string FormatErrorMessage(string name) => base.FormatErrorMessage(name);
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/NotEmptyAttribute.cs b/Admin.NET.Core/Attribute/NotEmptyAttribute.cs
new file mode 100644
index 0000000..a021120
--- /dev/null
+++ b/Admin.NET.Core/Attribute/NotEmptyAttribute.cs
@@ -0,0 +1,28 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 校验集合不能为空
+///
+[SuppressSniffer]
+public class NotEmptyAttribute : ValidationAttribute
+{
+ ///
+ /// 校验集合不能为空
+ ///
+ ///
+ ///
+ public override bool IsValid(object value) => (value as IEnumerable)?.GetEnumerator().MoveNext() ?? false;
+
+ ///
+ /// 错误信息
+ ///
+ ///
+ ///
+ public override string FormatErrorMessage(string name) => base.FormatErrorMessage(name);
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/OwnerOrgAttribute.cs b/Admin.NET.Core/Attribute/OwnerOrgAttribute.cs
new file mode 100644
index 0000000..468272c
--- /dev/null
+++ b/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.Core/Attribute/OwnerUserAttribute.cs b/Admin.NET.Core/Attribute/OwnerUserAttribute.cs
new file mode 100644
index 0000000..4fc7c69
--- /dev/null
+++ b/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.Core/Attribute/SeedDataAttribute.cs b/Admin.NET.Core/Attribute/SeedDataAttribute.cs
new file mode 100644
index 0000000..1463eff
--- /dev/null
+++ b/Admin.NET.Core/Attribute/SeedDataAttribute.cs
@@ -0,0 +1,25 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 种子数据特性
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+public class SeedDataAttribute : Attribute
+{
+ ///
+ /// 排序(越大越后执行)
+ ///
+ public int Order { get; set; } = 0;
+
+ public SeedDataAttribute(int orderNo)
+ {
+ Order = orderNo;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/SysTableAttribute.cs b/Admin.NET.Core/Attribute/SysTableAttribute.cs
new file mode 100644
index 0000000..f526b42
--- /dev/null
+++ b/Admin.NET.Core/Attribute/SysTableAttribute.cs
@@ -0,0 +1,16 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统表特性
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+public class SysTableAttribute : Attribute
+{
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Attribute/ThemeAttribute.cs b/Admin.NET.Core/Attribute/ThemeAttribute.cs
new file mode 100644
index 0000000..48be9d9
--- /dev/null
+++ b/Admin.NET.Core/Attribute/ThemeAttribute.cs
@@ -0,0 +1,22 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 枚举拓展主题样式
+///
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field)]
+public class ThemeAttribute : Attribute
+{
+ public string Theme { get; private set; }
+
+ public ThemeAttribute(string theme)
+ {
+ this.Theme = theme;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Cache/CacheSetup.cs b/Admin.NET.Core/Cache/CacheSetup.cs
new file mode 100644
index 0000000..5d55ecf
--- /dev/null
+++ b/Admin.NET.Core/Cache/CacheSetup.cs
@@ -0,0 +1,43 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using NewLife.Caching.Services;
+
+namespace Admin.NET.Core;
+
+public static class CacheSetup
+{
+ ///
+ /// 缓存注册(新生命Redis组件)
+ ///
+ ///
+ public static void AddCache(this IServiceCollection services)
+ {
+ var cacheOptions = App.GetConfig("Cache", true);
+ if (cacheOptions.CacheType == CacheTypeEnum.Redis.ToString())
+ {
+ var redis = new FullRedis(new RedisOptions
+ {
+ Configuration = cacheOptions.Redis.Configuration,
+ Prefix = cacheOptions.Redis.Prefix
+ })
+ {
+ // 自动检测集群节点
+ AutoDetect = App.GetConfig("Cache:Redis:AutoDetect", true)
+ };
+ // 最大消息大小
+ if (cacheOptions.Redis.MaxMessageSize > 0)
+ redis.MaxMessageSize = cacheOptions.Redis.MaxMessageSize;
+
+ // 注入 Redis 缓存提供者
+ services.AddSingleton(u => new RedisCacheProvider(u) { Cache = redis });
+ }
+
+ // 内存缓存兜底。在没有配置Redis时,使用内存缓存,逻辑代码无需修改
+ services.TryAddSingleton();
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Cache/SqlSugarCache.cs b/Admin.NET.Core/Cache/SqlSugarCache.cs
new file mode 100644
index 0000000..6bbcda6
--- /dev/null
+++ b/Admin.NET.Core/Cache/SqlSugarCache.cs
@@ -0,0 +1,56 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// SqlSugar二级缓存
+///
+public class SqlSugarCache : ICacheService
+{
+ ///
+ /// 系统缓存服务
+ ///
+ private static readonly SysCacheService _cache = App.GetRequiredService();
+
+ public void Add(string key, V value)
+ {
+ _cache.Set($"{CacheConst.SqlSugar}{key}", value);
+ }
+
+ public void Add(string key, V value, int cacheDurationInSeconds)
+ {
+ _cache.Set($"{CacheConst.SqlSugar}{key}", value, TimeSpan.FromSeconds(cacheDurationInSeconds));
+ }
+
+ public bool ContainsKey(string key)
+ {
+ return _cache.ExistKey($"{CacheConst.SqlSugar}{key}");
+ }
+
+ public V Get(string key)
+ {
+ return _cache.Get($"{CacheConst.SqlSugar}{key}");
+ }
+
+ public IEnumerable GetAllKey()
+ {
+ return _cache.GetKeysByPrefixKey(CacheConst.SqlSugar);
+ }
+
+ public V GetOrCreate(string key, Func create, int cacheDurationInSeconds = int.MaxValue)
+ {
+ return _cache.GetOrAdd($"{CacheConst.SqlSugar}{key}", (cacheKey) =>
+ {
+ return create();
+ }, cacheDurationInSeconds);
+ }
+
+ public void Remove(string key)
+ {
+ _cache.Remove(key); // SqlSugar调用Remove方法时,key中已包含了CacheConst.SqlSugar前缀
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Const/AlipayConst.cs b/Admin.NET.Core/Const/AlipayConst.cs
new file mode 100644
index 0000000..d6c4dda
--- /dev/null
+++ b/Admin.NET.Core/Const/AlipayConst.cs
@@ -0,0 +1,39 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 支付宝支付常量
+///
+[SuppressSniffer]
+public class AlipayConst
+{
+ ///
+ /// 单笔无密转账【业务场景】固定值
+ ///
+ public const string BizScene = "DIRECT_TRANSFER";
+
+ ///
+ /// 单笔无密转账【销售产品码】固定值
+ ///
+ public const string ProductCode = "TRANS_ACCOUNT_NO_PWD";
+
+ ///
+ /// 交易状态参数名
+ ///
+ public const string TradeStatus = "trade_status";
+
+ ///
+ /// 交易成功标识
+ ///
+ public const string TradeSuccess = "TRADE_SUCCESS";
+
+ ///
+ /// 授权类型
+ ///
+ public const string GrantType = "authorization_code";
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Const/CacheConst.cs b/Admin.NET.Core/Const/CacheConst.cs
new file mode 100644
index 0000000..3a0a3b9
--- /dev/null
+++ b/Admin.NET.Core/Const/CacheConst.cs
@@ -0,0 +1,128 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 缓存相关常量
+///
+public class CacheConst
+{
+ ///
+ /// 用户权限缓存(按钮集合)
+ ///
+ public const string KeyUserButton = "sys_user_button:";
+
+ ///
+ /// 用户机构缓存
+ ///
+ public const string KeyUserOrg = "sys_user_org:";
+
+ ///
+ /// 角色最大数据范围缓存
+ ///
+ public const string KeyRoleMaxDataScope = "sys_role_maxDataScope:";
+
+ ///
+ /// 在线用户缓存
+ ///
+ public const string KeyUserOnline = "sys_user_online:";
+
+ ///
+ /// 图形验证码缓存
+ ///
+ public const string KeyVerCode = "sys_verCode:";
+
+ ///
+ /// 手机验证码缓存
+ ///
+ public const string KeyPhoneVerCode = "sys_phoneVerCode:";
+
+ ///
+ /// 密码错误次数缓存
+ ///
+ public const string KeyPasswordErrorTimes = "sys_password_error_times:";
+
+ ///
+ /// 租户缓存
+ ///
+ public const string KeyTenant = "sys_tenant";
+
+ ///
+ /// 常量下拉框
+ ///
+ public const string KeyConst = "sys_const:";
+
+ ///
+ /// 所有缓存关键字集合
+ ///
+ public const string KeyAll = "sys_keys";
+
+ ///
+ /// SqlSugar二级缓存
+ ///
+ public const string SqlSugar = "sys_sqlSugar:";
+
+ ///
+ /// 开放接口身份缓存
+ ///
+ public const string KeyOpenAccess = "sys_open_access:";
+
+ ///
+ /// 开放接口身份随机数缓存
+ ///
+ public const string KeyOpenAccessNonce = "sys_open_access_nonce:";
+
+ ///
+ /// 登录黑名单
+ ///
+ public const string KeyBlacklist = "sys_blacklist:";
+
+ ///
+ /// 系统配置缓存
+ ///
+ public const string KeyConfig = "sys_config:";
+
+ ///
+ /// 系统租户配置缓存
+ ///
+ public const string KeyTenantConfig = "sys_tenant_config:";
+
+ ///
+ /// 系统用户配置缓存
+ ///
+ public const string KeyUserConfig = "sys_user_config:";
+
+ ///
+ /// 系统字典缓存
+ ///
+ public const string KeyDict = "sys_dict:";
+
+ ///
+ /// 系统租户字典缓存
+ ///
+ public const string KeyTenantDict = "sys_tenant_dict:";
+
+ ///
+ /// 重复请求(幂等)字典缓存
+ ///
+ public const string KeyIdempotent = "sys_idempotent:";
+
+ ///
+ /// Excel临时文件缓存
+ ///
+ public const string KeyExcelTemp = "sys_excel_temp:";
+
+ ///
+ /// 系统更新命令日志缓存
+ ///
+ public const string KeySysUpdateLog = "sys_update_log";
+
+ ///
+ /// 系统更新间隔标记缓存
+ ///
+ public const string KeySysUpdateInterval = "sys_update_interval";
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Const/ClaimConst.cs b/Admin.NET.Core/Const/ClaimConst.cs
new file mode 100644
index 0000000..7b3218b
--- /dev/null
+++ b/Admin.NET.Core/Const/ClaimConst.cs
@@ -0,0 +1,73 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// Claim相关常量
+///
+public class ClaimConst
+{
+ ///
+ /// 用户Id
+ ///
+ public const string UserId = "UserId";
+
+ ///
+ /// 账号
+ ///
+ public const string Account = "Account";
+
+ ///
+ /// 真实姓名
+ ///
+ public const string RealName = "RealName";
+
+ ///
+ /// 昵称
+ ///
+ public const string NickName = "NickName";
+
+ ///
+ /// 账号类型
+ ///
+ public const string AccountType = "AccountType";
+
+ ///
+ /// 租户Id
+ ///
+ public const string TenantId = "TenantId";
+
+ ///
+ /// 组织机构Id
+ ///
+ public const string OrgId = "OrgId";
+
+ ///
+ /// 组织机构名称
+ ///
+ public const string OrgName = "OrgName";
+
+ ///
+ /// 组织机构类型
+ ///
+ public const string OrgType = "OrgType";
+
+ ///
+ /// 微信OpenId
+ ///
+ public const string OpenId = "OpenId";
+
+ ///
+ /// 登录模式PC、APP
+ ///
+ public const string LoginMode = "LoginMode";
+
+ ///
+ /// 语言代码
+ ///
+ public const string LangCode = "LangCode";
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Const/CommonConst.cs b/Admin.NET.Core/Const/CommonConst.cs
new file mode 100644
index 0000000..dec1d9f
--- /dev/null
+++ b/Admin.NET.Core/Const/CommonConst.cs
@@ -0,0 +1,39 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 通用常量
+///
+[Const("平台配置")]
+public class CommonConst
+{
+ ///
+ /// 日志分组名称
+ ///
+ public const string SysLogCategoryName = "System.Logging.LoggingMonitor";
+
+ ///
+ /// 事件-增加异常日志
+ ///
+ public const string AddExLog = "Add:ExLog";
+
+ ///
+ /// 事件-发送异常邮件
+ ///
+ public const string SendErrorMail = "Send:ErrorMail";
+
+ ///
+ /// 默认基本角色名称
+ ///
+ public const string DefaultBaseRoleName = "默认基本角色";
+
+ ///
+ /// 默认基本角色编码
+ ///
+ public const string DefaultBaseRoleCode = "default_base_role";
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Const/ConfigConst.cs b/Admin.NET.Core/Const/ConfigConst.cs
new file mode 100644
index 0000000..bc35f05
--- /dev/null
+++ b/Admin.NET.Core/Const/ConfigConst.cs
@@ -0,0 +1,148 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 配置常量
+///
+public class ConfigConst
+{
+ ///
+ /// 演示环境
+ ///
+ public const string SysDemoEnv = "sys_demo";
+
+ ///
+ /// 默认密码
+ ///
+ public const string SysPassword = "sys_password";
+
+ ///
+ /// 密码最大错误次数
+ ///
+ public const string SysPasswordMaxErrorTimes = "sys_password_max_error_times";
+
+ ///
+ /// 日志保留天数
+ ///
+ public const string SysLogRetentionDays = "sys_log_retention_days";
+
+ ///
+ /// 记录操作日志
+ ///
+ public const string SysOpLog = "sys_oplog";
+
+ ///
+ /// 单设备登录
+ ///
+ public const string SysSingleLogin = "sys_single_login";
+
+ ///
+ /// 登入登出提醒
+ ///
+ public const string SysLoginOutReminder = "sys_login_out_reminder";
+
+ ///
+ /// 登陆时隐藏租户
+ ///
+ public const string SysHideTenantLogin = "sys_hide_tenant_login";
+
+ ///
+ /// 登录二次验证
+ ///
+ public const string SysSecondVer = "sys_second_ver";
+
+ ///
+ /// 图形验证码
+ ///
+ public const string SysCaptcha = "sys_captcha";
+
+ ///
+ /// Token过期时间
+ ///
+ public const string SysTokenExpire = "sys_token_expire";
+
+ ///
+ /// RefreshToken过期时间
+ ///
+ public const string SysRefreshTokenExpire = "sys_refresh_token_expire";
+
+ ///
+ /// 发送异常日志邮件
+ ///
+ public const string SysErrorMail = "sys_error_mail";
+
+ ///
+ /// 域登录验证
+ ///
+ public const string SysDomainLogin = "sys_domain_login";
+
+ // ///
+ // /// 租户域名隔离登录验证
+ // ///
+ // public const string SysTenantHostLogin = "sys_tenant_host_login";
+
+ ///
+ /// 数据校验日志
+ ///
+ public const string SysValidationLog = "sys_validation_log";
+
+ ///
+ /// 行政区域同步层级 1-省级,2-市级,3-区县级,4-街道级,5-村级
+ ///
+ public const string SysRegionSyncLevel = "sys_region_sync_level";
+
+ ///
+ /// Default 分组
+ ///
+ public const string SysDefaultGroup = "Default";
+
+ ///
+ /// 支付宝授权页面地址
+ ///
+ public const string AlipayAuthPageUrl = "alipay_auth_page_url_";
+
+ // ///
+ // /// 系统图标
+ // ///
+ // 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.Core/Const/SqlSugarConst.cs b/Admin.NET.Core/Const/SqlSugarConst.cs
new file mode 100644
index 0000000..ddbcbd4
--- /dev/null
+++ b/Admin.NET.Core/Const/SqlSugarConst.cs
@@ -0,0 +1,33 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// SqlSugar相关常量
+///
+public class SqlSugarConst
+{
+ ///
+ /// 默认主数据库标识(默认租户)
+ ///
+ public const string MainConfigId = "1300000000001";
+
+ ///
+ /// 默认日志数据库标识
+ ///
+ public const string LogConfigId = "1300000000002";
+
+ ///
+ /// 默认表主键
+ ///
+ public const string PrimaryKey = "Id";
+
+ ///
+ /// 默认租户Id
+ ///
+ public const long DefaultTenantId = 1300000000001;
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/ElasticSearch/ElasticSearchClientContainer.cs b/Admin.NET.Core/ElasticSearch/ElasticSearchClientContainer.cs
new file mode 100644
index 0000000..6c25664
--- /dev/null
+++ b/Admin.NET.Core/ElasticSearch/ElasticSearchClientContainer.cs
@@ -0,0 +1,47 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using Elastic.Clients.Elasticsearch;
+
+namespace Admin.NET.Core;
+
+///
+/// ES客户端容器
+///
+public class ElasticSearchClientContainer
+{
+ private readonly Dictionary _clients;
+
+ ///
+ /// 初始化容器(通过字典注入所有客户端)
+ ///
+ public ElasticSearchClientContainer(Dictionary clients)
+ {
+ _clients = clients ?? throw new ArgumentNullException(nameof(clients));
+ }
+
+ ///
+ /// 日志专用客户端
+ ///
+ public ElasticsearchClient Logging => GetClient(EsClientTypeEnum.Logging);
+
+ ///
+ /// 业务数据同步客户端
+ ///
+ public ElasticsearchClient Business => GetClient(EsClientTypeEnum.Business);
+
+ ///
+ /// 根据类型获取客户端(内部校验,避免未注册的类型)
+ ///
+ private ElasticsearchClient GetClient(EsClientTypeEnum type)
+ {
+ if (_clients.TryGetValue(type, out var client))
+ {
+ return client;
+ }
+ throw new KeyNotFoundException($"未注册的ES客户端类型:{type},请检查注册配置");
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/ElasticSearch/ElasticSearchClientFactory.cs b/Admin.NET.Core/ElasticSearch/ElasticSearchClientFactory.cs
new file mode 100644
index 0000000..95592b4
--- /dev/null
+++ b/Admin.NET.Core/ElasticSearch/ElasticSearchClientFactory.cs
@@ -0,0 +1,85 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using Elastic.Clients.Elasticsearch;
+using Elastic.Transport;
+
+namespace Admin.NET.Core;
+
+public class ElasticSearchClientFactory
+{
+ ///
+ /// 创建 ES 客户端(通用方法)
+ ///
+ /// 配置类型(支持通用或场景专用)
+ /// 配置文件路径(如 "ElasticSearch:Logging")
+ /// ES 客户端实例(或 null if 未启用)
+ public static ElasticsearchClient? CreateClient(string configPath) where TOptions : ElasticSearchOptions, new()
+ {
+ // 从配置文件读取当前场景的配置
+ var options = App.GetConfig(configPath);
+ if (options == null)
+ throw Oops.Oh($"未找到{configPath}配置项");
+
+ if (!options.Enabled)
+ return null;
+
+ // 验证服务地址
+ if (options.ServerUris == null || !options.ServerUris.Any())
+ throw new ArgumentException($"ES 配置 {configPath} 未设置 ServerUris");
+
+ // 构建连接池(支持集群)
+ var uris = options.ServerUris.Select(uri => new Uri(uri)).ToList();
+ var connectionPool = new StaticNodePool(uris);
+ var connectionSettings = new ElasticsearchClientSettings(connectionPool)
+ .DefaultIndex(options.DefaultIndex) // 设置默认索引
+ .DisableDirectStreaming() // 开启请求/响应日志,方便排查问题
+ .OnRequestCompleted(response =>
+ {
+ if (response.HttpStatusCode == 401)
+ {
+ Console.WriteLine("ES 请求被拒绝:未提供有效认证信息");
+ }
+ });
+
+ // 配置认证
+ ConfigureAuthentication(connectionSettings, options);
+
+ // 配置 HTTPS 证书指纹
+ if (!string.IsNullOrEmpty(options.Fingerprint))
+ connectionSettings.CertificateFingerprint(options.Fingerprint);
+
+ return new ElasticsearchClient(connectionSettings);
+ }
+
+ ///
+ /// 配置认证(通用逻辑)
+ ///
+ private static void ConfigureAuthentication(ElasticsearchClientSettings settings, ElasticSearchOptions options)
+ {
+ switch (options.AuthType)
+ {
+ case ElasticSearchAuthTypeEnum.Basic:
+ settings.Authentication(new BasicAuthentication(options.User, options.Password));
+ break;
+
+ case ElasticSearchAuthTypeEnum.ApiKey:
+ settings.Authentication(new ApiKey(options.ApiKey));
+ break;
+
+ case ElasticSearchAuthTypeEnum.Base64ApiKey:
+ settings.Authentication(new Base64ApiKey(options.Base64ApiKey));
+ break;
+
+ case ElasticSearchAuthTypeEnum.None:
+ // 无需认证
+ break;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(options.AuthType));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/ElasticSearch/ElasticSearchSetup.cs b/Admin.NET.Core/ElasticSearch/ElasticSearchSetup.cs
new file mode 100644
index 0000000..8990d11
--- /dev/null
+++ b/Admin.NET.Core/ElasticSearch/ElasticSearchSetup.cs
@@ -0,0 +1,41 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using Elastic.Clients.Elasticsearch;
+
+namespace Admin.NET.Core.ElasticSearch;
+
+///
+/// ES服务注册
+///
+public static class ElasticSearchSetup
+{
+ ///
+ /// 注册所有ES客户端(日志+业务)
+ ///
+ public static void AddElasticSearchClients(this IServiceCollection services)
+ {
+ // 1. 创建客户端字典(枚举→客户端实例)
+ var clients = new Dictionary();
+
+ // 2. 注册日志客户端
+ var loggingClient = ElasticSearchClientFactory.CreateClient(configPath: "ElasticSearch:Logging");
+ if (loggingClient != null)
+ {
+ clients[EsClientTypeEnum.Logging] = loggingClient;
+ }
+
+ // 3. 注册业务客户端
+ var businessClient = ElasticSearchClientFactory.CreateClient(configPath: "ElasticSearch:Business");
+ if (businessClient != null)
+ {
+ clients[EsClientTypeEnum.Business] = businessClient;
+ }
+
+ // 4. 将客户端容器注册为单例(全局唯一)
+ services.AddSingleton(new ElasticSearchClientContainer(clients));
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/EntityBase.cs b/Admin.NET.Core/Entity/EntityBase.cs
new file mode 100644
index 0000000..c334a2e
--- /dev/null
+++ b/Admin.NET.Core/Entity/EntityBase.cs
@@ -0,0 +1,203 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 框架实体基类Id
+///
+public abstract class EntityBaseId
+{
+ ///
+ /// 雪花Id
+ ///
+ [SugarColumn(ColumnName = "Id", ColumnDescription = "主键Id", IsPrimaryKey = true, IsIdentity = false)]
+ public virtual long Id { get; set; }
+}
+
+///
+/// 框架实体基类
+///
+[SugarIndex("index_{table}_CT", nameof(CreateTime), OrderByType.Asc)]
+public abstract class EntityBase : EntityBaseId
+{
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnDescription = "创建时间", IsNullable = true, IsOnlyIgnoreUpdate = true)]
+ public virtual DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnDescription = "更新时间")]
+ public virtual DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 创建者Id
+ ///
+ [OwnerUser]
+ [SugarColumn(ColumnDescription = "创建者Id", IsOnlyIgnoreUpdate = true)]
+ public virtual long? CreateUserId { get; set; }
+
+ /////
+ ///// 创建者
+ /////
+ //[Newtonsoft.Json.JsonIgnore]
+ //[System.Text.Json.Serialization.JsonIgnore]
+ //[Navigate(NavigateType.OneToOne, nameof(CreateUserId))]
+ //public virtual SysUser CreateUser { get; set; }
+
+ ///
+ /// 创建者姓名
+ ///
+ [SugarColumn(ColumnDescription = "创建者姓名", Length = 64, IsOnlyIgnoreUpdate = true)]
+ public virtual string? CreateUserName { get; set; }
+
+ ///
+ /// 修改者Id
+ ///
+ [SugarColumn(ColumnDescription = "修改者Id")]
+ public virtual long? UpdateUserId { get; set; }
+
+ /////
+ ///// 修改者
+ /////
+ //[Newtonsoft.Json.JsonIgnore]
+ //[System.Text.Json.Serialization.JsonIgnore]
+ //[Navigate(NavigateType.OneToOne, nameof(UpdateUserId))]
+ //public virtual SysUser UpdateUser { get; set; }
+
+ ///
+ /// 修改者姓名
+ ///
+ [SugarColumn(ColumnDescription = "修改者姓名", Length = 64)]
+ public virtual string? UpdateUserName { get; set; }
+}
+
+///
+/// 框架实体基类(删除标志)
+///
+[SugarIndex("index_{table}_D", nameof(IsDelete), OrderByType.Asc)]
+[SugarIndex("index_{table}_DT", nameof(DeleteTime), OrderByType.Asc)]
+public abstract class EntityBaseDel : EntityBase, IDeletedFilter
+{
+ ///
+ /// 软删除
+ ///
+ [SugarColumn(ColumnDescription = "软删除")]
+ public virtual bool IsDelete { get; set; } = false;
+
+ ///
+ /// 软删除时间
+ ///
+ [SugarColumn(ColumnDescription = "软删除时间")]
+ public virtual DateTime? DeleteTime { get; set; }
+}
+
+///
+/// 机构实体基类(数据权限)
+///
+public abstract class EntityBaseOrg : EntityBase, IOrgIdFilter
+{
+ ///
+ /// 机构Id
+ ///
+ [SugarColumn(ColumnDescription = "机构Id", IsNullable = true)]
+ public virtual long OrgId { get; set; }
+
+ /////
+ ///// 创建者部门Id
+ /////
+ //[SugarColumn(ColumnDescription = "创建者部门Id", IsOnlyIgnoreUpdate = true)]
+ //public virtual long? CreateOrgId { get; set; }
+
+ /////
+ ///// 创建者部门
+ /////
+ //[Newtonsoft.Json.JsonIgnore]
+ //[System.Text.Json.Serialization.JsonIgnore]
+ //[Navigate(NavigateType.OneToOne, nameof(CreateOrgId))]
+ //public virtual SysOrg CreateOrg { get; set; }
+
+ /////
+ ///// 创建者部门名称
+ /////
+ //[SugarColumn(ColumnDescription = "创建者部门名称", Length = 64, IsOnlyIgnoreUpdate = true)]
+ //public virtual string? CreateOrgName { get; set; }
+}
+
+///
+/// 机构实体基类(数据权限、删除标志)
+///
+public abstract class EntityBaseOrgDel : EntityBaseDel, IOrgIdFilter
+{
+ ///
+ /// 机构Id
+ ///
+ [SugarColumn(ColumnDescription = "机构Id", IsNullable = true)]
+ public virtual long OrgId { get; set; }
+}
+
+///
+/// 租户实体基类
+///
+public abstract class EntityBaseTenant : EntityBase, ITenantIdFilter
+{
+ ///
+ /// 租户Id
+ ///
+ [SugarColumn(ColumnDescription = "租户Id", IsOnlyIgnoreUpdate = true)]
+ public virtual long? TenantId { get; set; }
+}
+
+///
+/// 租户实体基类(删除标志)
+///
+public abstract class EntityBaseTenantDel : EntityBaseDel, ITenantIdFilter
+{
+ ///
+ /// 租户Id
+ ///
+ [SugarColumn(ColumnDescription = "租户Id", IsOnlyIgnoreUpdate = true)]
+ public virtual long? TenantId { get; set; }
+}
+
+///
+/// 租户实体基类Id
+///
+public abstract class EntityBaseTenantId : EntityBaseId, ITenantIdFilter
+{
+ ///
+ /// 租户Id
+ ///
+ [SugarColumn(ColumnDescription = "租户Id", IsOnlyIgnoreUpdate = true)]
+ public virtual long? TenantId { get; set; }
+}
+
+///
+/// 租户机构实体基类(数据权限)
+///
+public abstract class EntityBaseTenantOrg : EntityBaseOrg, ITenantIdFilter
+{
+ ///
+ /// 租户Id
+ ///
+ [SugarColumn(ColumnDescription = "租户Id", IsOnlyIgnoreUpdate = true)]
+ public virtual long? TenantId { get; set; }
+}
+
+///
+/// 租户机构实体基类(数据权限、删除标志)
+///
+public abstract class EntityBaseTenantOrgDel : EntityBaseOrgDel, ITenantIdFilter
+{
+ ///
+ /// 租户Id
+ ///
+ [SugarColumn(ColumnDescription = "租户Id", IsOnlyIgnoreUpdate = true)]
+ public virtual long? TenantId { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/IEntityFilter.cs b/Admin.NET.Core/Entity/IEntityFilter.cs
new file mode 100644
index 0000000..ec4f57b
--- /dev/null
+++ b/Admin.NET.Core/Entity/IEntityFilter.cs
@@ -0,0 +1,40 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 假删除接口过滤器
+///
+public interface IDeletedFilter
+{
+ ///
+ /// 软删除
+ ///
+ bool IsDelete { get; set; }
+}
+
+///
+/// 租户Id接口过滤器
+///
+public interface ITenantIdFilter
+{
+ ///
+ /// 租户Id
+ ///
+ long? TenantId { get; set; }
+}
+
+///
+/// 机构Id接口过滤器
+///
+public interface IOrgIdFilter
+{
+ ///
+ /// 机构Id
+ ///
+ long OrgId { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysAlipayAuthInfo.cs b/Admin.NET.Core/Entity/SysAlipayAuthInfo.cs
new file mode 100644
index 0000000..8842546
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysAlipayAuthInfo.cs
@@ -0,0 +1,149 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 支付宝授权记录表
+///
+[SugarTable(null, "支付宝授权记录表")]
+[SysTable]
+[SugarIndex("index_{table}_U", nameof(UserId), OrderByType.Asc)]
+[SugarIndex("index_{table}_T", nameof(OpenId), OrderByType.Asc)]
+public class SysAlipayAuthInfo : EntityBase
+{
+ ///
+ /// 商户AppId
+ ///
+ [SugarColumn(ColumnDescription = "商户AppId", Length = 64)]
+ public string? AppId { get; set; }
+
+ ///
+ /// 开放ID
+ ///
+ [SugarColumn(ColumnDescription = "开放ID", Length = 64)]
+ public string? OpenId { get; set; }
+
+ ///
+ /// 用户ID
+ ///
+ [SugarColumn(ColumnDescription = "用户ID", Length = 64)]
+ public string? UserId { get; set; }
+
+ ///
+ /// 性别
+ ///
+ [SugarColumn(ColumnDescription = "性别", Length = 8)]
+ public GenderEnum Gender { get; set; }
+
+ ///
+ /// 年龄
+ ///
+ [SugarColumn(ColumnDescription = "年龄", Length = 16)]
+ public int Age { get; set; }
+
+ ///
+ /// 手机号
+ ///
+ [SugarColumn(ColumnDescription = "手机号", Length = 32)]
+ public string Mobile { get; set; }
+
+ ///
+ /// 显示名称
+ ///
+ [SugarColumn(ColumnDescription = "显示名称", Length = 128)]
+ public string DisplayName { get; set; }
+
+ ///
+ /// 昵称
+ ///
+ [SugarColumn(ColumnDescription = "昵称", Length = 64)]
+ public string NickName { get; set; }
+
+ ///
+ /// 用户名
+ ///
+ [SugarColumn(ColumnDescription = "用户名", Length = 64)]
+ public string UserName { get; set; }
+
+ ///
+ /// 头像
+ ///
+ [SugarColumn(ColumnDescription = "头像", Length = 512)]
+ public string? Avatar { get; set; }
+
+ ///
+ /// 邮箱
+ ///
+ [SugarColumn(ColumnDescription = "邮箱", Length = 128)]
+ public string? Email { get; set; }
+
+ ///
+ /// 用户民族
+ ///
+ [SugarColumn(ColumnDescription = "用户民族", Length = 32)]
+ public string? UserNation { get; set; }
+
+ ///
+ /// 淘宝ID
+ ///
+ [SugarColumn(ColumnDescription = "淘宝ID", Length = 64)]
+ public string? TaobaoId { get; set; }
+
+ ///
+ /// 电话
+ ///
+ [SugarColumn(ColumnDescription = "电话", Length = 32)]
+ public string? Phone { get; set; }
+
+ ///
+ /// 生日
+ ///
+ [SugarColumn(ColumnDescription = "生日", Length = 32)]
+ public string? PersonBirthday { get; set; }
+
+ ///
+ /// 职业
+ ///
+ [SugarColumn(ColumnDescription = "职业", Length = 64)]
+ public string? Profession { get; set; }
+
+ ///
+ /// 省份
+ ///
+ [SugarColumn(ColumnDescription = "省份", Length = 64)]
+ public string? Province { get; set; }
+
+ ///
+ /// 用户状态
+ ///
+ [SugarColumn(ColumnDescription = "用户状态", Length = 32)]
+ public string? UserStatus { get; set; }
+
+ ///
+ /// 学历
+ ///
+ [SugarColumn(ColumnDescription = "学历", Length = 32)]
+ public string? Degree { get; set; }
+
+ ///
+ /// 用户类型
+ ///
+ [SugarColumn(ColumnDescription = "用户类型", Length = 32)]
+ public string? UserType { get; set; }
+
+ ///
+ /// 邮编
+ ///
+ [SugarColumn(ColumnDescription = "邮编", Length = 16)]
+ public string? Zip { get; set; }
+
+ ///
+ /// 地址
+ ///
+ [SugarColumn(ColumnDescription = "地址", Length = 256)]
+ public string? Address { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysAlipayTransaction.cs b/Admin.NET.Core/Entity/SysAlipayTransaction.cs
new file mode 100644
index 0000000..5913471
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysAlipayTransaction.cs
@@ -0,0 +1,108 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 支付宝交易记录表
+///
+[SugarTable(null, "支付宝交易记录表")]
+[SysTable]
+[SugarIndex("index_{table}_U", nameof(UserId), OrderByType.Asc)]
+[SugarIndex("index_{table}_T", nameof(TradeNo), OrderByType.Asc)]
+[SugarIndex("index_{table}_O", nameof(OutTradeNo), OrderByType.Asc)]
+public class SysAlipayTransaction : EntityBase
+{
+ ///
+ /// 用户Id
+ ///
+ [SugarColumn(ColumnDescription = "用户Id", Length = 64)]
+ public long UserId { get; set; }
+
+ ///
+ /// 交易号
+ ///
+ [SugarColumn(ColumnDescription = "交易号", Length = 64)]
+ public string? TradeNo { get; set; }
+
+ ///
+ /// 商户订单号
+ ///
+ [SugarColumn(ColumnDescription = "商户订单号", Length = 64)]
+ public string OutTradeNo { get; set; }
+
+ ///
+ /// 交易金额
+ ///
+ [SugarColumn(ColumnDescription = "交易金额", Length = 20)]
+ public decimal TotalAmount { get; set; }
+
+ ///
+ /// 交易状态
+ ///
+ [SugarColumn(ColumnDescription = "交易状态", Length = 32)]
+ public string TradeStatus { get; set; }
+
+ ///
+ /// 交易完成时间
+ ///
+ [SugarColumn(ColumnDescription = "交易完成时间")]
+ public DateTime? FinishTime { get; set; }
+
+ ///
+ /// 交易标题
+ ///
+ [SugarColumn(ColumnDescription = "交易标题", Length = 256)]
+ public string Subject { get; set; }
+
+ ///
+ /// 交易描述
+ ///
+ [SugarColumn(ColumnDescription = "交易描述", Length = 512)]
+ public string? Body { get; set; }
+
+ ///
+ /// 买家支付宝账号
+ ///
+ [SugarColumn(ColumnDescription = "买家支付宝账号", Length = 128)]
+ public string? BuyerLogonId { get; set; }
+
+ ///
+ /// 买家支付宝用户ID
+ ///
+ [SugarColumn(ColumnDescription = "买家支付宝用户ID", Length = 32)]
+ public string? BuyerUserId { get; set; }
+
+ ///
+ /// 卖家支付宝用户ID
+ ///
+ [SugarColumn(ColumnDescription = "卖家支付宝用户ID", Length = 32)]
+ public string? SellerUserId { get; set; }
+
+ ///
+ /// 商户AppId
+ ///
+ [SugarColumn(ColumnDescription = "商户AppId", Length = 64)]
+ public string? AppId { get; set; }
+
+ ///
+ /// 交易扩展信息
+ ///
+ [SugarColumn(ColumnDescription = "交易扩展信息", Length = 1024)]
+ public string? ExtendInfo { get; set; }
+
+ ///
+ /// 交易异常信息
+ ///
+ [SugarColumn(ColumnDescription = "交易扩展信息", Length = 1024)]
+ public string? ErrorInfo { get; set; }
+
+ ///
+ /// 交易备注
+ ///
+ [SugarColumn(ColumnDescription = "交易备注", Length = 512)]
+ public string? Remark { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysCodeGen.cs b/Admin.NET.Core/Entity/SysCodeGen.cs
new file mode 100644
index 0000000..c6d80a0
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysCodeGen.cs
@@ -0,0 +1,159 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 代码生成表
+///
+[SugarTable(null, "代码生成表")]
+[SysTable]
+[SugarIndex("index_{table}_B", nameof(BusName), OrderByType.Asc)]
+[SugarIndex("index_{table}_T", nameof(TableName), OrderByType.Asc)]
+public partial class SysCodeGen : EntityBase
+{
+ ///
+ /// 作者姓名
+ ///
+ [SugarColumn(ColumnDescription = "作者姓名", Length = 32)]
+ [MaxLength(32)]
+ public string? AuthorName { get; set; }
+
+ ///
+ /// 是否移除表前缀
+ ///
+ [SugarColumn(ColumnDescription = "是否移除表前缀", Length = 8)]
+ [MaxLength(8)]
+ public string? TablePrefix { get; set; }
+
+ ///
+ /// 生成方式
+ ///
+ [SugarColumn(ColumnDescription = "生成方式", Length = 32)]
+ [MaxLength(32)]
+ public string? GenerateType { get; set; }
+
+ ///
+ /// 库定位器名
+ ///
+ [SugarColumn(ColumnDescription = "库定位器名", Length = 64)]
+ [MaxLength(64)]
+ public string? ConfigId { get; set; }
+
+ ///
+ /// 库名
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public string DbNickName
+ {
+ get
+ {
+ try
+ {
+ var dbOptions = App.GetConfig("DbConnection", true);
+ var config = dbOptions.ConnectionConfigs.FirstOrDefault(m => m.ConfigId.ToString() == ConfigId);
+ return config.DbNickName;
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+ }
+ }
+
+ ///
+ /// 数据库名(保留字段)
+ ///
+ [SugarColumn(ColumnDescription = "数据库库名", Length = 64)]
+ [MaxLength(64)]
+ public string? DbName { get; set; }
+
+ ///
+ /// 数据库类型
+ ///
+ [SugarColumn(ColumnDescription = "数据库类型", Length = 64)]
+ [MaxLength(64)]
+ public string? DbType { get; set; }
+
+ ///
+ /// 数据库链接
+ ///
+ [SugarColumn(ColumnDescription = "数据库链接", Length = 256)]
+ [MaxLength(256)]
+ public string? ConnectionString { get; set; }
+
+ ///
+ /// 数据库表名
+ ///
+ [SugarColumn(ColumnDescription = "数据库表名", Length = 128)]
+ [MaxLength(128)]
+ public string? TableName { get; set; }
+
+ ///
+ /// 命名空间
+ ///
+ [SugarColumn(ColumnDescription = "命名空间", Length = 128)]
+ [MaxLength(128)]
+ public string? NameSpace { get; set; }
+
+ ///
+ /// 业务名
+ ///
+ [SugarColumn(ColumnDescription = "业务名", Length = 128)]
+ [MaxLength(128)]
+ public string? BusName { get; set; }
+
+ ///
+ /// 表唯一字段配置
+ ///
+ [SugarColumn(ColumnDescription = "表唯一字段配置", Length = 512)]
+ [MaxLength(128)]
+ public string? TableUniqueConfig { get; set; }
+
+ ///
+ /// 是否生成菜单
+ ///
+ [SugarColumn(ColumnDescription = "是否生成菜单")]
+ public bool GenerateMenu { get; set; } = true;
+
+ ///
+ /// 菜单图标
+ ///
+ [SugarColumn(ColumnDescription = "菜单图标", Length = 32)]
+ public string? MenuIcon { get; set; } = "ele-Menu";
+
+ ///
+ /// 菜单编码
+ ///
+ [SugarColumn(ColumnDescription = "菜单编码")]
+ public long? MenuPid { get; set; }
+
+ ///
+ /// 页面目录
+ ///
+ [SugarColumn(ColumnDescription = "页面目录", Length = 32)]
+ public string? PagePath { get; set; }
+
+ ///
+ /// 支持打印类型
+ ///
+ [SugarColumn(ColumnDescription = "支持打印类型", Length = 32)]
+ [MaxLength(32)]
+ public string? PrintType { get; set; }
+
+ ///
+ /// 打印模版名称
+ ///
+ [SugarColumn(ColumnDescription = "打印模版名称", Length = 32)]
+ [MaxLength(32)]
+ public string? PrintName { get; set; }
+
+ ///
+ /// 表唯一字段列表
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public virtual List TableUniqueList => string.IsNullOrWhiteSpace(TableUniqueConfig) ? null : JSON.Deserialize>(TableUniqueConfig);
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysCodeGenConfig.cs b/Admin.NET.Core/Entity/SysCodeGenConfig.cs
new file mode 100644
index 0000000..ff7697e
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysCodeGenConfig.cs
@@ -0,0 +1,207 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 代码生成字段配置表
+///
+[SugarTable(null, "代码生成字段配置表")]
+[SysTable]
+public partial class SysCodeGenConfig : EntityBase
+{
+ ///
+ /// 代码生成主表Id
+ ///
+ [SugarColumn(ColumnDescription = "主表Id")]
+ public long CodeGenId { get; set; }
+
+ ///
+ /// 数据库字段名
+ ///
+ [SugarColumn(ColumnDescription = "字段名称", Length = 128)]
+ [Required, MaxLength(128)]
+ public virtual string ColumnName { get; set; }
+
+ ///
+ /// 主键
+ ///
+ [SugarColumn(ColumnDescription = "主键", Length = 8)]
+ [MaxLength(8)]
+ public string? ColumnKey { get; set; }
+
+ ///
+ /// 实体属性名
+ ///
+ [SugarColumn(ColumnDescription = "属性名称", Length = 128)]
+ [Required, MaxLength(128)]
+ public virtual string PropertyName { get; set; }
+
+ ///
+ /// 字段数据长度
+ ///
+ [SugarColumn(ColumnDescription = "字段数据长度", DefaultValue = "0")]
+ public int ColumnLength { get; set; }
+
+ ///
+ /// 字段描述
+ ///
+ [SugarColumn(ColumnDescription = "字段描述", Length = 128)]
+ [MaxLength(128)]
+ public string? ColumnComment { get; set; }
+
+ ///
+ /// 数据库中类型(物理类型)
+ ///
+ [SugarColumn(ColumnDescription = "数据库中类型", Length = 64)]
+ [MaxLength(64)]
+ public string? DataType { get; set; }
+
+ ///
+ /// .NET数据类型
+ ///
+ [SugarColumn(ColumnDescription = "NET数据类型", Length = 64)]
+ [MaxLength(64)]
+ public string? NetType { get; set; }
+
+ ///
+ /// 字段数据默认值
+ ///
+ [SugarColumn(ColumnDescription = "默认值")]
+ public string? DefaultValue { get; set; }
+
+ ///
+ /// 作用类型(字典)
+ ///
+ [SugarColumn(ColumnDescription = "作用类型", Length = 64)]
+ [MaxLength(64)]
+ public string? EffectType { get; set; }
+
+ ///
+ /// 外键库标识
+ ///
+ [SugarColumn(ColumnDescription = "外键库标识", Length = 20)]
+ [MaxLength(20)]
+ public string? FkConfigId { get; set; }
+
+ ///
+ /// 外键实体名称
+ ///
+ [SugarColumn(ColumnDescription = "外键实体名称", Length = 64)]
+ [MaxLength(64)]
+ public string? FkEntityName { get; set; }
+
+ ///
+ /// 外键表名称
+ ///
+ [SugarColumn(ColumnDescription = "外键表名称", Length = 128)]
+ [MaxLength(128)]
+ public string? FkTableName { get; set; }
+
+ ///
+ /// 外键显示字段
+ ///
+ [SugarColumn(ColumnDescription = "外键显示字段", Length = 64)]
+ [MaxLength(64)]
+ public string? FkDisplayColumns { get; set; }
+
+ ///
+ /// 外键链接字段
+ ///
+ [SugarColumn(ColumnDescription = "外键链接字段", Length = 64)]
+ [MaxLength(64)]
+ public string? FkLinkColumnName { get; set; }
+
+ ///
+ /// 外键显示字段.NET类型
+ ///
+ [SugarColumn(ColumnDescription = "外键显示字段.NET类型", Length = 64)]
+ [MaxLength(64)]
+ public string? FkColumnNetType { get; set; }
+
+ ///
+ /// 父级字段
+ ///
+ [SugarColumn(ColumnDescription = "父级字段", Length = 128)]
+ [MaxLength(128)]
+ public string? PidColumn { get; set; }
+
+ ///
+ /// 字典编码
+ ///
+ [SugarColumn(ColumnDescription = "字典编码", Length = 64)]
+ [MaxLength(64)]
+ public string? DictTypeCode { get; set; }
+
+ ///
+ /// 查询方式
+ ///
+ [SugarColumn(ColumnDescription = "查询方式", Length = 16)]
+ [MaxLength(16)]
+ public string? QueryType { get; set; }
+
+ ///
+ /// 是否是查询条件
+ ///
+ [SugarColumn(ColumnDescription = "是否是查询条件", Length = 8)]
+ [MaxLength(8)]
+ public string? WhetherQuery { get; set; }
+
+ ///
+ /// 列表是否缩进(字典)
+ ///
+ [SugarColumn(ColumnDescription = "列表是否缩进", Length = 8)]
+ [MaxLength(8)]
+ public string? WhetherRetract { get; set; }
+
+ ///
+ /// 是否必填(字典)
+ ///
+ [SugarColumn(ColumnDescription = "是否必填", Length = 8)]
+ [MaxLength(8)]
+ public string? WhetherRequired { get; set; }
+
+ ///
+ /// 是否可排序(字典)
+ ///
+ [SugarColumn(ColumnDescription = "是否可排序", Length = 8)]
+ [MaxLength(8)]
+ public string? WhetherSortable { get; set; }
+
+ ///
+ /// 列表显示
+ ///
+ [SugarColumn(ColumnDescription = "列表显示", Length = 8)]
+ [MaxLength(8)]
+ public string? WhetherTable { get; set; }
+
+ ///
+ /// 增改
+ ///
+ [SugarColumn(ColumnDescription = "增改", Length = 8)]
+ [MaxLength(8)]
+ public string? WhetherAddUpdate { get; set; }
+
+ ///
+ /// 导入
+ ///
+ [SugarColumn(ColumnDescription = "导入", Length = 8)]
+ [MaxLength(8)]
+ public string? WhetherImport { get; set; }
+
+ ///
+ /// 是否通用字段
+ ///
+ [SugarColumn(ColumnDescription = "是否通用字段", Length = 8)]
+ [MaxLength(8)]
+ public string? WhetherCommon { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int OrderNo { get; set; } = 100;
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysConfig.cs b/Admin.NET.Core/Entity/SysConfig.cs
new file mode 100644
index 0000000..d5afeae
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysConfig.cs
@@ -0,0 +1,65 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统配置参数表
+///
+[SugarTable(null, "系统配置参数表")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
+[SugarIndex("index_{table}_C", nameof(Code), OrderByType.Asc, IsUnique = true)]
+public partial class SysConfig : EntityBase
+{
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string Name { get; set; }
+
+ ///
+ /// 编码
+ ///
+ [SugarColumn(ColumnDescription = "编码", Length = 64)]
+ [MaxLength(64)]
+ public string? Code { get; set; }
+
+ ///
+ /// 参数值
+ ///
+ [SugarColumn(ColumnDescription = "参数值", Length = 512)]
+ [MaxLength(512)]
+ [IgnoreUpdateSeedColumn]
+ public string? Value { get; set; }
+
+ ///
+ /// 是否是内置参数(Y-是,N-否)
+ ///
+ [SugarColumn(ColumnDescription = "是否是内置参数", DefaultValue = "1")]
+ public YesNoEnum SysFlag { get; set; } = YesNoEnum.Y;
+
+ ///
+ /// 分组编码
+ ///
+ [SugarColumn(ColumnDescription = "分组编码", Length = 64)]
+ [MaxLength(64)]
+ public string? GroupCode { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序", DefaultValue = "100")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 256)]
+ [MaxLength(256)]
+ public string? Remark { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysDictData.cs b/Admin.NET.Core/Entity/SysDictData.cs
new file mode 100644
index 0000000..735af86
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysDictData.cs
@@ -0,0 +1,105 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统字典值表
+///
+[SugarTable(null, "系统字典值表")]
+[SysTable]
+[SugarIndex("index_{table}_TV", nameof(DictTypeId), OrderByType.Asc, nameof(Value), OrderByType.Asc, IsUnique = true)]
+public partial class SysDictData : EntityBase
+{
+ ///
+ /// 字典类型Id
+ ///
+ [SugarColumn(ColumnDescription = "字典类型Id")]
+ public long DictTypeId { get; set; }
+
+ ///
+ /// 字典类型
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(DictTypeId))]
+ public SysDictType DictType { get; set; }
+
+ ///
+ /// 显示文本
+ ///
+ [SugarColumn(ColumnDescription = "显示文本", Length = 256)]
+ [Required, MaxLength(256)]
+ public virtual string Label { get; set; }
+
+ ///
+ /// 值
+ ///
+ [SugarColumn(ColumnDescription = "值", Length = 256)]
+ [Required, MaxLength(256)]
+ public virtual string Value { get; set; }
+
+ ///
+ /// 编码
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnDescription = "编码", Length = 256)]
+ public virtual string? Code { get; set; }
+
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 256)]
+ [MaxLength(256)]
+ public virtual string? Name { get; set; }
+
+ ///
+ /// 显示样式-标签颜色
+ ///
+ [SugarColumn(ColumnDescription = "显示样式-标签颜色", Length = 16)]
+ [MaxLength(16)]
+ public string? TagType { get; set; }
+
+ ///
+ /// 显示样式-Style(控制显示样式)
+ ///
+ [SugarColumn(ColumnDescription = "显示样式-Style", Length = 512)]
+ [MaxLength(512)]
+ public string? StyleSetting { get; set; }
+
+ ///
+ /// 显示样式-Class(控制显示样式)
+ ///
+ [SugarColumn(ColumnDescription = "显示样式-Class", Length = 512)]
+ [MaxLength(512)]
+ public string? ClassSetting { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序", DefaultValue = "100")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 2048)]
+ [MaxLength(2048)]
+ public string? Remark { get; set; }
+
+ ///
+ /// 拓展数据(保存业务功能的配置项)
+ ///
+ [SugarColumn(ColumnDescription = "拓展数据(保存业务功能的配置项)", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? ExtData { get; set; }
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态", DefaultValue = "1")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysDictDataTenant.cs b/Admin.NET.Core/Entity/SysDictDataTenant.cs
new file mode 100644
index 0000000..d14eac7
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysDictDataTenant.cs
@@ -0,0 +1,22 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统租户字典值表
+///
+[SugarTable(null, "系统租户字典值表")]
+[SysTable]
+[SugarIndex("index_{table}_TV", nameof(DictTypeId), OrderByType.Asc, nameof(Value), OrderByType.Asc)]
+public partial class SysDictDataTenant : SysDictData, ITenantIdFilter
+{
+ ///
+ /// 租户Id
+ ///
+ [SugarColumn(ColumnDescription = "租户Id", IsOnlyIgnoreUpdate = true)]
+ public virtual long? TenantId { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysDictType.cs b/Admin.NET.Core/Entity/SysDictType.cs
new file mode 100644
index 0000000..b9d0f9f
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysDictType.cs
@@ -0,0 +1,68 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统字典类型表
+///
+[SugarTable(null, "系统字典类型表")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
+[SugarIndex("index_{table}_C", nameof(Code), OrderByType.Asc)]
+public partial class SysDictType : EntityBase
+{
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string Name { get; set; }
+
+ ///
+ /// 编码
+ ///
+ [SugarColumn(ColumnDescription = "编码", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string Code { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序", DefaultValue = "100")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 256)]
+ [MaxLength(256)]
+ public string? Remark { get; set; }
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态", DefaultValue = "1")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
+
+ ///
+ /// 是否是内置字典(Y-是,N-否)
+ ///
+ [SugarColumn(ColumnDescription = "是否是内置字典", DefaultValue = "1")]
+ public virtual YesNoEnum SysFlag { get; set; } = YesNoEnum.Y;
+
+ ///
+ /// 是否是租户字典(Y-是,N-否)
+ ///
+ [SugarColumn(ColumnDescription = "是否是租户字典", DefaultValue = "2")]
+ public virtual YesNoEnum IsTenant { get; set; } = YesNoEnum.N;
+
+ ///
+ /// 字典值集合
+ ///
+ [Navigate(NavigateType.OneToMany, nameof(SysDictData.DictTypeId))]
+ public List Children { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysFile.cs b/Admin.NET.Core/Entity/SysFile.cs
new file mode 100644
index 0000000..27149d5
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysFile.cs
@@ -0,0 +1,104 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统文件表
+///
+[SugarTable(null, "系统文件表")]
+[SysTable]
+[SugarIndex("index_{table}_F", nameof(FileName), OrderByType.Asc)]
+public partial class SysFile : EntityBaseTenantOrg
+{
+ ///
+ /// 提供者
+ ///
+ [SugarColumn(ColumnDescription = "提供者", Length = 128)]
+ [MaxLength(128)]
+ public string? Provider { get; set; }
+
+ ///
+ /// 仓储名称
+ ///
+ [SugarColumn(ColumnDescription = "仓储名称", Length = 128)]
+ [MaxLength(128)]
+ public string? BucketName { get; set; }
+
+ ///
+ /// 文件名称(源文件名)
+ ///
+ [SugarColumn(ColumnDescription = "文件名称", Length = 128)]
+ [MaxLength(128)]
+ public string? FileName { get; set; }
+
+ ///
+ /// 文件后缀
+ ///
+ [SugarColumn(ColumnDescription = "文件后缀", Length = 16)]
+ [MaxLength(16)]
+ public string? Suffix { get; set; }
+
+ ///
+ /// 存储路径
+ ///
+ [SugarColumn(ColumnDescription = "存储路径", Length = 512)]
+ [MaxLength(512)]
+ public string? FilePath { get; set; }
+
+ ///
+ /// 文件大小KB
+ ///
+ [SugarColumn(ColumnDescription = "文件大小KB")]
+ public long SizeKb { get; set; }
+
+ ///
+ /// 文件大小信息-计算后的
+ ///
+ [SugarColumn(ColumnDescription = "文件大小信息", Length = 64)]
+ [MaxLength(64)]
+ public string? SizeInfo { get; set; }
+
+ ///
+ /// 外链地址-OSS上传后生成外链地址方便前端预览
+ ///
+ [SugarColumn(ColumnDescription = "外链地址", Length = 512)]
+ [MaxLength(512)]
+ public string? Url { get; set; }
+
+ ///
+ /// 文件MD5
+ ///
+ [SugarColumn(ColumnDescription = "文件MD5", Length = 128)]
+ [MaxLength(128)]
+ public string? FileMd5 { get; set; }
+
+ ///
+ /// 文件类别
+ ///
+ [SugarColumn(ColumnDescription = "文件类别", Length = 128)]
+ [MaxLength(128)]
+ public virtual string? FileType { get; set; }
+
+ ///
+ /// 文件别名
+ ///
+ [SugarColumn(ColumnDescription = "文件别名", Length = 128)]
+ [MaxLength(128)]
+ public string? FileAlias { get; set; }
+
+ ///
+ /// 是否公开
+ ///
+ [SugarColumn(ColumnDescription = "是否公开")]
+ public virtual bool IsPublic { get; set; } = false;
+
+ ///
+ /// 业务数据Id
+ ///
+ [SugarColumn(ColumnDescription = "业务数据Id")]
+ public long? DataId { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysFileProvider.cs b/Admin.NET.Core/Entity/SysFileProvider.cs
new file mode 100644
index 0000000..6fd9b54
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysFileProvider.cs
@@ -0,0 +1,118 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using Newtonsoft.Json;
+
+namespace Admin.NET.Core;
+
+///
+/// 系统文件存储提供者表
+///
+[SugarTable(null, "系统文件存储提供者表")]
+[SysTable]
+[SugarIndex("index_{table}_BucketName", nameof(BucketName), OrderByType.Asc)]
+[SugarIndex("index_{table}_IsEnable", nameof(IsEnable), OrderByType.Desc)]
+[SugarIndex("index_{table}_IsDefault", nameof(IsDefault), OrderByType.Desc)]
+public partial class SysFileProvider : EntityBaseTenant
+{
+ ///
+ /// 存储提供者(Minio, QCloud,Aliyun 等等)
+ ///
+ [SugarColumn(ColumnDescription = "存储提供者", Length = 16)]
+ [Required, MaxLength(16)]
+ public virtual string Provider { get; set; }
+
+ ///
+ /// 存储桶名称
+ ///
+ [SugarColumn(ColumnDescription = "存储桶名称", Length = 32)]
+ [Required, MaxLength(32)]
+ public virtual string BucketName { get; set; }
+
+ ///
+ /// 访问密钥 (填入 阿里云(Aliyun)/Minio:的 AccessKey,腾讯云(QCloud): 的 SecretId)
+ ///
+ [SugarColumn(ColumnDescription = "访问密钥", Length = 128)]
+ [MaxLength(128)]
+ public virtual string? AccessKey { get; set; }
+
+ ///
+ /// 密钥
+ ///
+ [SugarColumn(ColumnDescription = "密钥", Length = 128)]
+ [MaxLength(128)]
+ public virtual string? SecretKey { get; set; }
+
+ ///
+ /// 地域
+ ///
+ [SugarColumn(ColumnDescription = "地域", Length = 64)]
+ [MaxLength(64)]
+ public virtual string? Region { get; set; }
+
+ ///
+ /// 端点地址(填入 阿里云(Aliyun)/Minio:的 endpoint/Api address,腾讯云(QCloud): 的 AppId)
+ ///
+ [SugarColumn(ColumnDescription = "端点地址", Length = 256)]
+ [MaxLength(256)]
+ public virtual string? Endpoint { get; set; }
+
+ ///
+ /// 是否启用HTTPS
+ ///
+ [SugarColumn(ColumnDescription = "是否启用HTTPS")]
+ public virtual bool? IsEnableHttps { get; set; } = true;
+
+ ///
+ /// 是否启用缓存
+ ///
+ [SugarColumn(ColumnDescription = "是否启用缓存")]
+ public virtual bool? IsEnableCache { get; set; } = true;
+
+ ///
+ /// 是否启用
+ ///
+ [SugarColumn(ColumnDescription = "是否启用")]
+ public virtual bool? IsEnable { get; set; } = true;
+
+ ///
+ /// 是否默认提供者
+ ///
+ [SugarColumn(ColumnDescription = "是否默认提供者")]
+ public virtual bool? IsDefault { get; set; } = false;
+
+ ///
+ /// 自定义域名
+ ///
+ [SugarColumn(ColumnDescription = "自定义域名", Length = 256)]
+ [MaxLength(256)]
+ public virtual string? SinceDomain { get; set; }
+
+ ///
+ /// 排序号
+ ///
+ [SugarColumn(ColumnDescription = "排序号")]
+ public virtual int? OrderNo { get; set; } = 100;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 512)]
+ [MaxLength(512)]
+ public virtual string? Remark { get; set; }
+
+ ///
+ /// 获取显示名称
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public virtual string DisplayName => $"{Provider}-{BucketName}";
+
+ ///
+ /// 获取配置键名
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public virtual string ConfigKey => $"{Provider}_{BucketName}_{Id}";
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysJobCluster.cs b/Admin.NET.Core/Entity/SysJobCluster.cs
new file mode 100644
index 0000000..6687cf6
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysJobCluster.cs
@@ -0,0 +1,41 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统作业集群表
+///
+[SugarTable(null, "系统作业集群表")]
+[SysTable]
+public partial class SysJobCluster : EntityBaseId
+{
+ ///
+ /// 作业集群Id
+ ///
+ [SugarColumn(ColumnDescription = "作业集群Id", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string ClusterId { get; set; }
+
+ ///
+ /// 描述信息
+ ///
+ [SugarColumn(ColumnDescription = "描述信息", Length = 128)]
+ [MaxLength(128)]
+ public string? Description { get; set; }
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public ClusterStatus Status { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnDescription = "更新时间")]
+ public DateTime? UpdatedTime { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysJobDetail.cs b/Admin.NET.Core/Entity/SysJobDetail.cs
new file mode 100644
index 0000000..3c2868f
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysJobDetail.cs
@@ -0,0 +1,87 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统作业信息表
+///
+[SugarTable(null, "系统作业信息表")]
+[SysTable]
+[SugarIndex("index_{table}_J", nameof(JobId), OrderByType.Asc)]
+public partial class SysJobDetail : EntityBaseId
+{
+ ///
+ /// 作业Id
+ ///
+ [SugarColumn(ColumnDescription = "作业Id", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string JobId { get; set; }
+
+ ///
+ /// 组名称
+ ///
+ [SugarColumn(ColumnDescription = "组名称", Length = 128)]
+ [MaxLength(128)]
+ public string? GroupName { get; set; } = "default";
+
+ ///
+ /// 作业类型FullName
+ ///
+ [SugarColumn(ColumnDescription = "作业类型", Length = 128)]
+ [MaxLength(128)]
+ public string? JobType { get; set; }
+
+ ///
+ /// 程序集Name
+ ///
+ [SugarColumn(ColumnDescription = "程序集", Length = 128)]
+ [MaxLength(128)]
+ public string? AssemblyName { get; set; }
+
+ ///
+ /// 描述信息
+ ///
+ [SugarColumn(ColumnDescription = "描述信息", Length = 128)]
+ [MaxLength(128)]
+ public string? Description { get; set; }
+
+ ///
+ /// 是否并行执行
+ ///
+ [SugarColumn(ColumnDescription = "是否并行执行")]
+ public bool Concurrent { get; set; } = true;
+
+ ///
+ /// 是否扫描特性触发器
+ ///
+ [SugarColumn(ColumnDescription = "是否扫描特性触发器", ColumnName = "annotation")]
+ public bool IncludeAnnotation { get; set; } = false;
+
+ ///
+ /// 额外数据
+ ///
+ [SugarColumn(ColumnDescription = "额外数据", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? Properties { get; set; } = "{}";
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnDescription = "更新时间")]
+ public DateTime? UpdatedTime { get; set; }
+
+ ///
+ /// 作业创建类型
+ ///
+ [SugarColumn(ColumnDescription = "作业创建类型")]
+ public JobCreateTypeEnum CreateType { get; set; } = JobCreateTypeEnum.BuiltIn;
+
+ ///
+ /// 脚本代码
+ ///
+ [SugarColumn(ColumnDescription = "脚本代码", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? ScriptCode { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysJobTrigger.cs b/Admin.NET.Core/Entity/SysJobTrigger.cs
new file mode 100644
index 0000000..dc6d5c8
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysJobTrigger.cs
@@ -0,0 +1,147 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统作业触发器表
+///
+[SugarTable(null, "系统作业触发器表")]
+[SysTable]
+public partial class SysJobTrigger : EntityBaseId
+{
+ ///
+ /// 触发器Id
+ ///
+ [SugarColumn(ColumnDescription = "触发器Id", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string TriggerId { get; set; }
+
+ ///
+ /// 作业Id
+ ///
+ [SugarColumn(ColumnDescription = "作业Id", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string JobId { get; set; }
+
+ ///
+ /// 触发器类型FullName
+ ///
+ [SugarColumn(ColumnDescription = "触发器类型", Length = 128)]
+ [MaxLength(128)]
+ public string? TriggerType { get; set; }
+
+ ///
+ /// 程序集Name
+ ///
+ [SugarColumn(ColumnDescription = "程序集", Length = 128)]
+ [MaxLength(128)]
+ public string? AssemblyName { get; set; } = "Furion.Pure";
+
+ ///
+ /// 参数
+ ///
+ [SugarColumn(ColumnDescription = "参数", Length = 128)]
+ [MaxLength(128)]
+ public string? Args { get; set; }
+
+ ///
+ /// 描述信息
+ ///
+ [SugarColumn(ColumnDescription = "描述信息", Length = 128)]
+ [MaxLength(128)]
+ public string? Description { get; set; }
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public TriggerStatus Status { get; set; } = TriggerStatus.Ready;
+
+ ///
+ /// 起始时间
+ ///
+ [SugarColumn(ColumnDescription = "起始时间")]
+ public DateTime? StartTime { get; set; }
+
+ ///
+ /// 结束时间
+ ///
+ [SugarColumn(ColumnDescription = "结束时间")]
+ public DateTime? EndTime { get; set; }
+
+ ///
+ /// 最近运行时间
+ ///
+ [SugarColumn(ColumnDescription = "最近运行时间")]
+ public DateTime? LastRunTime { get; set; }
+
+ ///
+ /// 下一次运行时间
+ ///
+ [SugarColumn(ColumnDescription = "下一次运行时间")]
+ public DateTime? NextRunTime { get; set; }
+
+ ///
+ /// 触发次数
+ ///
+ [SugarColumn(ColumnDescription = "触发次数")]
+ public long NumberOfRuns { get; set; }
+
+ ///
+ /// 最大触发次数(0:不限制,n:N次)
+ ///
+ [SugarColumn(ColumnDescription = "最大触发次数")]
+ public long MaxNumberOfRuns { get; set; }
+
+ ///
+ /// 出错次数
+ ///
+ [SugarColumn(ColumnDescription = "出错次数")]
+ public long NumberOfErrors { get; set; }
+
+ ///
+ /// 最大出错次数(0:不限制,n:N次)
+ ///
+ [SugarColumn(ColumnDescription = "最大出错次数")]
+ public long MaxNumberOfErrors { get; set; }
+
+ ///
+ /// 重试次数
+ ///
+ [SugarColumn(ColumnDescription = "重试次数")]
+ public int NumRetries { get; set; }
+
+ ///
+ /// 重试间隔时间(ms)
+ ///
+ [SugarColumn(ColumnDescription = "重试间隔时间(ms)")]
+ public int RetryTimeout { get; set; } = 1000;
+
+ ///
+ /// 是否立即启动
+ ///
+ [SugarColumn(ColumnDescription = "是否立即启动")]
+ public bool StartNow { get; set; } = true;
+
+ ///
+ /// 是否启动时执行一次
+ ///
+ [SugarColumn(ColumnDescription = "是否启动时执行一次")]
+ public bool RunOnStart { get; set; } = false;
+
+ ///
+ /// 是否在启动时重置最大触发次数等于一次的作业
+ ///
+ [SugarColumn(ColumnDescription = "是否重置触发次数")]
+ public bool ResetOnlyOnce { get; set; } = true;
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnDescription = "更新时间")]
+ public DateTime? UpdatedTime { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysJobTriggerRecord.cs b/Admin.NET.Core/Entity/SysJobTriggerRecord.cs
new file mode 100644
index 0000000..080c5cc
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysJobTriggerRecord.cs
@@ -0,0 +1,72 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统作业触发器运行记录表
+///
+[SugarTable(null, "系统作业触发器运行记录表")]
+[SysTable]
+public partial class SysJobTriggerRecord : EntityBaseId
+{
+ ///
+ /// 作业Id
+ ///
+ [SugarColumn(ColumnDescription = "作业Id", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string JobId { get; set; }
+
+ ///
+ /// 触发器Id
+ ///
+ [SugarColumn(ColumnDescription = "触发器Id", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string TriggerId { get; set; }
+
+ ///
+ /// 当前运行次数
+ ///
+ [SugarColumn(ColumnDescription = "当前运行次数")]
+ public long NumberOfRuns { get; set; }
+
+ ///
+ /// 最近运行时间
+ ///
+ [SugarColumn(ColumnDescription = "最近运行时间")]
+ public DateTime? LastRunTime { get; set; }
+
+ ///
+ /// 下一次运行时间
+ ///
+ [SugarColumn(ColumnDescription = "下一次运行时间")]
+ public DateTime? NextRunTime { get; set; }
+
+ ///
+ /// 触发器状态
+ ///
+ [SugarColumn(ColumnDescription = "触发器状态")]
+ public TriggerStatus Status { get; set; } = TriggerStatus.Ready;
+
+ ///
+ /// 本次执行结果
+ ///
+ [SugarColumn(ColumnDescription = "本次执行结果", Length = 128)]
+ [MaxLength(128)]
+ public string? Result { get; set; }
+
+ ///
+ /// 本次执行耗时
+ ///
+ [SugarColumn(ColumnDescription = "本次执行耗时")]
+ public long ElapsedTime { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnDescription = "创建时间")]
+ public DateTime? CreatedTime { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysLang.cs b/Admin.NET.Core/Entity/SysLang.cs
new file mode 100644
index 0000000..8be0706
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysLang.cs
@@ -0,0 +1,86 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+[SugarTable(null, "语言配置")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
+[SugarIndex("index_{table}_C", nameof(Code), OrderByType.Asc)]
+public class SysLang : EntityBase
+{
+ ///
+ /// 语言名称
+ ///
+ [SugarColumn(ColumnDescription = "语言名称")]
+ public string Name { get; set; }
+
+ ///
+ /// 语言代码(如 zh-CN)
+ ///
+ [SugarColumn(ColumnDescription = "语言代码")]
+ public string Code { get; set; }
+
+ ///
+ /// ISO 语言代码
+ ///
+ [SugarColumn(ColumnDescription = "ISO 语言代码")]
+ public string IsoCode { get; set; }
+
+ ///
+ /// URL 语言代码
+ ///
+ [SugarColumn(ColumnDescription = "URL 语言代码")]
+ public string UrlCode { get; set; }
+
+ ///
+ /// 书写方向(1=从左到右,2=从右到左)
+ ///
+ [SugarColumn(ColumnDescription = "书写方向", DefaultValue = "1")]
+ public DirectionEnum Direction { get; set; } = DirectionEnum.Ltr;
+
+ ///
+ /// 日期格式(如 YYYY-MM-DD)
+ ///
+ [SugarColumn(ColumnDescription = "日期格式")]
+ public string DateFormat { get; set; }
+
+ ///
+ /// 时间格式(如 HH:MM:SS)
+ ///
+ [SugarColumn(ColumnDescription = "时间格式")]
+ public string TimeFormat { get; set; }
+
+ ///
+ /// 每周起始日(如 0=星期日,1=星期一)
+ ///
+ [SugarColumn(ColumnDescription = "每周起始日", DefaultValue = "7")]
+ public WeekEnum WeekStart { get; set; } = WeekEnum.Sunday;
+
+ ///
+ /// 分组符号(如 ,)
+ ///
+ [SugarColumn(ColumnDescription = "分组符号")]
+ public string Grouping { get; set; }
+
+ ///
+ /// 小数点符号
+ ///
+ [SugarColumn(ColumnDescription = "小数点符号")]
+ public string DecimalPoint { get; set; }
+
+ ///
+ /// 千分位分隔符
+ ///
+ [SugarColumn(ColumnDescription = "千分位分隔符")]
+ public string? ThousandsSep { get; set; }
+
+ ///
+ /// 是否启用
+ ///
+ [SugarColumn(ColumnDescription = "是否启用")]
+ public bool Active { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysLangText.cs b/Admin.NET.Core/Entity/SysLangText.cs
new file mode 100644
index 0000000..f1258cf
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysLangText.cs
@@ -0,0 +1,44 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+[SugarTable(null, "翻译表")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(EntityName), OrderByType.Asc)]
+[SugarIndex("index_{table}_F", nameof(FieldName), OrderByType.Asc)]
+public class SysLangText : EntityBase
+{
+ ///
+ /// 所属实体名
+ ///
+ [SugarColumn(ColumnDescription = "所属实体名")]
+ public string EntityName { get; set; }
+
+ ///
+ /// 所属实体ID
+ ///
+ [SugarColumn(ColumnDescription = "所属实体ID")]
+ public long EntityId { get; set; }
+
+ ///
+ /// 字段名
+ ///
+ [SugarColumn(ColumnDescription = "字段名")]
+ public string FieldName { get; set; }
+
+ ///
+ /// 语言代码
+ ///
+ [SugarColumn(ColumnDescription = "语言代码")]
+ public string LangCode { get; set; }
+
+ ///
+ /// 多语言内容
+ ///
+ [SugarColumn(ColumnDescription = "翻译内容")]
+ public string Content { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysLdap.cs b/Admin.NET.Core/Entity/SysLdap.cs
new file mode 100644
index 0000000..f27d1aa
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysLdap.cs
@@ -0,0 +1,89 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统域登录信息配置表
+///
+[SugarTable(null, "系统域登录信息配置表")]
+[SysTable]
+public class SysLdap : EntityBaseTenantDel
+{
+ ///
+ /// 主机
+ ///
+ [SugarColumn(ColumnDescription = "主机", Length = 128)]
+ [Required]
+ public virtual string Host { get; set; }
+
+ ///
+ /// 端口
+ ///
+ [SugarColumn(ColumnDescription = "端口")]
+ public virtual int Port { get; set; }
+
+ ///
+ /// 用户搜索基准
+ ///
+ [SugarColumn(ColumnDescription = "用户搜索基准", Length = 128)]
+ [Required]
+ public virtual string BaseDn { get; set; }
+
+ ///
+ /// 绑定DN(有管理权限制的用户)
+ ///
+ [SugarColumn(ColumnDescription = "绑定DN", Length = 128)]
+ [Required]
+ public virtual string BindDn { get; set; }
+
+ ///
+ /// 绑定密码(有管理权限制的用户密码)
+ ///
+ [SugarColumn(ColumnDescription = "绑定密码", Length = 512)]
+ [Required]
+ public virtual string BindPass { get; set; }
+
+ ///
+ /// 用户过滤规则
+ ///
+ [SugarColumn(ColumnDescription = "用户过滤规则", Length = 128)]
+ [Required]
+ public virtual string AuthFilter { get; set; } = "sAMAccountName=%s";
+
+ ///
+ /// Ldap版本
+ ///
+ [SugarColumn(ColumnDescription = "Ldap版本")]
+ public int Version { get; set; }
+
+ ///
+ /// 绑定域账号字段属性值
+ ///
+ [SugarColumn(ColumnDescription = "绑定域账号字段属性值", Length = 32)]
+ [Required]
+ public virtual string BindAttrAccount { get; set; } = "sAMAccountName";
+
+ ///
+ /// 绑定用户EmployeeId属性值
+ ///
+ [SugarColumn(ColumnDescription = "绑定用户EmployeeId属性值", Length = 32)]
+ [Required]
+ public virtual string BindAttrEmployeeId { get; set; } = "EmployeeId";
+
+ ///
+ /// 绑定Code属性值
+ ///
+ [SugarColumn(ColumnDescription = "绑定对象Code属性值", Length = 64)]
+ [Required]
+ public virtual string BindAttrCode { get; set; } = "objectGUID";
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysLogDiff.cs b/Admin.NET.Core/Entity/SysLogDiff.cs
new file mode 100644
index 0000000..96366b7
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysLogDiff.cs
@@ -0,0 +1,52 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统差异日志表
+///
+[SugarTable(null, "系统差异日志表")]
+[SysTable]
+[LogTable]
+public partial class SysLogDiff : EntityBaseTenant
+{
+ ///
+ /// 差异数据
+ ///
+ [SugarColumn(ColumnDescription = "差异数据", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? DiffData { get; set; }
+
+ ///
+ /// Sql
+ ///
+ [SugarColumn(ColumnDescription = "Sql", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? Sql { get; set; }
+
+ ///
+ /// 参数 手动传入的参数
+ ///
+ [SugarColumn(ColumnDescription = "参数", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? Parameters { get; set; }
+
+ ///
+ /// 业务对象
+ ///
+ [SugarColumn(ColumnDescription = "业务对象", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? BusinessData { get; set; }
+
+ ///
+ /// 差异操作
+ ///
+ [SugarColumn(ColumnDescription = "差异操作", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? DiffType { get; set; }
+
+ ///
+ /// 耗时
+ ///
+ [SugarColumn(ColumnDescription = "耗时")]
+ public long? Elapsed { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysLogEx.cs b/Admin.NET.Core/Entity/SysLogEx.cs
new file mode 100644
index 0000000..e650144
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysLogEx.cs
@@ -0,0 +1,72 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统异常日志表
+///
+[SugarTable(null, "系统异常日志表")]
+[SysTable]
+[LogTable]
+public partial class SysLogEx : SysLogVis
+{
+ ///
+ /// 请求方式
+ ///
+ [SugarColumn(ColumnDescription = "请求方式", Length = 32)]
+ [MaxLength(32)]
+ public string? HttpMethod { get; set; }
+
+ ///
+ /// 请求地址
+ ///
+ [SugarColumn(ColumnDescription = "请求地址", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? RequestUrl { get; set; }
+
+ ///
+ /// 请求参数
+ ///
+ [SugarColumn(ColumnDescription = "请求参数", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? RequestParam { get; set; }
+
+ ///
+ /// 返回结果
+ ///
+ [SugarColumn(ColumnDescription = "返回结果", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? ReturnResult { get; set; }
+
+ ///
+ /// 事件Id
+ ///
+ [SugarColumn(ColumnDescription = "事件Id")]
+ public int? EventId { get; set; }
+
+ ///
+ /// 线程Id
+ ///
+ [SugarColumn(ColumnDescription = "线程Id")]
+ public int? ThreadId { get; set; }
+
+ ///
+ /// 请求跟踪Id
+ ///
+ [SugarColumn(ColumnDescription = "请求跟踪Id", Length = 128)]
+ [MaxLength(128)]
+ public string? TraceId { get; set; }
+
+ ///
+ /// 异常信息
+ ///
+ [SugarColumn(ColumnDescription = "异常信息", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? Exception { get; set; }
+
+ ///
+ /// 日志消息Json
+ ///
+ [SugarColumn(ColumnDescription = "日志消息Json", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? Message { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysLogOp.cs b/Admin.NET.Core/Entity/SysLogOp.cs
new file mode 100644
index 0000000..e5ba1c1
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysLogOp.cs
@@ -0,0 +1,72 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统操作日志表
+///
+[SugarTable(null, "系统操作日志表")]
+[SysTable]
+[LogTable]
+public partial class SysLogOp : SysLogVis
+{
+ ///
+ /// 请求方式
+ ///
+ [SugarColumn(ColumnDescription = "请求方式", Length = 32)]
+ [MaxLength(32)]
+ public string? HttpMethod { get; set; }
+
+ ///
+ /// 请求地址
+ ///
+ [SugarColumn(ColumnDescription = "请求地址", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? RequestUrl { get; set; }
+
+ ///
+ /// 请求参数
+ ///
+ [SugarColumn(ColumnDescription = "请求参数", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? RequestParam { get; set; }
+
+ ///
+ /// 返回结果
+ ///
+ [SugarColumn(ColumnDescription = "返回结果", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? ReturnResult { get; set; }
+
+ ///
+ /// 事件Id
+ ///
+ [SugarColumn(ColumnDescription = "事件Id")]
+ public int? EventId { get; set; }
+
+ ///
+ /// 线程Id
+ ///
+ [SugarColumn(ColumnDescription = "线程Id")]
+ public int? ThreadId { get; set; }
+
+ ///
+ /// 请求跟踪Id
+ ///
+ [SugarColumn(ColumnDescription = "请求跟踪Id", Length = 128)]
+ [MaxLength(128)]
+ public string? TraceId { get; set; }
+
+ ///
+ /// 异常信息
+ ///
+ [SugarColumn(ColumnDescription = "异常信息", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? Exception { get; set; }
+
+ ///
+ /// 日志消息Json
+ ///
+ [SugarColumn(ColumnDescription = "日志消息Json", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? Message { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysLogVis.cs b/Admin.NET.Core/Entity/SysLogVis.cs
new file mode 100644
index 0000000..6f269b5
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysLogVis.cs
@@ -0,0 +1,116 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统访问日志表
+///
+[SugarTable(null, "系统访问日志表")]
+[SysTable]
+[LogTable]
+public partial class SysLogVis : EntityBaseTenant
+{
+ ///
+ /// 模块名称
+ ///
+ [SugarColumn(ColumnDescription = "模块名称", Length = 256)]
+ [MaxLength(256)]
+ public string? ControllerName { get; set; }
+
+ ///
+ /// 方法名称
+ ///
+ [SugarColumn(ColumnDescription = "方法名称", Length = 256)]
+ [MaxLength(256)]
+ public string? ActionName { get; set; }
+
+ ///
+ /// 显示名称
+ ///
+ [SugarColumn(ColumnDescription = "显示名称", Length = 256)]
+ [MaxLength(256)]
+ public string? DisplayTitle { get; set; }
+
+ ///
+ /// 执行状态
+ ///
+ [SugarColumn(ColumnDescription = "执行状态", Length = 32)]
+ [MaxLength(32)]
+ public string? Status { get; set; }
+
+ ///
+ /// IP地址
+ ///
+ [SugarColumn(ColumnDescription = "IP地址", Length = 256)]
+ [MaxLength(256)]
+ public string? RemoteIp { get; set; }
+
+ ///
+ /// 登录地点
+ ///
+ [SugarColumn(ColumnDescription = "登录地点", Length = 128)]
+ [MaxLength(128)]
+ public string? Location { get; set; }
+
+ ///
+ /// 经度
+ ///
+ [SugarColumn(ColumnDescription = "经度")]
+ public decimal? Longitude { get; set; }
+
+ ///
+ /// 维度
+ ///
+ [SugarColumn(ColumnDescription = "维度")]
+ public decimal? Latitude { get; set; }
+
+ ///
+ /// 浏览器
+ ///
+ [SugarColumn(ColumnDescription = "浏览器", Length = 1024)]
+ [MaxLength(1024)]
+ public string? Browser { get; set; }
+
+ ///
+ /// 操作系统
+ ///
+ [SugarColumn(ColumnDescription = "操作系统", Length = 256)]
+ [MaxLength(256)]
+ public string? Os { get; set; }
+
+ ///
+ /// 操作用时
+ ///
+ [SugarColumn(ColumnDescription = "操作用时")]
+ public long? Elapsed { get; set; }
+
+ ///
+ /// 日志时间
+ ///
+ [SugarColumn(ColumnDescription = "日志时间")]
+ public DateTime? LogDateTime { get; set; }
+
+ ///
+ /// 日志级别
+ ///
+ [SugarColumn(ColumnDescription = "日志级别")]
+ public LogLevel? LogLevel { get; set; }
+
+ ///
+ /// 账号
+ ///
+ [SugarColumn(ColumnDescription = "账号", Length = 32)]
+ [MaxLength(32)]
+ public string? Account { get; set; }
+
+ ///
+ /// 真实姓名
+ ///
+ [SugarColumn(ColumnDescription = "真实姓名", Length = 32)]
+ [MaxLength(32)]
+ public string? RealName { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysMenu.cs b/Admin.NET.Core/Entity/SysMenu.cs
new file mode 100644
index 0000000..a89a776
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysMenu.cs
@@ -0,0 +1,134 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统菜单表
+///
+[SugarTable(null, "系统菜单表")]
+[SysTable]
+[SugarIndex("index_{table}_T", nameof(Title), OrderByType.Asc)]
+[SugarIndex("index_{table}_T2", nameof(Type), OrderByType.Asc)]
+public partial class SysMenu : EntityBase
+{
+ ///
+ /// 父Id
+ ///
+ [SugarColumn(ColumnDescription = "父Id")]
+ public long Pid { get; set; }
+
+ ///
+ /// 菜单类型(1目录 2菜单 3按钮)
+ ///
+ [SugarColumn(ColumnDescription = "菜单类型")]
+ public MenuTypeEnum Type { get; set; }
+
+ ///
+ /// 路由名称
+ ///
+ [SugarColumn(ColumnDescription = "路由名称", Length = 64)]
+ [MaxLength(64)]
+ public string? Name { get; set; }
+
+ ///
+ /// 路由地址
+ ///
+ [SugarColumn(ColumnDescription = "路由地址", Length = 128)]
+ [MaxLength(128)]
+ public string? Path { get; set; }
+
+ ///
+ /// 组件路径
+ ///
+ [SugarColumn(ColumnDescription = "组件路径", Length = 128)]
+ [MaxLength(128)]
+ public string? Component { get; set; }
+
+ ///
+ /// 重定向
+ ///
+ [SugarColumn(ColumnDescription = "重定向", Length = 128)]
+ [MaxLength(128)]
+ public string? Redirect { get; set; }
+
+ ///
+ /// 权限标识
+ ///
+ [SugarColumn(ColumnDescription = "权限标识", Length = 128)]
+ [MaxLength(128)]
+ public string? Permission { get; set; }
+
+ ///
+ /// 菜单名称
+ ///
+ [SugarColumn(ColumnDescription = "菜单名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string Title { get; set; }
+
+ ///
+ /// 图标
+ ///
+ [SugarColumn(ColumnDescription = "图标", Length = 128)]
+ [MaxLength(128)]
+ public string? Icon { get; set; } = "ele-Menu";
+
+ ///
+ /// 是否内嵌
+ ///
+ [SugarColumn(ColumnDescription = "是否内嵌")]
+ public bool IsIframe { get; set; }
+
+ ///
+ /// 外链链接
+ ///
+ [SugarColumn(ColumnDescription = "外链链接", Length = 256)]
+ [MaxLength(256)]
+ public string? OutLink { get; set; }
+
+ ///
+ /// 是否隐藏
+ ///
+ [SugarColumn(ColumnDescription = "是否隐藏")]
+ public bool IsHide { get; set; }
+
+ ///
+ /// 是否缓存
+ ///
+ [SugarColumn(ColumnDescription = "是否缓存")]
+ public bool IsKeepAlive { get; set; } = true;
+
+ ///
+ /// 是否固定
+ ///
+ [SugarColumn(ColumnDescription = "是否固定")]
+ public bool IsAffix { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 256)]
+ [MaxLength(256)]
+ public string? Remark { get; set; }
+
+ ///
+ /// 菜单子项
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public List Children { get; set; } = new();
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysNotice.cs b/Admin.NET.Core/Entity/SysNotice.cs
new file mode 100644
index 0000000..7aa7d01
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysNotice.cs
@@ -0,0 +1,82 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统通知公告表
+///
+[SugarTable(null, "系统通知公告表")]
+[SysTable]
+[SugarIndex("index_{table}_T", nameof(Type), OrderByType.Asc)]
+public partial class SysNotice : EntityBase
+{
+ ///
+ /// 标题
+ ///
+ [SugarColumn(ColumnDescription = "标题", Length = 32)]
+ [Required, MaxLength(32)]
+ [SensitiveDetection('*')]
+ public virtual string Title { get; set; }
+
+ ///
+ /// 内容
+ ///
+ [SugarColumn(ColumnDescription = "内容", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ [Required]
+ [SensitiveDetection('*')]
+ public virtual string Content { get; set; }
+
+ ///
+ /// 类型(1通知 2公告)
+ ///
+ [SugarColumn(ColumnDescription = "类型(1通知 2公告)")]
+ public NoticeTypeEnum Type { get; set; }
+
+ ///
+ /// 发布人Id
+ ///
+ [SugarColumn(ColumnDescription = "发布人Id")]
+ public long PublicUserId { get; set; }
+
+ ///
+ /// 发布人姓名
+ ///
+ [SugarColumn(ColumnDescription = "发布人姓名", Length = 32)]
+ [MaxLength(32)]
+ public string? PublicUserName { get; set; }
+
+ ///
+ /// 发布机构Id
+ ///
+ [SugarColumn(ColumnDescription = "发布机构Id")]
+ public long PublicOrgId { get; set; }
+
+ ///
+ /// 发布机构名称
+ ///
+ [SugarColumn(ColumnDescription = "发布机构名称", Length = 64)]
+ [MaxLength(64)]
+ public string? PublicOrgName { get; set; }
+
+ ///
+ /// 发布时间
+ ///
+ [SugarColumn(ColumnDescription = "发布时间")]
+ public DateTime? PublicTime { get; set; }
+
+ ///
+ /// 撤回时间
+ ///
+ [SugarColumn(ColumnDescription = "撤回时间")]
+ public DateTime? CancelTime { get; set; }
+
+ ///
+ /// 状态(0草稿 1发布 2撤回 3删除)
+ ///
+ [SugarColumn(ColumnDescription = "状态(0草稿 1发布 2撤回 3删除)")]
+ public NoticeStatusEnum Status { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysNoticeUser.cs b/Admin.NET.Core/Entity/SysNoticeUser.cs
new file mode 100644
index 0000000..5f71ba4
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysNoticeUser.cs
@@ -0,0 +1,45 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统通知公告用户表
+///
+[SugarTable(null, "系统通知公告用户表")]
+[SysTable]
+public partial class SysNoticeUser : EntityBaseId
+{
+ ///
+ /// 通知公告Id
+ ///
+ [SugarColumn(ColumnDescription = "通知公告Id")]
+ public long NoticeId { get; set; }
+
+ ///
+ /// 通知公告
+ ///
+ [Navigate(NavigateType.OneToOne, nameof(NoticeId))]
+ public SysNotice SysNotice { get; set; }
+
+ ///
+ /// 用户Id
+ ///
+ [SugarColumn(ColumnDescription = "用户Id")]
+ public long UserId { get; set; }
+
+ ///
+ /// 阅读时间
+ ///
+ [SugarColumn(ColumnDescription = "阅读时间")]
+ public DateTime? ReadTime { get; set; }
+
+ ///
+ /// 状态(0未读 1已读)
+ ///
+ [SugarColumn(ColumnDescription = "状态(0未读 1已读)")]
+ public NoticeUserStatusEnum ReadStatus { get; set; } = NoticeUserStatusEnum.UNREAD;
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysOnlineUser.cs b/Admin.NET.Core/Entity/SysOnlineUser.cs
new file mode 100644
index 0000000..d4eb387
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysOnlineUser.cs
@@ -0,0 +1,68 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统在线用户表
+///
+[SugarTable(null, "系统在线用户表")]
+[SysTable]
+public partial class SysOnlineUser : EntityBaseTenantId
+{
+ ///
+ /// 连接Id
+ ///
+ [SugarColumn(ColumnDescription = "连接Id")]
+ public string? ConnectionId { get; set; }
+
+ ///
+ /// 用户Id
+ ///
+ [SugarColumn(ColumnDescription = "用户Id")]
+ public long UserId { get; set; }
+
+ ///
+ /// 账号
+ ///
+ [SugarColumn(ColumnDescription = "账号", Length = 32)]
+ [Required, MaxLength(32)]
+ public virtual string UserName { get; set; }
+
+ ///
+ /// 真实姓名
+ ///
+ [SugarColumn(ColumnDescription = "真实姓名", Length = 32)]
+ [MaxLength(32)]
+ public string? RealName { get; set; }
+
+ ///
+ /// 连接时间
+ ///
+ [SugarColumn(ColumnDescription = "连接时间")]
+ public DateTime? Time { get; set; }
+
+ ///
+ /// 连接IP
+ ///
+ [SugarColumn(ColumnDescription = "连接IP", Length = 256)]
+ [MaxLength(256)]
+ public string? Ip { get; set; }
+
+ ///
+ /// 浏览器
+ ///
+ [SugarColumn(ColumnDescription = "浏览器", Length = 128)]
+ [MaxLength(128)]
+ public string? Browser { get; set; }
+
+ ///
+ /// 操作系统
+ ///
+ [SugarColumn(ColumnDescription = "操作系统", Length = 128)]
+ [MaxLength(128)]
+ public string? Os { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysOpenAccess.cs b/Admin.NET.Core/Entity/SysOpenAccess.cs
new file mode 100644
index 0000000..8680426
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysOpenAccess.cs
@@ -0,0 +1,56 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 开放接口身份表
+///
+[SugarTable(null, "开放接口身份表")]
+[SysTable]
+[SugarIndex("index_{table}_A", nameof(AccessKey), OrderByType.Asc)]
+public partial class SysOpenAccess : EntityBase
+{
+ ///
+ /// 身份标识
+ ///
+ [SugarColumn(ColumnDescription = "身份标识", Length = 128)]
+ [Required, MaxLength(128)]
+ public virtual string AccessKey { get; set; }
+
+ ///
+ /// 密钥
+ ///
+ [SugarColumn(ColumnDescription = "密钥", Length = 256)]
+ [Required, MaxLength(256)]
+ public virtual string AccessSecret { get; set; }
+
+ ///
+ /// 绑定租户Id
+ ///
+ [SugarColumn(ColumnDescription = "绑定租户Id")]
+ public long BindTenantId { get; set; }
+
+ ///
+ /// 绑定租户
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(BindTenantId))]
+ public SysTenant BindTenant { get; set; }
+
+ ///
+ /// 绑定用户Id
+ ///
+ [SugarColumn(ColumnDescription = "绑定用户Id")]
+ public virtual long BindUserId { get; set; }
+
+ ///
+ /// 绑定用户
+ ///
+ [Navigate(NavigateType.OneToOne, nameof(BindUserId))]
+ public SysUser BindUser { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysOrg.cs b/Admin.NET.Core/Entity/SysOrg.cs
new file mode 100644
index 0000000..d64a8a3
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysOrg.cs
@@ -0,0 +1,96 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统机构表
+///
+[SugarTable(null, "系统机构表")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
+[SugarIndex("index_{table}_C", nameof(Code), OrderByType.Asc)]
+[SugarIndex("index_{table}_T", nameof(Type), OrderByType.Asc)]
+public partial class SysOrg : EntityBaseTenant
+{
+ ///
+ /// 父Id
+ ///
+ [SugarColumn(ColumnDescription = "父Id")]
+ public long Pid { get; set; }
+
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string Name { get; set; }
+
+ ///
+ /// 编码
+ ///
+ [SugarColumn(ColumnDescription = "编码", Length = 64)]
+ [MaxLength(64)]
+ public string? Code { get; set; }
+
+ ///
+ /// 级别
+ ///
+ [SugarColumn(ColumnDescription = "级别")]
+ public int? Level { get; set; }
+
+ ///
+ /// 机构类型-数据字典
+ ///
+ [SugarColumn(ColumnDescription = "机构类型", Length = 64)]
+ [MaxLength(64)]
+ public virtual string? Type { get; set; }
+
+ ///
+ /// 负责人Id
+ ///
+ [SugarColumn(ColumnDescription = "负责人Id", IsNullable = true)]
+ public long? DirectorId { get; set; }
+
+ ///
+ /// 负责人
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(DirectorId))]
+ public SysUser Director { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 128)]
+ [MaxLength(128)]
+ public string? Remark { get; set; }
+
+ ///
+ /// 机构子项
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public List Children { get; set; }
+
+ ///
+ /// 是否禁止选中
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public bool Disabled { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysPlugin.cs b/Admin.NET.Core/Entity/SysPlugin.cs
new file mode 100644
index 0000000..86594dd
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysPlugin.cs
@@ -0,0 +1,56 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统动态插件表
+///
+[SugarTable(null, "系统动态插件表")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
+public partial class SysPlugin : EntityBaseTenant
+{
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string Name { get; set; }
+
+ ///
+ /// C#代码
+ ///
+ [SugarColumn(ColumnDescription = "C#代码", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ [Required]
+ public virtual string CsharpCode { get; set; }
+
+ ///
+ /// 程序集名称
+ ///
+ [SugarColumn(ColumnDescription = "程序集名称", Length = 512)]
+ [MaxLength(512)]
+ public string? AssemblyName { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 128)]
+ [MaxLength(128)]
+ public string? Remark { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysPos.cs b/Admin.NET.Core/Entity/SysPos.cs
new file mode 100644
index 0000000..7045eb8
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysPos.cs
@@ -0,0 +1,56 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统职位表
+///
+[SugarTable(null, "系统职位表")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
+[SugarIndex("index_{table}_C", nameof(Code), OrderByType.Asc)]
+public partial class SysPos : EntityBaseTenant
+{
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string Name { get; set; }
+
+ ///
+ /// 编码
+ ///
+ [SugarColumn(ColumnDescription = "编码", Length = 64)]
+ [MaxLength(64)]
+ public string? Code { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 128)]
+ [MaxLength(128)]
+ public string? Remark { get; set; }
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
+
+ ///
+ /// 在职人员
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public List UserList { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysPrint.cs b/Admin.NET.Core/Entity/SysPrint.cs
new file mode 100644
index 0000000..269d42a
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysPrint.cs
@@ -0,0 +1,75 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统打印模板表
+///
+[SugarTable(null, "系统打印模板表")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
+public partial class SysPrint : EntityBaseTenant
+{
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string Name { get; set; }
+
+ ///
+ /// 打印模板
+ ///
+ [SugarColumn(ColumnDescription = "打印模板", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ [Required]
+ public virtual string Template { get; set; }
+
+ ///
+ /// 打印类型
+ ///
+ [SugarColumn(ColumnDescription = "打印类型")]
+ [Required]
+ public virtual PrintTypeEnum? PrintType { get; set; }
+
+ ///
+ /// 客户端服务地址
+ ///
+ [SugarColumn(ColumnDescription = "客户端服务地址", Length = 128)]
+ [MaxLength(128)]
+ public virtual string? ClientServiceAddress { get; set; }
+
+ ///
+ /// 打印参数
+ ///
+ [SugarColumn(ColumnDescription = "打印参数", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public virtual string? PrintParam { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 128)]
+ [MaxLength(128)]
+ public string? Remark { get; set; }
+
+ ///
+ /// 打印预览测试数据
+ ///
+ [SugarColumn(ColumnDescription = "打印预览测试数据", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? PrintDataDemo { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysRegion.cs b/Admin.NET.Core/Entity/SysRegion.cs
new file mode 100644
index 0000000..7ada329
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysRegion.cs
@@ -0,0 +1,109 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统行政地区表
+///
+[SugarTable(null, "系统行政地区表")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
+[SugarIndex("index_{table}_C", nameof(Code), OrderByType.Asc, IsUnique = true)]
+public partial class SysRegion : EntityBaseId
+{
+ ///
+ /// 父Id
+ ///
+ [SugarColumn(ColumnDescription = "父Id")]
+ public long Pid { get; set; }
+
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 128)]
+ [Required, MaxLength(128)]
+ public virtual string Name { get; set; }
+
+ ///
+ /// 简称
+ ///
+ [SugarColumn(ColumnDescription = "简称", Length = 32)]
+ [MaxLength(32)]
+ public string? ShortName { get; set; }
+
+ ///
+ /// 组合名
+ ///
+ [SugarColumn(ColumnDescription = "组合名", Length = 64)]
+ [MaxLength(64)]
+ public string? MergerName { get; set; }
+
+ ///
+ /// 行政代码
+ ///
+ [SugarColumn(ColumnDescription = "行政代码", Length = 32)]
+ [MaxLength(32)]
+ public string? Code { get; set; }
+
+ ///
+ /// 邮政编码
+ ///
+ [SugarColumn(ColumnDescription = "邮政编码", Length = 6)]
+ [MaxLength(6)]
+ public string? ZipCode { get; set; }
+
+ ///
+ /// 区号
+ ///
+ [SugarColumn(ColumnDescription = "区号", Length = 6)]
+ [MaxLength(6)]
+ public string? CityCode { get; set; }
+
+ ///
+ /// 层级
+ ///
+ [SugarColumn(ColumnDescription = "层级")]
+ public int Level { get; set; }
+
+ ///
+ /// 拼音
+ ///
+ [SugarColumn(ColumnDescription = "拼音", Length = 128)]
+ [MaxLength(128)]
+ public string? PinYin { get; set; }
+
+ ///
+ /// 经度
+ ///
+ [SugarColumn(ColumnDescription = "经度")]
+ public float Lng { get; set; }
+
+ ///
+ /// 维度
+ ///
+ [SugarColumn(ColumnDescription = "维度")]
+ public float Lat { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 128)]
+ [MaxLength(128)]
+ public string? Remark { get; set; }
+
+ ///
+ /// 机构子项
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public List Children { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysRole.cs b/Admin.NET.Core/Entity/SysRole.cs
new file mode 100644
index 0000000..2f0eae4
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysRole.cs
@@ -0,0 +1,56 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统角色表
+///
+[SugarTable(null, "系统角色表")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
+[SugarIndex("index_{table}_C", nameof(Code), OrderByType.Asc)]
+public partial class SysRole : EntityBaseTenant
+{
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string Name { get; set; }
+
+ ///
+ /// 编码
+ ///
+ [SugarColumn(ColumnDescription = "编码", Length = 64)]
+ [MaxLength(64)]
+ public string? Code { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 数据范围(1全部数据 2本部门及以下数据 3本部门数据 4仅本人数据 5自定义数据)
+ ///
+ [SugarColumn(ColumnDescription = "数据范围")]
+ public DataScopeEnum DataScope { get; set; } = DataScopeEnum.Self;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 128)]
+ [MaxLength(128)]
+ public string? Remark { get; set; }
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysRoleMenu.cs b/Admin.NET.Core/Entity/SysRoleMenu.cs
new file mode 100644
index 0000000..04e3f1d
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysRoleMenu.cs
@@ -0,0 +1,35 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统角色菜单表
+///
+[SugarTable(null, "系统角色菜单表")]
+[SysTable]
+public class SysRoleMenu : EntityBaseId
+{
+ ///
+ /// 角色Id
+ ///
+ [SugarColumn(ColumnDescription = "角色Id")]
+ public long RoleId { get; set; }
+
+ ///
+ /// 菜单Id
+ ///
+ [SugarColumn(ColumnDescription = "菜单Id")]
+ public long MenuId { get; set; }
+
+ ///
+ /// 菜单
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(MenuId))]
+ public SysMenu SysMenu { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysRoleOrg.cs b/Admin.NET.Core/Entity/SysRoleOrg.cs
new file mode 100644
index 0000000..c4622f8
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysRoleOrg.cs
@@ -0,0 +1,35 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统角色机构表
+///
+[SugarTable(null, "系统角色机构表")]
+[SysTable]
+public class SysRoleOrg : EntityBaseId
+{
+ ///
+ /// 角色Id
+ ///
+ [SugarColumn(ColumnDescription = "角色Id")]
+ public long RoleId { get; set; }
+
+ ///
+ /// 机构Id
+ ///
+ [SugarColumn(ColumnDescription = "机构Id")]
+ public long OrgId { get; set; }
+
+ ///
+ /// 机构
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(OrgId))]
+ public SysOrg SysOrg { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysSchedule.cs b/Admin.NET.Core/Entity/SysSchedule.cs
new file mode 100644
index 0000000..4361bd3
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysSchedule.cs
@@ -0,0 +1,52 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统日程表
+///
+[SugarTable(null, "系统日程表")]
+[SysTable]
+public class SysSchedule : EntityBaseTenant
+{
+ ///
+ /// 用户Id
+ ///
+ [SugarColumn(ColumnDescription = "用户Id")]
+ public long UserId { get; set; }
+
+ ///
+ /// 日程日期
+ ///
+ [SugarColumn(ColumnDescription = "日程日期")]
+ public DateTime? ScheduleTime { get; set; }
+
+ ///
+ /// 开始时间
+ ///
+ [SugarColumn(ColumnDescription = "开始时间", Length = 10)]
+ public string? StartTime { get; set; }
+
+ ///
+ /// 结束时间
+ ///
+ [SugarColumn(ColumnDescription = "结束时间", Length = 10)]
+ public string? EndTime { get; set; }
+
+ ///
+ /// 日程内容
+ ///
+ [SugarColumn(ColumnDescription = "日程内容", Length = 256)]
+ [Required, MaxLength(256)]
+ public virtual string Content { get; set; }
+
+ ///
+ /// 完成状态
+ ///
+ [SugarColumn(ColumnDescription = "完成状态")]
+ public FinishStatusEnum Status { get; set; } = FinishStatusEnum.UnFinish;
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysTemplate.cs b/Admin.NET.Core/Entity/SysTemplate.cs
new file mode 100644
index 0000000..9364cd6
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysTemplate.cs
@@ -0,0 +1,63 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统模板表
+///
+[SysTable]
+[SugarTable(null, "系统模板表")]
+[SugarIndex("index_{table}_C", nameof(Code), OrderByType.Asc, IsUnique = true)]
+[SugarIndex("index_{table}_G", nameof(GroupName), OrderByType.Asc)]
+public partial class SysTemplate : EntityBaseTenant
+{
+ ///
+ /// 名称
+ ///
+ [MaxLength(128)]
+ [SugarColumn(ColumnDescription = "名称", Length = 128)]
+ public virtual string Name { get; set; }
+
+ ///
+ /// 分组名称
+ ///
+ [SugarColumn(ColumnDescription = "分组名称")]
+ public virtual TemplateTypeEnum Type { get; set; }
+
+ ///
+ /// 编码
+ ///
+ [MaxLength(128)]
+ [SugarColumn(ColumnDescription = "编码", Length = 128)]
+ public virtual string Code { get; set; }
+
+ ///
+ /// 分组名称
+ ///
+ [MaxLength(32)]
+ [SugarColumn(ColumnDescription = "分组名称", Length = 32)]
+ public virtual string GroupName { get; set; }
+
+ ///
+ /// 模板内容
+ ///
+ [SugarColumn(ColumnDescription = "模板内容", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public virtual string Content { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [MaxLength(128)]
+ [SugarColumn(ColumnDescription = "备注", Length = 128)]
+ public virtual string? Remark { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public virtual int OrderNo { get; set; } = 100;
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysTenant.cs b/Admin.NET.Core/Entity/SysTenant.cs
new file mode 100644
index 0000000..9f2090e
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysTenant.cs
@@ -0,0 +1,145 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统租户表
+///
+[SugarTable(null, "系统租户表")]
+[SysTable]
+public partial class SysTenant : EntityBase
+{
+ ///
+ /// 租管用户Id
+ ///
+ [SugarColumn(ColumnDescription = "租管用户Id")]
+ public virtual long UserId { get; set; }
+
+ ///
+ /// 机构Id
+ ///
+ [SugarColumn(ColumnDescription = "机构Id")]
+ public virtual long OrgId { get; set; }
+
+ ///
+ /// 域名
+ ///
+ [SugarColumn(ColumnDescription = "域名", Length = 128)]
+ [MaxLength(128)]
+ public virtual string? Host { get; set; }
+
+ ///
+ /// 租户类型
+ ///
+ [SugarColumn(ColumnDescription = "租户类型")]
+ public virtual TenantTypeEnum TenantType { get; set; }
+
+ ///
+ /// 数据库类型
+ ///
+ [SugarColumn(ColumnDescription = "数据库类型")]
+ public virtual SqlSugar.DbType DbType { get; set; }
+
+ ///
+ /// 数据库连接
+ ///
+ [SugarColumn(ColumnDescription = "数据库连接", Length = 256)]
+ [MaxLength(256)]
+ public virtual string? Connection { get; set; }
+
+ ///
+ /// 数据库标识
+ ///
+ [SugarColumn(ColumnDescription = "数据库标识", Length = 64)]
+ [MaxLength(64)]
+ public virtual string? ConfigId { get; set; }
+
+ ///
+ /// 从库连接/读写分离
+ ///
+ [SugarColumn(ColumnDescription = "从库连接/读写分离", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public virtual string? SlaveConnections { get; set; }
+
+ ///
+ /// 启用注册功能
+ ///
+ [SugarColumn(ColumnDescription = "启用注册功能")]
+ public virtual YesNoEnum? EnableReg { get; set; } = YesNoEnum.N;
+
+ ///
+ /// 默认注册方案Id
+ ///
+ [SugarColumn(ColumnDescription = "默认注册方案")]
+ public virtual long? RegWayId { get; set; }
+
+ ///
+ /// 图标
+ ///
+ [SugarColumn(ColumnDescription = "图标", Length = 256), MaxLength(256)]
+ public virtual string? Logo { get; set; }
+
+ ///
+ /// 标题
+ ///
+ [SugarColumn(ColumnDescription = "标题", Length = 32), MaxLength(32)]
+ public virtual string? Title { get; set; }
+
+ ///
+ /// 副标题
+ ///
+ [SugarColumn(ColumnDescription = "副标题", Length = 32), MaxLength(32)]
+ public virtual string? ViceTitle { get; set; }
+
+ ///
+ /// 副描述
+ ///
+ [SugarColumn(ColumnDescription = "副描述", Length = 64), MaxLength(64)]
+ public virtual string? ViceDesc { get; set; }
+
+ ///
+ /// 水印
+ ///
+ [SugarColumn(ColumnDescription = "水印", Length = 32), MaxLength(32)]
+ public virtual string? Watermark { get; set; }
+
+ ///
+ /// 版权信息
+ ///
+ [SugarColumn(ColumnDescription = "版权信息", Length = 64), MaxLength(64)]
+ public virtual string? Copyright { get; set; }
+
+ ///
+ /// ICP备案号
+ ///
+ [SugarColumn(ColumnDescription = "ICP备案号", Length = 32), MaxLength(32)]
+ public virtual string? Icp { get; set; }
+
+ ///
+ /// ICP地址
+ ///
+ [SugarColumn(ColumnDescription = "ICP地址", Length = 32), MaxLength(32)]
+ public virtual string? IcpUrl { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public virtual int OrderNo { get; set; } = 100;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 128)]
+ [MaxLength(128)]
+ public virtual string? Remark { get; set; }
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public virtual StatusEnum Status { get; set; } = StatusEnum.Enable;
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysTenantConfig.cs b/Admin.NET.Core/Entity/SysTenantConfig.cs
new file mode 100644
index 0000000..2cfd676
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysTenantConfig.cs
@@ -0,0 +1,21 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统租户配置参数表
+///
+[SugarTable(null, "系统租户配置参数表")]
+[SysTable]
+public partial class SysTenantConfig : SysConfig
+{
+ ///
+ /// 无效字段,用于忽略实体类的Value字段
+ ///
+ [SugarColumn(IsIgnore = true)]
+ private new string? Value { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysTenantConfigData.cs b/Admin.NET.Core/Entity/SysTenantConfigData.cs
new file mode 100644
index 0000000..0741c31
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysTenantConfigData.cs
@@ -0,0 +1,29 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统租户配置参数值表
+///
+[SugarTable(null, "系统租户配置参数值表")]
+[SysTable]
+[SugarIndex("index_{table}_TC", nameof(TenantId), OrderByType.Asc, nameof(ConfigId), OrderByType.Asc)]
+public class SysTenantConfigData : EntityBaseTenantId
+{
+ ///
+ /// 配置项Id
+ ///
+ [SugarColumn(ColumnDescription = "配置项Id")]
+ public long ConfigId { get; set; }
+
+ ///
+ /// 参数值
+ ///
+ [SugarColumn(ColumnDescription = "参数值", Length = 512)]
+ [MaxLength(512)]
+ public string? Value { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysTenantMenu.cs b/Admin.NET.Core/Entity/SysTenantMenu.cs
new file mode 100644
index 0000000..74ed1dc
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysTenantMenu.cs
@@ -0,0 +1,27 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统租户菜单表
+///
+[SysTable]
+[SugarTable(null, "系统租户菜单表")]
+public class SysTenantMenu : EntityBaseId
+{
+ ///
+ /// 租户Id
+ ///
+ [SugarColumn(ColumnDescription = "租户Id")]
+ public long TenantId { get; set; }
+
+ ///
+ /// 菜单Id
+ ///
+ [SugarColumn(ColumnDescription = "菜单Id")]
+ public long MenuId { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysUser.cs b/Admin.NET.Core/Entity/SysUser.cs
new file mode 100644
index 0000000..335753e
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysUser.cs
@@ -0,0 +1,353 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统用户表
+///
+[SugarTable(null, "系统用户表")]
+[SysTable]
+[SugarIndex("index_{table}_A", nameof(Account), OrderByType.Asc)]
+[SugarIndex("index_{table}_P", nameof(Phone), OrderByType.Asc)]
+public partial class SysUser : EntityBaseTenantOrg
+{
+ ///
+ /// 账号
+ ///
+ [SugarColumn(ColumnDescription = "账号", Length = 32)]
+ [Required, MaxLength(32)]
+ public virtual string Account { get; set; }
+
+ ///
+ /// 密码
+ ///
+ [SugarColumn(ColumnDescription = "密码", Length = 512)]
+ [MaxLength(512)]
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public virtual string Password { get; set; }
+
+ ///
+ /// 真实姓名
+ ///
+ [SugarColumn(ColumnDescription = "真实姓名", Length = 32)]
+ [MaxLength(32)]
+ public virtual string RealName { get; set; }
+
+ ///
+ /// 昵称
+ ///
+ [SugarColumn(ColumnDescription = "昵称", Length = 32)]
+ [MaxLength(32)]
+ public string? NickName { get; set; }
+
+ ///
+ /// 头像
+ ///
+ [SugarColumn(ColumnDescription = "头像", Length = 512)]
+ [MaxLength(512)]
+ public string? Avatar { get; set; }
+
+ ///
+ /// 性别-男_1、女_2
+ ///
+ [SugarColumn(ColumnDescription = "性别")]
+ public GenderEnum Sex { get; set; } = GenderEnum.Male;
+
+ ///
+ /// 年龄
+ ///
+ [SugarColumn(ColumnDescription = "年龄")]
+ public int Age { get; set; }
+
+ ///
+ /// 出生日期
+ ///
+ [SugarColumn(ColumnDescription = "出生日期")]
+ public DateTime? Birthday { get; set; }
+
+ ///
+ /// 民族
+ ///
+ [SugarColumn(ColumnDescription = "民族", Length = 32)]
+ [MaxLength(32)]
+ public string? Nation { get; set; }
+
+ ///
+ /// 手机号码
+ ///
+ [SugarColumn(ColumnDescription = "手机号码", Length = 16)]
+ [MaxLength(16)]
+ public string? Phone { get; set; }
+
+ ///
+ /// 证件类型
+ ///
+ [SugarColumn(ColumnDescription = "证件类型")]
+ public CardTypeEnum CardType { get; set; }
+
+ ///
+ /// 身份证号
+ ///
+ [SugarColumn(ColumnDescription = "身份证号", Length = 32)]
+ [MaxLength(32)]
+ public string? IdCardNum { get; set; }
+
+ ///
+ /// 邮箱
+ ///
+ [SugarColumn(ColumnDescription = "邮箱", Length = 64)]
+ [MaxLength(64)]
+ public string? Email { get; set; }
+
+ ///
+ /// 地址
+ ///
+ [SugarColumn(ColumnDescription = "地址", Length = 256)]
+ [MaxLength(256)]
+ public string? Address { get; set; }
+
+ ///
+ /// 文化程度
+ ///
+ [SugarColumn(ColumnDescription = "文化程度")]
+ public CultureLevelEnum CultureLevel { get; set; }
+
+ ///
+ /// 政治面貌
+ ///
+ [SugarColumn(ColumnDescription = "政治面貌", Length = 16)]
+ [MaxLength(16)]
+ public string? PoliticalOutlook { get; set; }
+
+ ///
+ /// 毕业院校
+ ///
+ [SugarColumn(ColumnDescription = "毕业院校", Length = 128)]
+ [MaxLength(128)]
+ public string? College { get; set; }
+
+ ///
+ /// 办公电话
+ ///
+ [SugarColumn(ColumnDescription = "办公电话", Length = 16)]
+ [MaxLength(16)]
+ public string? OfficePhone { get; set; }
+
+ ///
+ /// 紧急联系人
+ ///
+ [SugarColumn(ColumnDescription = "紧急联系人", Length = 32)]
+ [MaxLength(32)]
+ public string? EmergencyContact { get; set; }
+
+ ///
+ /// 紧急联系人电话
+ ///
+ [SugarColumn(ColumnDescription = "紧急联系人电话", Length = 16)]
+ [MaxLength(16)]
+ public string? EmergencyPhone { get; set; }
+
+ ///
+ /// 紧急联系人地址
+ ///
+ [SugarColumn(ColumnDescription = "紧急联系人地址", Length = 256)]
+ [MaxLength(256)]
+ public string? EmergencyAddress { get; set; }
+
+ ///
+ /// 个人简介
+ ///
+ [SugarColumn(ColumnDescription = "个人简介", Length = 512)]
+ [MaxLength(512)]
+ public string? Introduction { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 256)]
+ [MaxLength(256)]
+ public string? Remark { get; set; }
+
+ ///
+ /// 账号类型
+ ///
+ [SugarColumn(ColumnDescription = "账号类型")]
+ public AccountTypeEnum AccountType { get; set; } = AccountTypeEnum.NormalUser;
+
+ /////
+ ///// 直属机构Id
+ /////
+ //[SugarColumn(ColumnDescription = "直属机构Id")]
+ //public long OrgId { get; set; }
+
+ ///
+ /// 直属机构
+ ///
+ [Navigate(NavigateType.OneToOne, nameof(OrgId))]
+ public SysOrg SysOrg { get; set; }
+
+ ///
+ /// 直属主管Id
+ ///
+ [SugarColumn(ColumnDescription = "直属主管Id")]
+ public long? ManagerUserId { get; set; }
+
+ ///
+ /// 直属主管
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(ManagerUserId))]
+ public SysUser ManagerUser { get; set; }
+
+ ///
+ /// 职位Id
+ ///
+ [SugarColumn(ColumnDescription = "职位Id")]
+ public long PosId { get; set; }
+
+ ///
+ /// 职位
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(PosId))]
+ public SysPos SysPos { get; set; }
+
+ ///
+ /// 工号
+ ///
+ [SugarColumn(ColumnDescription = "工号", Length = 32)]
+ [MaxLength(32)]
+ public string? JobNum { get; set; }
+
+ ///
+ /// 职级
+ ///
+ [SugarColumn(ColumnDescription = "职级", Length = 32)]
+ [MaxLength(32)]
+ public string? PosLevel { get; set; }
+
+ ///
+ /// 职称
+ ///
+ [SugarColumn(ColumnDescription = "职称", Length = 32)]
+ [MaxLength(32)]
+ public string? PosTitle { get; set; }
+
+ ///
+ /// 擅长领域
+ ///
+ [SugarColumn(ColumnDescription = "擅长领域", Length = 32)]
+ [MaxLength(32)]
+ public string? Expertise { get; set; }
+
+ ///
+ /// 办公区域
+ ///
+ [SugarColumn(ColumnDescription = "办公区域", Length = 32)]
+ [MaxLength(32)]
+ public string? OfficeZone { get; set; }
+
+ ///
+ /// 办公室
+ ///
+ [SugarColumn(ColumnDescription = "办公室", Length = 32)]
+ [MaxLength(32)]
+ public string? Office { get; set; }
+
+ ///
+ /// 入职日期
+ ///
+ [SugarColumn(ColumnDescription = "入职日期")]
+ public DateTime? JoinDate { get; set; }
+
+ ///
+ /// 最新登录Ip
+ ///
+ [SugarColumn(ColumnDescription = "最新登录Ip", Length = 256)]
+ [MaxLength(256)]
+ public string? LastLoginIp { get; set; }
+
+ ///
+ /// 最新登录地点
+ ///
+ [SugarColumn(ColumnDescription = "最新登录地点", Length = 128)]
+ [MaxLength(128)]
+ public string? LastLoginAddress { get; set; }
+
+ ///
+ /// 最新登录时间
+ ///
+ [SugarColumn(ColumnDescription = "最新登录时间")]
+ public DateTime? LastLoginTime { get; set; }
+
+ ///
+ /// 最新登录设备
+ ///
+ [SugarColumn(ColumnDescription = "最新登录设备", Length = 128)]
+ [MaxLength(128)]
+ public string? LastLoginDevice { get; set; }
+
+ ///
+ /// 电子签名
+ ///
+ [SugarColumn(ColumnDescription = "电子签名", Length = 512)]
+ [MaxLength(512)]
+ public string? Signature { get; set; }
+
+ ///
+ /// 语言代码(如 zh-CN)
+ ///
+ [SugarColumn(ColumnDescription = "语言代码")]
+ public string LangCode { get; set; } = App.GetOptions().DefaultCulture;
+
+ ///
+ /// 个性化首页地址
+ ///
+ [SugarColumn(ColumnDescription = "个性化首页地址", Length = 512)]
+ [MaxLength(512)]
+ public string? Homepage { get; set; }
+
+ ///
+ /// 验证超级管理员类型,若账号类型为超级管理员则报错
+ ///
+ /// 自定义错误消息
+ public void ValidateIsSuperAdminAccountType(ErrorCodeEnum? errorMsg = ErrorCodeEnum.D1014)
+ {
+ if (AccountType == AccountTypeEnum.SuperAdmin)
+ {
+ throw Oops.Oh(errorMsg);
+ }
+ }
+
+ ///
+ /// 验证用户Id是否相同,若用户Id相同则报错
+ ///
+ /// 用户Id
+ /// 自定义错误消息
+ public void ValidateIsUserId(long userId, ErrorCodeEnum? errorMsg = ErrorCodeEnum.D1001)
+ {
+ if (Id == userId)
+ {
+ throw Oops.Oh(errorMsg);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysUserConfig.cs b/Admin.NET.Core/Entity/SysUserConfig.cs
new file mode 100644
index 0000000..50e5100
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysUserConfig.cs
@@ -0,0 +1,21 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统用户配置参数表
+///
+[SugarTable(null, "系统用户配置参数表")]
+[SysTable]
+public partial class SysUserConfig : SysConfig
+{
+ ///
+ /// 无效字段,用于忽略实体类的Value字段
+ ///
+ [SugarColumn(IsIgnore = true)]
+ private new string? Value { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysUserConfigData.cs b/Admin.NET.Core/Entity/SysUserConfigData.cs
new file mode 100644
index 0000000..f1bf4f9
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysUserConfigData.cs
@@ -0,0 +1,35 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统租户配置参数值表
+///
+[SugarTable(null, "系统租户配置参数值表")]
+[SysTable]
+[SugarIndex("index_{table}_UC", nameof(UserId), OrderByType.Asc, nameof(ConfigId), OrderByType.Asc)]
+public class SysUserConfigData : EntityBaseId
+{
+ ///
+ /// 用户Id
+ ///
+ [SugarColumn(ColumnDescription = "用户Id")]
+ public long UserId { get; set; }
+
+ ///
+ /// 配置项Id
+ ///
+ [SugarColumn(ColumnDescription = "配置项Id")]
+ public long ConfigId { get; set; }
+
+ ///
+ /// 参数值
+ ///
+ [SugarColumn(ColumnDescription = "参数值", Length = 512)]
+ [MaxLength(512)]
+ public string? Value { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysUserExtOrg.cs b/Admin.NET.Core/Entity/SysUserExtOrg.cs
new file mode 100644
index 0000000..cc8c3cb
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysUserExtOrg.cs
@@ -0,0 +1,77 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统用户扩展机构表
+///
+[SugarTable(null, "系统用户扩展机构表")]
+[SysTable]
+public partial class SysUserExtOrg : EntityBaseId
+{
+ ///
+ /// 用户Id
+ ///
+ [SugarColumn(ColumnDescription = "用户Id")]
+ public long UserId { get; set; }
+
+ ///
+ /// 用户
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(UserId))]
+ public SysUser SysUser { get; set; }
+
+ ///
+ /// 机构Id
+ ///
+ [SugarColumn(ColumnDescription = "机构Id")]
+ public long OrgId { get; set; }
+
+ ///
+ /// 机构
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(OrgId))]
+ public SysOrg SysOrg { get; set; }
+
+ ///
+ /// 职位Id
+ ///
+ [SugarColumn(ColumnDescription = "职位Id")]
+ public long PosId { get; set; }
+
+ ///
+ /// 职位
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(PosId))]
+ public SysPos SysPos { get; set; }
+
+ ///
+ /// 工号
+ ///
+ [SugarColumn(ColumnDescription = "工号", Length = 32)]
+ [MaxLength(32)]
+ public string? JobNum { get; set; }
+
+ ///
+ /// 职级
+ ///
+ [SugarColumn(ColumnDescription = "职级", Length = 32)]
+ [MaxLength(32)]
+ public string? PosLevel { get; set; }
+
+ ///
+ /// 入职日期
+ ///
+ [SugarColumn(ColumnDescription = "入职日期")]
+ public DateTime? JoinDate { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysUserLdap.cs b/Admin.NET.Core/Entity/SysUserLdap.cs
new file mode 100644
index 0000000..723c6ca
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysUserLdap.cs
@@ -0,0 +1,80 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统用户域配置表
+///
+[SugarTable(null, "系统用户域配置表")]
+[SysTable]
+[SugarIndex("index_{table}_A", nameof(Account), OrderByType.Asc)]
+[SugarIndex("index_{table}_U", nameof(UserId), OrderByType.Asc)]
+public class SysUserLdap : EntityBaseTenantId
+{
+ ///
+ /// 用户Id
+ ///
+ [SugarColumn(ColumnDescription = "用户Id")]
+ public long UserId { get; set; }
+
+ ///
+ /// 域账号
+ /// AD域对应sAMAccountName
+ /// Ldap对应uid
+ ///
+ [SugarColumn(ColumnDescription = "域账号", Length = 32)]
+ [Required]
+ public string Account { get; set; }
+
+ ///
+ /// 域用户名
+ ///
+ [SugarColumn(ColumnDescription = "域用户名", Length = 32)]
+ public string UserName { get; set; }
+
+ ///
+ /// 对应EmployeeId(用于数据导入对照)
+ ///
+ [SugarColumn(ColumnDescription = "对应EmployeeId", Length = 32)]
+ public string? EmployeeId { get; set; }
+
+ ///
+ /// 组织代码
+ ///
+ [SugarColumn(ColumnDescription = "组织代码", Length = 64)]
+ public string? DeptCode { get; set; }
+
+ ///
+ /// 最后设置密码时间
+ ///
+ [SugarColumn(ColumnDescription = "最后设置密码时间")]
+ public DateTime? PwdLastSetTime { get; set; }
+
+ ///
+ /// 邮箱
+ ///
+ [SugarColumn(ColumnDescription = "组织代码", Length = 64)]
+ public string? Mail { get; set; }
+
+ ///
+ /// 检查账户是否已过期
+ ///
+ [SugarColumn(ColumnDescription = "检查账户是否已过期")]
+ public bool AccountExpiresFlag { get; set; } = false;
+
+ ///
+ /// 密码设置是否永不过期
+ ///
+ [SugarColumn(ColumnDescription = "密码设置是否永不过期")]
+ public bool DontExpiresFlag { get; set; } = false;
+
+ ///
+ /// DN
+ ///
+ [SugarColumn(ColumnDescription = "DN", Length = 512)]
+ public string Dn { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysUserMenu.cs b/Admin.NET.Core/Entity/SysUserMenu.cs
new file mode 100644
index 0000000..ee2a683
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysUserMenu.cs
@@ -0,0 +1,41 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统用户菜单快捷导航表
+///
+[SugarTable(null, "系统用户菜单快捷导航表")]
+[SysTable]
+public partial class SysUserMenu : EntityBaseId
+{
+ ///
+ /// 用户Id
+ ///
+ [SugarColumn(ColumnDescription = "用户Id")]
+ public long UserId { get; set; }
+
+ ///
+ /// 用户
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(UserId))]
+ public SysUser SysUser { get; set; }
+
+ ///
+ /// 菜单Id
+ ///
+ [SugarColumn(ColumnDescription = "菜单Id")]
+ public long MenuId { get; set; }
+
+ ///
+ /// 菜单
+ ///
+ [Navigate(NavigateType.OneToOne, nameof(MenuId))]
+ public SysMenu SysMenu { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysUserRegWay.cs b/Admin.NET.Core/Entity/SysUserRegWay.cs
new file mode 100644
index 0000000..6ae445b
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysUserRegWay.cs
@@ -0,0 +1,59 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统用户注册方案表
+///
+[SugarTable(null, "系统用户注册方案表")]
+[SysTable]
+public partial class SysUserRegWay : EntityBaseTenant
+{
+ ///
+ /// 方案名称
+ ///
+ [MaxLength(32)]
+ [SugarColumn(ColumnDescription = "方案名称", Length = 32)]
+ public virtual string Name { get; set; }
+
+ ///
+ /// 账号类型
+ ///
+ [SugarColumn(ColumnDescription = "账号类型")]
+ public virtual AccountTypeEnum AccountType { get; set; } = AccountTypeEnum.NormalUser;
+
+ ///
+ /// 注册用户默认角色
+ ///
+ [SugarColumn(ColumnDescription = "角色")]
+ public virtual long RoleId { get; set; }
+
+ ///
+ /// 注册用户默认机构
+ ///
+ [SugarColumn(ColumnDescription = "机构")]
+ public virtual long OrgId { get; set; }
+
+ ///
+ /// 注册用户默认职位
+ ///
+ [SugarColumn(ColumnDescription = "职位")]
+ public virtual long PosId { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int OrderNo { get; set; } = 100;
+
+ ///
+ /// 备注
+ ///
+ [MaxLength(128)]
+ [SugarColumn(ColumnDescription = "备注", Length = 128)]
+ public string? Remark { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysUserRole.cs b/Admin.NET.Core/Entity/SysUserRole.cs
new file mode 100644
index 0000000..8d5cff1
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysUserRole.cs
@@ -0,0 +1,41 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统用户角色表
+///
+[SugarTable(null, "系统用户角色表")]
+[SysTable]
+public class SysUserRole : EntityBaseId
+{
+ ///
+ /// 用户Id
+ ///
+ [SugarColumn(ColumnDescription = "用户Id")]
+ public long UserId { get; set; }
+
+ ///
+ /// 用户
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(UserId))]
+ public SysUser SysUser { get; set; }
+
+ ///
+ /// 角色Id
+ ///
+ [SugarColumn(ColumnDescription = "角色Id")]
+ public long RoleId { get; set; }
+
+ ///
+ /// 角色
+ ///
+ [Navigate(NavigateType.OneToOne, nameof(RoleId))]
+ public SysRole SysRole { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysWechatPay.cs b/Admin.NET.Core/Entity/SysWechatPay.cs
new file mode 100644
index 0000000..0676295
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysWechatPay.cs
@@ -0,0 +1,191 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统微信支付表
+///
+[SugarTable(null, "系统微信支付表")]
+[SysTable]
+[SugarIndex("index_{table}_BU", nameof(BusinessId), OrderByType.Asc)]
+[SugarIndex("index_{table}_TR", nameof(TradeState), OrderByType.Asc)]
+[SugarIndex("index_{table}_TA", nameof(Tags), OrderByType.Asc)]
+public partial class SysWechatPay : EntityBase
+{
+ ///
+ /// 微信商户号
+ ///
+ [SugarColumn(ColumnDescription = "微信商户号")]
+ [Required]
+ public virtual string MerchantId { get; set; }
+
+ ///
+ /// 服务商AppId
+ ///
+ [SugarColumn(ColumnDescription = "服务商AppId")]
+ [Required]
+ public virtual string AppId { get; set; }
+
+ ///
+ /// 商户订单号
+ ///
+ [SugarColumn(ColumnDescription = "商户订单号")]
+ [Required]
+ public virtual string OutTradeNumber { get; set; }
+
+ ///
+ /// 支付订单号
+ ///
+ [SugarColumn(ColumnDescription = "支付订单号")]
+ [Required]
+ public virtual string TransactionId { get; set; }
+
+ ///
+ /// 交易类型
+ ///
+ [SugarColumn(ColumnDescription = "交易类型")]
+ public string? TradeType { get; set; }
+
+ ///
+ /// 交易状态
+ ///
+ [SugarColumn(ColumnDescription = "交易状态")]
+ public string? TradeState { get; set; }
+
+ ///
+ /// 交易状态描述
+ ///
+ [SugarColumn(ColumnDescription = "交易状态描述")]
+ public string? TradeStateDescription { get; set; }
+
+ ///
+ /// 付款银行类型
+ ///
+ [SugarColumn(ColumnDescription = "付款银行类型")]
+ public string? BankType { get; set; }
+
+ ///
+ /// 订单总金额
+ ///
+ [SugarColumn(ColumnDescription = "订单总金额")]
+ public int Total { get; set; }
+
+ ///
+ /// 用户支付金额
+ ///
+ [SugarColumn(ColumnDescription = "用户支付金额")]
+ public int? PayerTotal { get; set; }
+
+ ///
+ /// 支付完成时间
+ ///
+ [SugarColumn(ColumnDescription = "支付完成时间")]
+ public DateTime? SuccessTime { get; set; }
+
+ ///
+ /// 交易结束时间
+ ///
+ [SugarColumn(ColumnDescription = "交易结束时间")]
+ public DateTime? ExpireTime { get; set; }
+
+ ///
+ /// 商品描述
+ ///
+ [SugarColumn(ColumnDescription = "商品描述")]
+ public string? Description { get; set; }
+
+ ///
+ /// 场景信息
+ ///
+ [SugarColumn(ColumnDescription = "场景信息")]
+ public string? Scene { get; set; }
+
+ ///
+ /// 附加数据
+ ///
+ [SugarColumn(ColumnDescription = "附加数据")]
+ public string? Attachment { get; set; }
+
+ ///
+ /// 优惠标记
+ ///
+ [SugarColumn(ColumnDescription = "优惠标记")]
+ public string? GoodsTag { get; set; }
+
+ ///
+ /// 结算信息
+ ///
+ [SugarColumn(ColumnDescription = "结算信息")]
+ public string? Settlement { get; set; }
+
+ ///
+ /// 回调通知地址
+ ///
+ [SugarColumn(ColumnDescription = "回调通知地址")]
+ public string? NotifyUrl { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注")]
+ public string? Remark { get; set; }
+
+ ///
+ /// 微信OpenId标识
+ ///
+ [SugarColumn(ColumnDescription = "微信OpenId标识")]
+ public string? OpenId { get; set; }
+
+ ///
+ /// 业务标签,用来区分做什么业务
+ ///
+ ///
+ /// Tags标识用来区分这个支付记录对应什么业务从而确定相关联的表名,
+ /// 再结合BusinessId保存了对应的业务数据的ID,就可以确定这个支付
+ /// 记录与哪一条业务数据相关联
+ ///
+ [SugarColumn(ColumnDescription = "业务标签,用来区分做什么业务", Length = 64)]
+ public string? Tags { get; set; }
+
+ ///
+ /// 对应业务的主键
+ ///
+ [SugarColumn(ColumnDescription = "对应业务的主键")]
+ public long BusinessId { get; set; }
+
+ ///
+ /// 付款二维码内容
+ ///
+ [SugarColumn(ColumnDescription = "付款二维码内容")]
+ public string? QrcodeContent { get; set; }
+
+ ///
+ /// 关联微信用户
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(OpenId))]
+ public SysWechatUser SysWechatUser { get; set; }
+
+ ///
+ /// 子商户号
+ ///
+ [SugarColumn(ColumnDescription = "子商户号")]
+ public string? SubMerchantId { get; set; }
+
+ ///
+ /// 子商户AppId
+ ///
+ [SugarColumn(ColumnDescription = "回调通知地址")]
+ public string? SubAppId { get; set; }
+
+ ///
+ /// 子商户唯一标识
+ ///
+ [SugarColumn(ColumnDescription = "子商户唯一标识")]
+ public string? SubOpenId { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysWechatRefund.cs b/Admin.NET.Core/Entity/SysWechatRefund.cs
new file mode 100644
index 0000000..cc9b938
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysWechatRefund.cs
@@ -0,0 +1,97 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统微信支付退款表
+///
+[SugarTable(null, "系统微信支付退款表")]
+[SysTable]
+[SugarIndex("index_{table}_W", nameof(WechatPayId), OrderByType.Asc)]
+public partial class SysWechatRefund : EntityBase
+{
+ ///
+ /// 定单主键
+ ///
+ [SugarColumn(ColumnDescription = "定单主键")]
+ public long WechatPayId { get; set; }
+
+ ///
+ /// 商户退款号
+ ///
+ [SugarColumn(ColumnDescription = "商户退款号")]
+ [Required]
+ public virtual string OutRefundNumber { get; set; }
+
+ ///
+ /// 退款订单号
+ ///
+ [SugarColumn(ColumnDescription = "退款订单号")]
+ [Required]
+ public virtual string TransactionId { get; set; }
+
+ ///
+ /// 退款原因
+ ///
+ [SugarColumn(ColumnDescription = "退款原因")]
+ public string? Reason { get; set; }
+
+ ///
+ /// 退款渠道
+ ///
+ [SugarColumn(ColumnDescription = "退款渠道")]
+ public string? Channel { get; set; }
+
+ ///
+ /// 退款入账账户
+ ///
+ ///
+ /// 取当前退款单的退款入账方,有以下几种情况:
+ /// 1)退回银行卡:{银行名称}{卡类型}{ 卡尾号}
+ /// 2)退回支付用户零钱: 支付用户零钱
+ /// 3)退还商户: 商户基本账户商户结算银行账户
+ /// 4)退回支付用户零钱通: 支付用户零钱通
+ ///
+ [SugarColumn(ColumnDescription = "退款入账账户")]
+ public string? UserReceivedAccount { get; set; }
+
+ ///
+ /// 退款状态
+ ///
+ [SugarColumn(ColumnDescription = "退款状态")]
+ public string? TradeState { get; set; }
+
+ ///
+ /// 交易状态描述
+ ///
+ [SugarColumn(ColumnDescription = "交易状态描述")]
+ public string? TradeStateDescription { get; set; }
+
+ ///
+ /// 订单总金额
+ ///
+ [SugarColumn(ColumnDescription = "退款金额")]
+ public int Refund { get; set; }
+
+ ///
+ /// 支完成时间
+ ///
+ [SugarColumn(ColumnDescription = "完成时间")]
+ public DateTime? SuccessTime { get; set; }
+
+ ///
+ /// 回调通知地址
+ ///
+ [SugarColumn(ColumnDescription = "回调通知地址")]
+ public string? NotifyUrl { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注")]
+ public string? Remark { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Entity/SysWechatUser.cs b/Admin.NET.Core/Entity/SysWechatUser.cs
new file mode 100644
index 0000000..8aa2e58
--- /dev/null
+++ b/Admin.NET.Core/Entity/SysWechatUser.cs
@@ -0,0 +1,138 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统微信用户表
+///
+[SugarTable(null, "系统微信用户表")]
+[SysTable]
+[SugarIndex("index_{table}_N", nameof(NickName), OrderByType.Asc)]
+[SugarIndex("index_{table}_M", nameof(Mobile), OrderByType.Asc)]
+public partial class SysWechatUser : EntityBase
+{
+ ///
+ /// 系统用户Id
+ ///
+ [SugarColumn(ColumnDescription = "系统用户Id")]
+ public long UserId { get; set; }
+
+ ///
+ /// 系统用户
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ [Navigate(NavigateType.OneToOne, nameof(UserId))]
+ public SysUser SysUser { get; set; }
+
+ ///
+ /// 平台类型
+ ///
+ [SugarColumn(ColumnDescription = "平台类型")]
+ public PlatformTypeEnum PlatformType { get; set; } = PlatformTypeEnum.微信公众号;
+
+ ///
+ /// OpenId
+ ///
+ [SugarColumn(ColumnDescription = "OpenId", Length = 64)]
+ [Required, MaxLength(64)]
+ public virtual string OpenId { get; set; }
+
+ ///
+ /// 会话密钥
+ ///
+ [SugarColumn(ColumnDescription = "会话密钥", Length = 256)]
+ [MaxLength(256)]
+ public string? SessionKey { get; set; }
+
+ ///
+ /// UnionId
+ ///
+ [SugarColumn(ColumnDescription = "UnionId", Length = 64)]
+ [MaxLength(64)]
+ public string? UnionId { get; set; }
+
+ ///
+ /// 昵称
+ ///
+ [SugarColumn(ColumnDescription = "昵称", Length = 64)]
+ [MaxLength(64)]
+ public string? NickName { get; set; }
+
+ ///
+ /// 头像
+ ///
+ [SugarColumn(ColumnDescription = "头像", Length = 256)]
+ [MaxLength(256)]
+ public string? Avatar { get; set; }
+
+ ///
+ /// 手机号码
+ ///
+ [SugarColumn(ColumnDescription = "手机号码", Length = 16)]
+ [MaxLength(16)]
+ public string? Mobile { get; set; }
+
+ ///
+ /// 性别
+ ///
+ [SugarColumn(ColumnDescription = "性别")]
+ public int? Sex { get; set; }
+
+ ///
+ /// 语言
+ ///
+ [SugarColumn(ColumnDescription = "语言", Length = 64)]
+ [MaxLength(64)]
+ public string? Language { get; set; }
+
+ ///
+ /// 城市
+ ///
+ [SugarColumn(ColumnDescription = "城市", Length = 64)]
+ [MaxLength(64)]
+ public string? City { get; set; }
+
+ ///
+ /// 省
+ ///
+ [SugarColumn(ColumnDescription = "省", Length = 64)]
+ [MaxLength(64)]
+ public string? Province { get; set; }
+
+ ///
+ /// 国家
+ ///
+ [SugarColumn(ColumnDescription = "国家", Length = 64)]
+ [MaxLength(64)]
+ public string? Country { get; set; }
+
+ ///
+ /// AccessToken
+ ///
+ [SugarColumn(ColumnDescription = "AccessToken", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? AccessToken { get; set; }
+
+ ///
+ /// RefreshToken
+ ///
+ [SugarColumn(ColumnDescription = "RefreshToken", ColumnDataType = StaticConfig.CodeFirst_BigString)]
+ public string? RefreshToken { get; set; }
+
+ ///
+ /// 过期时间
+ ///
+ [SugarColumn(ColumnDescription = "ExpiresIn")]
+ public int? ExpiresIn { get; set; }
+
+ ///
+ /// 用户授权的作用域,使用逗号分隔
+ ///
+ [SugarColumn(ColumnDescription = "授权作用域", Length = 64)]
+ [MaxLength(64)]
+ public string? Scope { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/AccountTypeEnum.cs b/Admin.NET.Core/Enum/AccountTypeEnum.cs
new file mode 100644
index 0000000..bedbec6
--- /dev/null
+++ b/Admin.NET.Core/Enum/AccountTypeEnum.cs
@@ -0,0 +1,38 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 账号类型枚举
+///
+[Description("账号类型枚举")]
+public enum AccountTypeEnum
+{
+ ///
+ /// 超级管理员
+ ///
+ [Description("超级管理员")]
+ SuperAdmin = 999,
+
+ ///
+ /// 系统管理员
+ ///
+ [Description("系统管理员")]
+ SysAdmin = 888,
+
+ ///
+ /// 普通账号
+ ///
+ [Description("普通账号")]
+ NormalUser = 777,
+
+ ///
+ /// 会员
+ ///
+ [Description("会员")]
+ Member = 666,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/AlipayCertTypeEnum.cs b/Admin.NET.Core/Enum/AlipayCertTypeEnum.cs
new file mode 100644
index 0000000..8bc1c34
--- /dev/null
+++ b/Admin.NET.Core/Enum/AlipayCertTypeEnum.cs
@@ -0,0 +1,21 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 参与方的证件类型枚举
+///
+[SuppressSniffer]
+[Description("参与方的证件类型枚举")]
+public enum AlipayCertTypeEnum
+{
+ [Description("身份证")]
+ IDENTITY_CARD,
+
+ [Description("护照")]
+ PASSPORT
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/AlipayIdentityTypeEnum.cs b/Admin.NET.Core/Enum/AlipayIdentityTypeEnum.cs
new file mode 100644
index 0000000..4b2d864
--- /dev/null
+++ b/Admin.NET.Core/Enum/AlipayIdentityTypeEnum.cs
@@ -0,0 +1,21 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 参与方的标识类型枚举
+///
+[SuppressSniffer]
+[Description("参与方的标识类型枚举")]
+public enum AlipayIdentityTypeEnum
+{
+ [Description("支付宝用户UID")]
+ ALIPAY_USER_ID,
+
+ [Description("支付宝登录号")]
+ ALIPAY_LOGON_ID
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/CacheTypeEnum.cs b/Admin.NET.Core/Enum/CacheTypeEnum.cs
new file mode 100644
index 0000000..e6832ed
--- /dev/null
+++ b/Admin.NET.Core/Enum/CacheTypeEnum.cs
@@ -0,0 +1,26 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 缓存类型枚举
+///
+[Description("缓存类型枚举")]
+public enum CacheTypeEnum
+{
+ ///
+ /// 内存缓存
+ ///
+ [Description("内存缓存")]
+ Memory,
+
+ ///
+ /// Redis缓存
+ ///
+ [Description("Redis缓存")]
+ Redis
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/CardTypeEnum.cs b/Admin.NET.Core/Enum/CardTypeEnum.cs
new file mode 100644
index 0000000..774359b
--- /dev/null
+++ b/Admin.NET.Core/Enum/CardTypeEnum.cs
@@ -0,0 +1,50 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 证件类型枚举
+///
+[Description("证件类型枚举")]
+public enum CardTypeEnum
+{
+ ///
+ /// 身份证
+ ///
+ [Description("身份证")]
+ IdCard = 0,
+
+ ///
+ /// 护照
+ ///
+ [Description("护照")]
+ PassportCard = 1,
+
+ ///
+ /// 出生证
+ ///
+ [Description("出生证")]
+ BirthCard = 2,
+
+ ///
+ /// 港澳台通行证
+ ///
+ [Description("港澳台通行证")]
+ GatCard = 3,
+
+ ///
+ /// 外国人居留证
+ ///
+ [Description("外国人居留证")]
+ ForeignCard = 4,
+
+ ///
+ /// 营业执照
+ ///
+ [Description("营业执照")]
+ License = 5,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/CryptogramEnum.cs b/Admin.NET.Core/Enum/CryptogramEnum.cs
new file mode 100644
index 0000000..e259bea
--- /dev/null
+++ b/Admin.NET.Core/Enum/CryptogramEnum.cs
@@ -0,0 +1,32 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 密码加密枚举
+///
+[Description("密码加密枚举")]
+public enum CryptogramEnum
+{
+ ///
+ /// MD5
+ ///
+ [Description("MD5")]
+ MD5 = 0,
+
+ ///
+ /// SM2(国密)
+ ///
+ [Description("SM2")]
+ SM2 = 1,
+
+ ///
+ /// SM4(国密)
+ ///
+ [Description("SM4")]
+ SM4 = 2
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/CultureLevelEnum.cs b/Admin.NET.Core/Enum/CultureLevelEnum.cs
new file mode 100644
index 0000000..ce54e33
--- /dev/null
+++ b/Admin.NET.Core/Enum/CultureLevelEnum.cs
@@ -0,0 +1,92 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 文化程度枚举
+///
+[Description("文化程度枚举")]
+public enum CultureLevelEnum
+{
+ ///
+ /// 其他
+ ///
+ [Description("其他"), Theme("info")]
+ Level0 = 0,
+
+ ///
+ /// 文盲
+ ///
+ [Description("文盲")]
+ Level1 = 1,
+
+ ///
+ /// 小学
+ ///
+ [Description("小学")]
+ Level2 = 2,
+
+ ///
+ /// 初中
+ ///
+ [Description("初中")]
+ Level3 = 3,
+
+ ///
+ /// 普通高中
+ ///
+ [Description("普通高中")]
+ Level4 = 4,
+
+ ///
+ /// 技工学校
+ ///
+ [Description("技工学校")]
+ Level5 = 5,
+
+ ///
+ /// 职业教育
+ ///
+ [Description("职业教育")]
+ Level6 = 6,
+
+ ///
+ /// 职业高中
+ ///
+ [Description("职业高中")]
+ Level7 = 7,
+
+ ///
+ /// 中等专科
+ ///
+ [Description("中等专科")]
+ Level8 = 8,
+
+ ///
+ /// 大学专科
+ ///
+ [Description("大学专科")]
+ Level9 = 9,
+
+ ///
+ /// 大学本科
+ ///
+ [Description("大学本科")]
+ Level10 = 10,
+
+ ///
+ /// 硕士研究生
+ ///
+ [Description("硕士研究生")]
+ Level11 = 11,
+
+ ///
+ /// 博士研究生
+ ///
+ [Description("博士研究生")]
+ Level12 = 12,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/DataOpTypeEnum.cs b/Admin.NET.Core/Enum/DataOpTypeEnum.cs
new file mode 100644
index 0000000..71ae9c0
--- /dev/null
+++ b/Admin.NET.Core/Enum/DataOpTypeEnum.cs
@@ -0,0 +1,92 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 数据操作类型枚举
+///
+[Description("数据操作类型枚举")]
+public enum DataOpTypeEnum
+{
+ ///
+ /// 其它
+ ///
+ [Description("其它"), Theme("info")]
+ Other,
+
+ ///
+ /// 增加
+ ///
+ [Description("增加")]
+ Add,
+
+ ///
+ /// 删除
+ ///
+ [Description("删除")]
+ Delete,
+
+ ///
+ /// 编辑
+ ///
+ [Description("编辑")]
+ Edit,
+
+ ///
+ /// 更新
+ ///
+ [Description("更新")]
+ Update,
+
+ ///
+ /// 查询
+ ///
+ [Description("查询")]
+ Query,
+
+ ///
+ /// 详情
+ ///
+ [Description("详情")]
+ Detail,
+
+ ///
+ /// 树
+ ///
+ [Description("树")]
+ Tree,
+
+ ///
+ /// 导入
+ ///
+ [Description("导入")]
+ Import,
+
+ ///
+ /// 导出
+ ///
+ [Description("导出")]
+ Export,
+
+ ///
+ /// 授权
+ ///
+ [Description("授权")]
+ Grant,
+
+ ///
+ /// 强退
+ ///
+ [Description("强退")]
+ Force,
+
+ ///
+ /// 清空
+ ///
+ [Description("清空")]
+ Clean
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/DataScopeEnum.cs b/Admin.NET.Core/Enum/DataScopeEnum.cs
new file mode 100644
index 0000000..d6fc8bd
--- /dev/null
+++ b/Admin.NET.Core/Enum/DataScopeEnum.cs
@@ -0,0 +1,44 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 角色数据范围枚举
+///
+[Description("角色数据范围枚举")]
+public enum DataScopeEnum
+{
+ ///
+ /// 全部数据
+ ///
+ [Description("全部数据")]
+ All = 1,
+
+ ///
+ /// 本部门及以下数据
+ ///
+ [Description("本部门及以下数据")]
+ DeptChild = 2,
+
+ ///
+ /// 本部门数据
+ ///
+ [Description("本部门数据")]
+ Dept = 3,
+
+ ///
+ /// 仅本人数据
+ ///
+ [Description("仅本人数据")]
+ Self = 4,
+
+ ///
+ /// 自定义数据
+ ///
+ [Description("自定义数据")]
+ Define = 5
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/DirectionEnum.cs b/Admin.NET.Core/Enum/DirectionEnum.cs
new file mode 100644
index 0000000..caa57ad
--- /dev/null
+++ b/Admin.NET.Core/Enum/DirectionEnum.cs
@@ -0,0 +1,26 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 书写方向枚举
+///
+[Description("书写方向枚举")]
+public enum DirectionEnum
+{
+ ///
+ /// 从左到右
+ ///
+ [Description("从左到右")]
+ Ltr = 1,
+
+ ///
+ /// 从右到左
+ ///
+ [Description("从右到左")]
+ Rtl = 2
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/ElasticSearchAuthTypeEnum.cs b/Admin.NET.Core/Enum/ElasticSearchAuthTypeEnum.cs
new file mode 100644
index 0000000..e11fb00
--- /dev/null
+++ b/Admin.NET.Core/Enum/ElasticSearchAuthTypeEnum.cs
@@ -0,0 +1,39 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// ES认证类型枚举
+/// https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/_options_on_elasticsearchclientsettings.html
+///
+[Description("ES认证类型枚举")]
+public enum ElasticSearchAuthTypeEnum
+{
+ ///
+ /// BasicAuthentication
+ ///
+ [Description("BasicAuthentication")]
+ Basic = 1,
+
+ ///
+ /// ApiKey
+ ///
+ [Description("ApiKey")]
+ ApiKey = 2,
+
+ ///
+ /// Base64ApiKey
+ ///
+ [Description("Base64ApiKey")]
+ Base64ApiKey = 3,
+
+ ///
+ /// 不验证
+ ///
+ [Description("None")]
+ None = 4
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/ErrorCodeEnum.cs b/Admin.NET.Core/Enum/ErrorCodeEnum.cs
new file mode 100644
index 0000000..dff72be
--- /dev/null
+++ b/Admin.NET.Core/Enum/ErrorCodeEnum.cs
@@ -0,0 +1,909 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统错误码
+///
+[ErrorCodeType]
+[Description("系统错误码")]
+public enum ErrorCodeEnum
+{
+ ///
+ /// 验证码错误
+ ///
+ [ErrorCodeItemMetadata("验证码错误")]
+ D0008,
+
+ ///
+ /// 账号不存在
+ ///
+ [ErrorCodeItemMetadata("账号不存在")]
+ D0009,
+
+ ///
+ /// 密匙不匹配
+ ///
+ [ErrorCodeItemMetadata("密匙不匹配")]
+ D0010,
+
+ ///
+ /// 账号或密码不正确
+ ///
+ [ErrorCodeItemMetadata("账号或密码不正确")]
+ D1000,
+
+ ///
+ /// 非法操作!禁止删除自己
+ ///
+ [ErrorCodeItemMetadata("非法操作,禁止删除自己")]
+ D1001,
+
+ ///
+ /// 记录不存在
+ ///
+ [ErrorCodeItemMetadata("记录不存在")]
+ D1002,
+
+ ///
+ /// 账号已存在
+ ///
+ [ErrorCodeItemMetadata("账号已存在")]
+ D1003,
+
+ ///
+ /// 旧密码不匹配
+ ///
+ [ErrorCodeItemMetadata("旧密码输入错误")]
+ D1004,
+
+ /////
+ ///// 测试数据禁止更改admin密码
+ /////
+ //[ErrorCodeItemMetadata("测试数据禁止更改用户【admin】密码")]
+ //D1005,
+
+ ///
+ /// 数据已存在
+ ///
+ [ErrorCodeItemMetadata("数据已存在")]
+ D1006,
+
+ ///
+ /// 数据不存在或含有关联引用,禁止删除
+ ///
+ [ErrorCodeItemMetadata("数据不存在或含有关联引用,禁止删除")]
+ D1007,
+
+ ///
+ /// 禁止为管理员分配角色
+ ///
+ [ErrorCodeItemMetadata("禁止为管理员分配角色")]
+ D1008,
+
+ ///
+ /// 重复数据或记录含有不存在数据
+ ///
+ [ErrorCodeItemMetadata("重复数据或记录含有不存在数据")]
+ D1009,
+
+ ///
+ /// 禁止为超级管理员角色分配权限
+ ///
+ [ErrorCodeItemMetadata("禁止为超级管理员角色分配权限")]
+ D1010,
+
+ ///
+ /// 非法操作,未登录
+ ///
+ [ErrorCodeItemMetadata("非法操作,未登录")]
+ D1011,
+
+ ///
+ /// Id不能为空
+ ///
+ [ErrorCodeItemMetadata("Id不能为空")]
+ D1012,
+
+ ///
+ /// 所属机构不在自己的数据范围内
+ ///
+ [ErrorCodeItemMetadata("没有权限操作该数据")]
+ D1013,
+
+ ///
+ /// 禁止删除超级管理员
+ ///
+ [ErrorCodeItemMetadata("禁止删除超级管理员")]
+ D1014,
+
+ ///
+ /// 禁止修改超级管理员状态
+ ///
+ [ErrorCodeItemMetadata("禁止修改超级管理员状态")]
+ D1015,
+
+ ///
+ /// 没有权限
+ ///
+ [ErrorCodeItemMetadata("没有权限")]
+ D1016,
+
+ ///
+ /// 账号已冻结
+ ///
+ [ErrorCodeItemMetadata("账号已冻结")]
+ D1017,
+
+ ///
+ /// 该租户下角色菜单权限集为空
+ ///
+ [ErrorCodeItemMetadata("该租户下角色菜单权限集为空")]
+ D1019,
+
+ ///
+ /// 禁止删除默认租户
+ ///
+ [ErrorCodeItemMetadata("禁止删除默认租户")]
+ D1023,
+
+ ///
+ /// 已将其他地方登录账号下线
+ ///
+ [ErrorCodeItemMetadata("已将其他地方登录账号下线")]
+ D1024,
+
+ ///
+ /// 此角色下面存在账号禁止删除
+ ///
+ [ErrorCodeItemMetadata("此角色下面存在账号禁止删除")]
+ D1025,
+
+ ///
+ /// 禁止修改本人账号状态
+ ///
+ [ErrorCodeItemMetadata("禁止修改本人账号状态")]
+ D1026,
+
+ ///
+ /// 密码错误次数过多,账号已锁定,请半小时后重试!
+ ///
+ [ErrorCodeItemMetadata("密码错误次数过多,账号已锁定,请半小时后重试!")]
+ D1027,
+
+ ///
+ /// 新密码不能与旧密码相同
+ ///
+ [ErrorCodeItemMetadata("新密码不能与旧密码相同")]
+ D1028,
+
+ ///
+ /// 系统默认账号禁止删除
+ ///
+ [ErrorCodeItemMetadata("系统默认账号禁止删除")]
+ D1029,
+
+ ///
+ /// 开放接口绑定账号禁止删除
+ ///
+ [ErrorCodeItemMetadata("开放接口绑定账号禁止删除")]
+ D1030,
+
+ ///
+ /// 开放接口绑定租户禁止删除
+ ///
+ [ErrorCodeItemMetadata("开放接口绑定租户禁止删除")]
+ D1031,
+
+ ///
+ /// 手机号已存在
+ ///
+ [ErrorCodeItemMetadata("手机号已存在")]
+ D1032,
+
+ ///
+ /// 此角色下存在注册方案禁止删除
+ ///
+ [ErrorCodeItemMetadata("此角色下存在注册方案禁止删除")]
+ D1033,
+
+ ///
+ /// 注册功能未开启禁止注册
+ ///
+ [ErrorCodeItemMetadata("注册功能未开启禁止注册")]
+ D1034,
+
+ ///
+ /// 注册方案不存在
+ ///
+ [ErrorCodeItemMetadata("注册方案不存在")]
+ D1035,
+
+ ///
+ /// 角色不存在
+ ///
+ [ErrorCodeItemMetadata("角色不存在")]
+ D1036,
+
+ ///
+ /// 禁止注册超级管理员和系统管理员
+ ///
+ [ErrorCodeItemMetadata("禁止注册超级管理员和系统管理员")]
+ D1037,
+
+ ///
+ /// 禁止越权操作系统账户
+ ///
+ [ErrorCodeItemMetadata("禁止越权操作系统账户")]
+ D1038,
+
+ ///
+ /// 父机构不存在
+ ///
+ [ErrorCodeItemMetadata("父机构不存在")]
+ D2000,
+
+ ///
+ /// 当前机构Id不能与父机构Id相同
+ ///
+ [ErrorCodeItemMetadata("当前机构Id不能与父机构Id相同")]
+ D2001,
+
+ ///
+ /// 已有相同组织机构,编码或名称相同
+ ///
+ [ErrorCodeItemMetadata("已有相同组织机构,编码或名称相同")]
+ D2002,
+
+ ///
+ /// 没有权限操作机构
+ ///
+ [ErrorCodeItemMetadata("没有权限操作机构")]
+ D2003,
+
+ ///
+ /// 该机构下有用户禁止删除
+ ///
+ [ErrorCodeItemMetadata("该机构下有用户禁止删除")]
+ D2004,
+
+ ///
+ /// 附属机构下有用户禁止删除
+ ///
+ [ErrorCodeItemMetadata("附属机构下有用户禁止删除")]
+ D2005,
+
+ ///
+ /// 只能增加下级机构
+ ///
+ [ErrorCodeItemMetadata("只能增加下级机构")]
+ D2006,
+
+ ///
+ /// 下级机构下有用户禁止删除
+ ///
+ [ErrorCodeItemMetadata("下级机构下有用户禁止删除")]
+ D2007,
+
+ ///
+ /// 系统默认机构禁止删除
+ ///
+ [ErrorCodeItemMetadata("系统默认机构禁止删除")]
+ D2008,
+
+ ///
+ /// 禁止增加根节点机构
+ ///
+ [ErrorCodeItemMetadata("禁止增加根节点机构")]
+ D2009,
+
+ ///
+ /// 此机构下存在注册方案禁止删除
+ ///
+ [ErrorCodeItemMetadata("此机构下存在注册方案禁止删除")]
+ D2010,
+
+ ///
+ /// 机构不存在
+ ///
+ [ErrorCodeItemMetadata("机构不存在")]
+ D2011,
+
+ ///
+ /// 系统默认机构禁止修改
+ ///
+ [ErrorCodeItemMetadata("系统默认机构禁止修改")]
+ D2012,
+
+ ///
+ /// 字典类型不存在
+ ///
+ [ErrorCodeItemMetadata("字典类型不存在")]
+ D3000,
+
+ ///
+ /// 字典类型已存在
+ ///
+ [ErrorCodeItemMetadata("字典类型已存在,名称或编码重复")]
+ D3001,
+
+ ///
+ /// 字典类型下面有字典值禁止删除
+ ///
+ [ErrorCodeItemMetadata("字典类型下面有字典值禁止删除")]
+ D3002,
+
+ ///
+ /// 字典值已存在
+ ///
+ [ErrorCodeItemMetadata("字典值已存在")]
+ D3003,
+
+ ///
+ /// 字典值不存在
+ ///
+ [ErrorCodeItemMetadata("字典值不存在")]
+ D3004,
+
+ ///
+ /// 字典状态错误
+ ///
+ [ErrorCodeItemMetadata("字典状态错误")]
+ D3005,
+
+ ///
+ /// 字典编码不能以Enum结尾
+ ///
+ [ErrorCodeItemMetadata("字典编码不能以Enum结尾")]
+ D3006,
+
+ ///
+ /// 禁止修改枚举类型的字典编码
+ ///
+ [ErrorCodeItemMetadata("禁止修改枚举类型的字典编码")]
+ D3007,
+
+ ///
+ /// 禁止迁移枚举字典
+ ///
+ [ErrorCodeItemMetadata("禁止迁移枚举字典")]
+ D3008,
+
+ ///
+ /// 字典已在该租户禁止迁移
+ ///
+ [ErrorCodeItemMetadata("字典已在该租户禁止迁移")]
+ D3009,
+
+ ///
+ /// 非超管用户禁止操作系统字典
+ ///
+ [ErrorCodeItemMetadata("非超管用户禁止操作系统字典")]
+ D3010,
+
+ ///
+ /// 获取字典值集合入参有误
+ ///
+ [ErrorCodeItemMetadata("获取字典值集合入参有误")]
+ D3011,
+
+ ///
+ /// 禁止修改租户字典状态
+ ///
+ [ErrorCodeItemMetadata("禁止修改租户字典状态")]
+ D3012,
+
+ ///
+ /// 菜单已存在
+ ///
+ [ErrorCodeItemMetadata("菜单已存在")]
+ D4000,
+
+ ///
+ /// 路由地址为空
+ ///
+ [ErrorCodeItemMetadata("路由地址为空")]
+ D4001,
+
+ ///
+ /// 打开方式为空
+ ///
+ [ErrorCodeItemMetadata("打开方式为空")]
+ D4002,
+
+ ///
+ /// 权限标识格式为空
+ ///
+ [ErrorCodeItemMetadata("权限标识格式为空")]
+ D4003,
+
+ ///
+ /// 权限标识格式错误
+ ///
+ [ErrorCodeItemMetadata("权限标识格式错误 如xxx:xxx")]
+ D4004,
+
+ ///
+ /// 权限不存在
+ ///
+ [ErrorCodeItemMetadata("权限不存在")]
+ D4005,
+
+ ///
+ /// 父级菜单不能为当前节点,请重新选择父级菜单
+ ///
+ [ErrorCodeItemMetadata("父级菜单不能为当前节点,请重新选择父级菜单")]
+ D4006,
+
+ ///
+ /// 不能移动根节点
+ ///
+ [ErrorCodeItemMetadata("不能移动根节点")]
+ D4007,
+
+ ///
+ /// 禁止本节点与父节点相同
+ ///
+ [ErrorCodeItemMetadata("禁止本节点与父节点相同")]
+ D4008,
+
+ ///
+ /// 路由名称重复
+ ///
+ [ErrorCodeItemMetadata("路由名称重复")]
+ D4009,
+
+ ///
+ /// 父节点不能为按钮类型
+ ///
+ [ErrorCodeItemMetadata("父节点不能为按钮类型")]
+ D4010,
+
+ ///
+ /// 租户不能为空
+ ///
+ [ErrorCodeItemMetadata("租户不能为空")]
+ D4011,
+
+ ///
+ /// 系统菜单禁止修改
+ ///
+ [ErrorCodeItemMetadata("系统菜单禁止修改")]
+ D4012,
+
+ ///
+ /// 系统菜单禁止删除
+ ///
+ [ErrorCodeItemMetadata("系统菜单禁止删除")]
+ D4013,
+
+ ///
+ /// 已存在同名或同编码应用
+ ///
+ [ErrorCodeItemMetadata("已存在同名或同编码应用")]
+ D5000,
+
+ ///
+ /// 默认激活系统只能有一个
+ ///
+ [ErrorCodeItemMetadata("默认激活系统只能有一个")]
+ D5001,
+
+ ///
+ /// 该应用下有菜单禁止删除
+ ///
+ [ErrorCodeItemMetadata("该应用下有菜单禁止删除")]
+ D5002,
+
+ ///
+ /// 已存在同名或同编码应用
+ ///
+ [ErrorCodeItemMetadata("已存在同名或同编码应用")]
+ D5003,
+
+ ///
+ /// 已存在同名或同编码职位
+ ///
+ [ErrorCodeItemMetadata("已存在同名或同编码职位")]
+ D6000,
+
+ ///
+ /// 该职位下有用户禁止删除
+ ///
+ [ErrorCodeItemMetadata("该职位下有用户禁止删除")]
+ D6001,
+
+ ///
+ /// 无权修改本职位
+ ///
+ [ErrorCodeItemMetadata("无权修改本职位")]
+ D6002,
+
+ ///
+ /// 职位不存在
+ ///
+ [ErrorCodeItemMetadata("职位不存在")]
+ D6003,
+
+ ///
+ /// 此职位下存在注册方案禁止删除
+ ///
+ [ErrorCodeItemMetadata("此职位下存在注册方案禁止删除")]
+ D6004,
+
+ ///
+ /// 通知公告状态错误
+ ///
+ [ErrorCodeItemMetadata("通知公告状态错误")]
+ D7000,
+
+ ///
+ /// 通知公告删除失败
+ ///
+ [ErrorCodeItemMetadata("通知公告删除失败")]
+ D7001,
+
+ ///
+ /// 通知公告编辑失败
+ ///
+ [ErrorCodeItemMetadata("通知公告编辑失败,类型必须为草稿")]
+ D7002,
+
+ ///
+ /// 通知公告操作失败,非发布者不能进行操作
+ ///
+ [ErrorCodeItemMetadata("通知公告操作失败,非发布者不能进行操作")]
+ D7003,
+
+ ///
+ /// 文件不存在
+ ///
+ [ErrorCodeItemMetadata("文件不存在")]
+ D8000,
+
+ ///
+ /// 不允许的文件类型
+ ///
+ [ErrorCodeItemMetadata("不允许的文件类型")]
+ D8001,
+
+ ///
+ /// 文件超过允许大小
+ ///
+ [ErrorCodeItemMetadata("文件超过允许大小")]
+ D8002,
+
+ ///
+ /// 文件后缀错误
+ ///
+ [ErrorCodeItemMetadata("文件后缀错误")]
+ D8003,
+
+ ///
+ /// 文件已存在
+ ///
+ [ErrorCodeItemMetadata("文件已存在")]
+ D8004,
+
+ ///
+ /// 无效的文件名
+ ///
+ [ErrorCodeItemMetadata("无效的文件名")]
+ D8005,
+
+ ///
+ /// 已存在同名或同编码参数配置
+ ///
+ [ErrorCodeItemMetadata("已存在同名或同编码参数配置")]
+ D9000,
+
+ ///
+ /// 禁止删除系统参数
+ ///
+ [ErrorCodeItemMetadata("禁止删除系统参数")]
+ D9001,
+
+ ///
+ /// 已存在同名任务调度
+ ///
+ [ErrorCodeItemMetadata("已存在同名任务调度")]
+ D1100,
+
+ ///
+ /// 任务调度不存在
+ ///
+ [ErrorCodeItemMetadata("任务调度不存在")]
+ D1101,
+
+ ///
+ /// 演示环境禁止修改数据
+ ///
+ [ErrorCodeItemMetadata("演示环境禁止修改数据")]
+ D1200,
+
+ ///
+ /// 已存在同名的租户
+ ///
+ [ErrorCodeItemMetadata("已存在同名的租户")]
+ D1300,
+
+ ///
+ /// 已存在同名的租户管理员
+ ///
+ [ErrorCodeItemMetadata("已存在同名的租户管理员")]
+ D1301,
+
+ ///
+ /// 租户从库配置错误
+ ///
+ [ErrorCodeItemMetadata("租户从库配置错误")]
+ D1302,
+
+ ///
+ /// 已存在同名的租户域名
+ ///
+ [ErrorCodeItemMetadata("已存在同名的租户域名")]
+ D1303,
+
+ ///
+ /// 授权菜单存在重复项
+ ///
+ [ErrorCodeItemMetadata("授权菜单存在重复项")]
+ D1304,
+
+ ///
+ /// 该表代码模板已经生成过
+ ///
+ [ErrorCodeItemMetadata("该表代码模板已经生成过")]
+ D1400,
+
+ ///
+ /// 数据库配置不存在
+ ///
+ [ErrorCodeItemMetadata("数据库配置不存在")]
+ D1401,
+
+ ///
+ /// 该类型不存在
+ ///
+ [ErrorCodeItemMetadata("该类型不存在")]
+ D1501,
+
+ ///
+ /// 该字段不存在
+ ///
+ [ErrorCodeItemMetadata("该字段不存在")]
+ D1502,
+
+ ///
+ /// 该类型不是枚举类型
+ ///
+ [ErrorCodeItemMetadata("该类型不是枚举类型")]
+ D1503,
+
+ ///
+ /// 该实体不存在
+ ///
+ [ErrorCodeItemMetadata("该实体不存在")]
+ D1504,
+
+ ///
+ /// 父菜单不存在
+ ///
+ [ErrorCodeItemMetadata("父菜单不存在")]
+ D1505,
+
+ ///
+ /// 父资源不存在
+ ///
+ [ErrorCodeItemMetadata("父资源不存在")]
+ D1600,
+
+ ///
+ /// 当前资源Id不能与父资源Id相同
+ ///
+ [ErrorCodeItemMetadata("当前资源Id不能与父资源Id相同")]
+ D1601,
+
+ ///
+ /// 已有相同编码或名称
+ ///
+ [ErrorCodeItemMetadata("已有相同编码或名称")]
+ D1602,
+
+ ///
+ /// 脚本代码不能为空
+ ///
+ [ErrorCodeItemMetadata("脚本代码不能为空")]
+ D1701,
+
+ ///
+ /// 脚本代码中的作业类,需要定义 [JobDetail] 特性
+ ///
+ [ErrorCodeItemMetadata("脚本代码中的作业类,需要定义 [JobDetail] 特性")]
+ D1702,
+
+ ///
+ /// 作业编号需要与脚本代码中的作业类 [JobDetail('jobId')] 一致
+ ///
+ [ErrorCodeItemMetadata("作业编号需要与脚本代码中的作业类 [JobDetail('jobId')] 一致")]
+ D1703,
+
+ ///
+ /// 禁止修改作业编号
+ ///
+ [ErrorCodeItemMetadata("禁止修改作业编号")]
+ D1704,
+
+ ///
+ /// 执行作业失败
+ ///
+ [ErrorCodeItemMetadata("执行作业失败")]
+ D1705,
+
+ ///
+ /// 已存在同名打印模板
+ ///
+ [ErrorCodeItemMetadata("已存在同名打印模板")]
+ D1800,
+
+ ///
+ /// 已存在同名功能或同名程序及插件
+ ///
+ [ErrorCodeItemMetadata("已存在同名功能或同名程序及插件")]
+ D1900,
+
+ ///
+ /// 注册方案名称已存在
+ ///
+ [ErrorCodeItemMetadata("注册方案名称已存在")]
+ D2101,
+
+ ///
+ /// 已存在同名模板
+ ///
+ [ErrorCodeItemMetadata("已存在同名模板")]
+ T1000,
+
+ ///
+ /// 已存在相同编码模板
+ ///
+ [ErrorCodeItemMetadata("已存在相同编码模板")]
+ T1001,
+
+ ///
+ /// 禁止删除存在关联租户的应用
+ ///
+ [ErrorCodeItemMetadata("禁止删除存在关联租户的应用")]
+ A1001,
+
+ ///
+ /// 禁止删除存在关联菜单的应用
+ ///
+ [ErrorCodeItemMetadata("禁止删除存在关联菜单的应用")]
+ A1002,
+
+ ///
+ /// 找不到系统应用
+ ///
+ [ErrorCodeItemMetadata("找不到系统应用")]
+ A1000,
+
+ ///
+ /// 已存在同名或同编码项目
+ ///
+ [ErrorCodeItemMetadata("已存在同名或同编码项目")]
+ xg1000,
+
+ ///
+ /// 已存在相同证件号码人员
+ ///
+ [ErrorCodeItemMetadata("已存在相同证件号码人员")]
+ xg1001,
+
+ ///
+ /// 检测数据不存在
+ ///
+ [ErrorCodeItemMetadata("检测数据不存在")]
+ xg1002,
+
+ ///
+ /// 请添加数据列
+ ///
+ [ErrorCodeItemMetadata("请添加数据列")]
+ db1000,
+
+ ///
+ /// 数据表不存在
+ ///
+ [ErrorCodeItemMetadata("数据表不存在")]
+ db1001,
+
+ ///
+ /// 数据表不存在
+ ///
+ [ErrorCodeItemMetadata("不允许添加相同字段名")]
+ db1002,
+
+ ///
+ /// 实体文件不存在或匹配不到。如果是刚刚生成的实体,请重启服务后再试
+ ///
+ [ErrorCodeItemMetadata("实体文件不存在或匹配不到。如果是刚刚生成的实体,请重启服务后再试")]
+ db1003,
+
+ ///
+ /// 父节点不存在
+ ///
+ [ErrorCodeItemMetadata("父节点不存在")]
+ R2000,
+
+ ///
+ /// 当前节点Id不能与父节点Id相同
+ ///
+ [ErrorCodeItemMetadata("当前节点Id不能与父节点Id相同")]
+ R2001,
+
+ ///
+ /// 已有相同编码或名称
+ ///
+ [ErrorCodeItemMetadata("已有相同编码或名称")]
+ R2002,
+
+ ///
+ /// 行政区代码只能为6、9或12位
+ ///
+ [ErrorCodeItemMetadata("行政区代码只能为6、9或12位")]
+ R2003,
+
+ ///
+ /// 父节点不能为自己的子节点
+ ///
+ [ErrorCodeItemMetadata("父节点不能为自己的子节点")]
+ R2004,
+
+ ///
+ /// 同步国家统计局数据异常,请稍后重试
+ ///
+ [ErrorCodeItemMetadata("同步国家统计局数据异常,请稍后重试")]
+ R2005,
+
+ ///
+ /// 默认租户状态禁止修改
+ ///
+ [ErrorCodeItemMetadata("默认租户状态禁止修改")]
+ Z1001,
+
+ ///
+ /// 禁止创建此类型的数据库
+ ///
+ [ErrorCodeItemMetadata("禁止创建此类型的数据库")]
+ Z1002,
+
+ ///
+ /// 租户不存在或已禁用
+ ///
+ [ErrorCodeItemMetadata("租户不存在或已禁用")]
+ Z1003,
+
+ ///
+ /// 租户库连接不能为空
+ ///
+ [ErrorCodeItemMetadata("租户库连接不能为空")]
+ Z1004,
+
+ ///
+ /// 身份标识已存在
+ ///
+ [ErrorCodeItemMetadata("身份标识已存在")]
+ O1000,
+
+ ///
+ /// 禁止非超级管理员操作
+ ///
+ [ErrorCodeItemMetadata("禁止非超级管理员操作")]
+ SA001
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/EsClientTypeEnum.cs b/Admin.NET.Core/Enum/EsClientTypeEnum.cs
new file mode 100644
index 0000000..14d55e7
--- /dev/null
+++ b/Admin.NET.Core/Enum/EsClientTypeEnum.cs
@@ -0,0 +1,23 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// ES客户端类型(标识不同场景)
+///
+public enum EsClientTypeEnum
+{
+ ///
+ /// 日志专用
+ ///
+ Logging,
+
+ ///
+ /// 业务数据
+ ///
+ Business
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/FilterLogicEnum.cs b/Admin.NET.Core/Enum/FilterLogicEnum.cs
new file mode 100644
index 0000000..5e898f2
--- /dev/null
+++ b/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.Core/Enum/FilterOperatorEnum.cs b/Admin.NET.Core/Enum/FilterOperatorEnum.cs
new file mode 100644
index 0000000..0de28dd
--- /dev/null
+++ b/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.Core/Enum/FinishStatusEnum.cs b/Admin.NET.Core/Enum/FinishStatusEnum.cs
new file mode 100644
index 0000000..90e188f
--- /dev/null
+++ b/Admin.NET.Core/Enum/FinishStatusEnum.cs
@@ -0,0 +1,26 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 完成状态枚举
+///
+[Description("完成状态枚举")]
+public enum FinishStatusEnum
+{
+ ///
+ /// 已完成
+ ///
+ [Description("已完成"), Theme("success")]
+ Finish = 1,
+
+ ///
+ /// 未完成
+ ///
+ [Description("未完成"), Theme("danger")]
+ UnFinish = 0,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/GenderEnum.cs b/Admin.NET.Core/Enum/GenderEnum.cs
new file mode 100644
index 0000000..ceea591
--- /dev/null
+++ b/Admin.NET.Core/Enum/GenderEnum.cs
@@ -0,0 +1,38 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 性别枚举(GB/T 2261.1-2003)
+///
+[Description("性别枚举")]
+public enum GenderEnum
+{
+ ///
+ /// 未知
+ ///
+ [Description("未知"), Theme("info")]
+ Unknown = 0,
+
+ ///
+ /// 男性
+ ///
+ [Description("男性"), Theme("success")]
+ Male = 1,
+
+ ///
+ /// 女性
+ ///
+ [Description("女性"), Theme("danger")]
+ Female = 2,
+
+ /////
+ ///// 未说明的性别
+ /////
+ //[Description("未说明的性别"), Theme("warning")]
+ //Unspecified = 9
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/HttpMethodEnum.cs b/Admin.NET.Core/Enum/HttpMethodEnum.cs
new file mode 100644
index 0000000..f930893
--- /dev/null
+++ b/Admin.NET.Core/Enum/HttpMethodEnum.cs
@@ -0,0 +1,68 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// HTTP请求方法枚举
+///
+[Description("HTTP请求方法枚举")]
+public enum HttpMethodEnum
+{
+ ///
+ /// HTTP "GET" method.
+ ///
+ [Description("HTTP \"GET\" method.")]
+ Get,
+
+ ///
+ /// HTTP "POST" method.
+ ///
+ [Description("HTTP \"POST\" method.")]
+ Post,
+
+ ///
+ /// HTTP "PUT" method.
+ ///
+ [Description(" HTTP \"PUT\" method.")]
+ Put,
+
+ ///
+ /// HTTP "DELETE" method.
+ ///
+ [Description("HTTP \"DELETE\" method.")]
+ Delete,
+
+ ///
+ /// HTTP "PATCH" method.
+ ///
+ [Description("HTTP \"PATCH\" method. ")]
+ Patch,
+
+ ///
+ /// HTTP "HEAD" method.
+ ///
+ [Description("HTTP \"HEAD\" method.")]
+ Head,
+
+ ///
+ /// HTTP "OPTIONS" method.
+ ///
+ [Description("HTTP \"OPTIONS\" method.")]
+ Options,
+
+ ///
+ /// HTTP "TRACE" method.
+ ///
+ [Description(" HTTP \"TRACE\" method.")]
+ Trace,
+
+ ///
+ /// HTTP "CONNECT" method.
+ ///
+ [Description("HTTP \"CONNECT\" method.")]
+ Connect
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/JobCreateTypeEnum.cs b/Admin.NET.Core/Enum/JobCreateTypeEnum.cs
new file mode 100644
index 0000000..2d90b69
--- /dev/null
+++ b/Admin.NET.Core/Enum/JobCreateTypeEnum.cs
@@ -0,0 +1,32 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 作业创建类型枚举
+///
+[Description("作业创建类型枚举")]
+public enum JobCreateTypeEnum
+{
+ ///
+ /// 内置
+ ///
+ [Description("内置"), Theme("info")]
+ BuiltIn = 0,
+
+ ///
+ /// 脚本
+ ///
+ [Description("脚本")]
+ Script = 1,
+
+ ///
+ /// HTTP请求
+ ///
+ [Description("HTTP请求")]
+ Http = 2,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/JobStatusEnum.cs b/Admin.NET.Core/Enum/JobStatusEnum.cs
new file mode 100644
index 0000000..b06c65c
--- /dev/null
+++ b/Admin.NET.Core/Enum/JobStatusEnum.cs
@@ -0,0 +1,38 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 岗位状态枚举
+///
+[Description("岗位状态枚举")]
+public enum JobStatusEnum
+{
+ ///
+ /// 在职
+ ///
+ [Description("在职")]
+ On = 1,
+
+ ///
+ /// 离职
+ ///
+ [Description("离职")]
+ Off = 2,
+
+ ///
+ /// 请假
+ ///
+ [Description("请假")]
+ Leave = 3,
+
+ ///
+ /// 其他
+ ///
+ [Description("其他")]
+ Other = 4,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/LoginModeEnum.cs b/Admin.NET.Core/Enum/LoginModeEnum.cs
new file mode 100644
index 0000000..55e8ddb
--- /dev/null
+++ b/Admin.NET.Core/Enum/LoginModeEnum.cs
@@ -0,0 +1,26 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 登录模式枚举
+///
+[Description("登录模式枚举")]
+public enum LoginModeEnum
+{
+ ///
+ /// PC模式
+ ///
+ [Description("PC模式")]
+ PC = 1,
+
+ ///
+ /// APP
+ ///
+ [Description("APP")]
+ APP = 2
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/LoginTypeEnum.cs b/Admin.NET.Core/Enum/LoginTypeEnum.cs
new file mode 100644
index 0000000..9fa0950
--- /dev/null
+++ b/Admin.NET.Core/Enum/LoginTypeEnum.cs
@@ -0,0 +1,32 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 登录类型枚举
+///
+[Description("登录类型枚举")]
+public enum LoginTypeEnum
+{
+ ///
+ /// PC登录
+ ///
+ [Description("PC登录")]
+ Login = 1,
+
+ ///
+ /// PC退出
+ ///
+ [Description("PC退出")]
+ Logout = 2,
+
+ ///
+ /// PC注册
+ ///
+ [Description("PC注册")]
+ Register = 3
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/MaritalStatusEnum.cs b/Admin.NET.Core/Enum/MaritalStatusEnum.cs
new file mode 100644
index 0000000..b3787b2
--- /dev/null
+++ b/Admin.NET.Core/Enum/MaritalStatusEnum.cs
@@ -0,0 +1,50 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 婚姻状况枚举
+///
+[Description("婚姻状况枚举")]
+public enum MaritalStatusEnum
+{
+ ///
+ /// 未婚
+ ///
+ [Description("未婚")]
+ UnMarried = 1,
+
+ ///
+ /// 已婚
+ ///
+ [Description("已婚")]
+ Married = 2,
+
+ ///
+ /// 离异
+ ///
+ [Description("离异")]
+ Divorce = 3,
+
+ ///
+ /// 再婚
+ ///
+ [Description("再婚")]
+ Remarry = 4,
+
+ ///
+ /// 丧偶
+ ///
+ [Description("丧偶")]
+ Widowed = 5,
+
+ ///
+ /// 未知
+ ///
+ [Description("未知")]
+ None = 6,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/MenuTypeEnum.cs b/Admin.NET.Core/Enum/MenuTypeEnum.cs
new file mode 100644
index 0000000..0912635
--- /dev/null
+++ b/Admin.NET.Core/Enum/MenuTypeEnum.cs
@@ -0,0 +1,33 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统菜单类型枚举
+///
+[Description("系统菜单类型枚举")]
+public enum MenuTypeEnum
+{
+ ///
+ /// 目录
+ ///
+
+ [Description("目录"), Theme("warning")]
+ Dir = 1,
+
+ ///
+ /// 菜单
+ ///
+ [Description("菜单")]
+ Menu = 2,
+
+ ///
+ /// 按钮
+ ///
+ [Description("按钮"), Theme("info")]
+ Btn = 3
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/MessageTypeEnum.cs b/Admin.NET.Core/Enum/MessageTypeEnum.cs
new file mode 100644
index 0000000..1ac3bfd
--- /dev/null
+++ b/Admin.NET.Core/Enum/MessageTypeEnum.cs
@@ -0,0 +1,38 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 消息类型枚举
+///
+[Description("消息类型枚举")]
+public enum MessageTypeEnum
+{
+ ///
+ /// 普通信息
+ ///
+ [Description("消息"), Theme("info")]
+ Info = 0,
+
+ ///
+ /// 成功提示
+ ///
+ [Description("成功"), Theme("success")]
+ Success = 1,
+
+ ///
+ /// 警告提示
+ ///
+ [Description("警告"), Theme("warning")]
+ Warning = 2,
+
+ ///
+ /// 错误提示
+ ///
+ [Description("错误"), Theme("danger")]
+ Error = 3
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/NationEnum.cs b/Admin.NET.Core/Enum/NationEnum.cs
new file mode 100644
index 0000000..25dd2ed
--- /dev/null
+++ b/Admin.NET.Core/Enum/NationEnum.cs
@@ -0,0 +1,350 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 民族枚举
+///
+[Description("民族枚举")]
+public enum NationEnum
+{
+ ///
+ /// 汉族
+ ///
+ [Description("汉族")]
+ HanZu = 1,
+
+ ///
+ /// 壮族
+ ///
+ [Description("壮族")]
+ ZhuangZu = 2,
+
+ ///
+ /// 满族
+ ///
+ [Description("满族")]
+ ManZu = 3,
+
+ ///
+ /// 回族
+ ///
+ [Description("回族")]
+ HuiZu = 4,
+
+ ///
+ /// 苗族
+ ///
+ [Description("苗族")]
+ MiaoZu = 5,
+
+ ///
+ /// 维吾尔族
+ ///
+ [Description("维吾尔族")]
+ WeiWuErZu = 6,
+
+ ///
+ /// 土家族
+ ///
+ [Description("土家族")]
+ TuJiaZu = 7,
+
+ ///
+ /// 彝族
+ ///
+ [Description("彝族")]
+ YiZu = 8,
+
+ ///
+ /// 蒙古族
+ ///
+ [Description("蒙古族")]
+ MengGuZu = 9,
+
+ ///
+ /// 藏族
+ ///
+ [Description("藏族")]
+ ZangZu = 10,
+
+ ///
+ /// 布依族
+ ///
+ [Description("布依族")]
+ BuYiZu = 11,
+
+ ///
+ /// 侗族
+ ///
+ [Description("侗族")]
+ DongZu = 12,
+
+ ///
+ /// 瑶族
+ ///
+ [Description("瑶族")]
+ YaoZu = 13,
+
+ ///
+ /// 朝鲜族
+ ///
+ [Description("朝鲜族")]
+ ChaoXianZu = 14,
+
+ ///
+ /// 白族
+ ///
+ [Description("白族")]
+ BaiZu = 15,
+
+ ///
+ /// 哈尼族
+ ///
+ [Description("哈尼族")]
+ HaNiZu = 16,
+
+ ///
+ /// 哈萨克族
+ ///
+ [Description("哈萨克族")]
+ HaSaKeZu = 17,
+
+ ///
+ /// 黎族
+ ///
+ [Description("黎族")]
+ LiZu = 18,
+
+ ///
+ /// 傣族
+ ///
+ [Description("傣族")]
+ DaiZu = 19,
+
+ ///
+ /// 畲族
+ ///
+ [Description("畲族")]
+ SheZu = 20,
+
+ ///
+ /// 傈僳族
+ ///
+ [Description("傈僳族")]
+ LiSuZu = 21,
+
+ ///
+ /// 仡佬族
+ ///
+ [Description("仡佬族")]
+ GeLaoZu = 22,
+
+ ///
+ /// 拉祜族
+ ///
+ [Description("拉祜族")]
+ LaHuZu = 23,
+
+ ///
+ /// 东乡族
+ ///
+ [Description("东乡族")]
+ DongXiangZu = 24,
+
+ ///
+ /// 纳西族
+ ///
+ [Description("纳西族")]
+ NaXiZu = 25,
+
+ ///
+ /// 景颇族
+ ///
+ [Description("景颇族")]
+ JingPoZu = 26,
+
+ ///
+ /// 柯尔克孜族
+ ///
+ [Description("柯尔克孜族")]
+ KeErKeZiZu = 27,
+
+ ///
+ /// 土族
+ ///
+ [Description("土族")]
+ TuZu = 28,
+
+ ///
+ /// 达斡尔族
+ ///
+ [Description("达斡尔族")]
+ DaWoErZu = 29,
+
+ ///
+ /// 仫佬族
+ ///
+ [Description("仫佬族")]
+ MuLaoZu = 30,
+
+ ///
+ /// 羌族
+ ///
+ [Description("羌族")]
+ QiangZu = 31,
+
+ ///
+ /// 布朗族
+ ///
+ [Description("布朗族")]
+ BuLangZu = 32,
+
+ ///
+ /// 撒拉族
+ ///
+ [Description("撒拉族")]
+ SaLaZu = 33,
+
+ ///
+ /// 毛南族
+ ///
+ [Description("毛南族")]
+ MaoNanZu = 34,
+
+ ///
+ /// 仡族
+ ///
+ [Description("仡族")]
+ GeZu = 35,
+
+ ///
+ /// 锡伯族
+ ///
+ [Description("锡伯族")]
+ XiBoZu = 36,
+
+ ///
+ /// 阿昌族
+ ///
+ [Description("阿昌族")]
+ AChangZu = 37,
+
+ ///
+ /// 普米族
+ ///
+ [Description("普米族")]
+ PuMiZu = 38,
+
+ ///
+ /// 塔吉克族
+ ///
+ [Description("塔吉克族")]
+ TaJiKeZu = 39,
+
+ ///
+ /// 怒族
+ ///
+ [Description("怒族")]
+ NuZu = 40,
+
+ ///
+ /// 乌孜别克族
+ ///
+ [Description("乌孜别克族")]
+ WuZiBieKeZu = 41,
+
+ ///
+ /// 俄罗斯族
+ ///
+ [Description("俄罗斯族")]
+ ELuoSiZu = 42,
+
+ ///
+ /// 鄂温克族
+ ///
+ [Description("鄂温克族")]
+ EwenKeZu = 43,
+
+ ///
+ /// 德昂族
+ ///
+ [Description("德昂族")]
+ DeAngZu = 44,
+
+ ///
+ /// 保安族
+ ///
+ [Description("保安族")]
+ BaoAnZu = 45,
+
+ ///
+ /// 裕固族
+ ///
+ [Description("裕固族")]
+ YuGuZu = 46,
+
+ ///
+ /// 京族
+ ///
+ [Description("京族")]
+ JingZu = 47,
+
+ ///
+ /// 塔塔尔族
+ ///
+ [Description("塔塔尔族")]
+ TaTaErZu = 48,
+
+ ///
+ /// 独龙族
+ ///
+ [Description("独龙族")]
+ DuLongZu = 49,
+
+ ///
+ /// 鄂伦春族
+ ///
+ [Description("鄂伦春族")]
+ ELunChunZu = 50,
+
+ ///
+ /// 赫哲族
+ ///
+ [Description("赫哲族")]
+ HeZheZu = 51,
+
+ ///
+ /// 门巴族
+ ///
+ [Description("门巴族")]
+ MenBaZu = 52,
+
+ ///
+ /// 珞巴族
+ ///
+ [Description("珞巴族")]
+ LuoBaZu = 53,
+
+ ///
+ /// 高山族
+ ///
+ [Description("高山族")]
+ GaoShanZu = 54,
+
+ ///
+ /// 佤族
+ ///
+ [Description("佤族")]
+ WaZu = 55,
+
+ ///
+ /// 基诺族
+ ///
+ [Description("基诺族")]
+ JiNuoZu = 56
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/NoticeStatusEnum.cs b/Admin.NET.Core/Enum/NoticeStatusEnum.cs
new file mode 100644
index 0000000..0bd68e8
--- /dev/null
+++ b/Admin.NET.Core/Enum/NoticeStatusEnum.cs
@@ -0,0 +1,38 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 通知公告状态枚举
+///
+[Description("通知公告状态枚举")]
+public enum NoticeStatusEnum
+{
+ ///
+ /// 草稿
+ ///
+ [Description("草稿"), Theme("info")]
+ DRAFT = 0,
+
+ ///
+ /// 发布
+ ///
+ [Description("发布")]
+ PUBLIC = 1,
+
+ ///
+ /// 撤回
+ ///
+ [Description("撤回")]
+ CANCEL = 2,
+
+ ///
+ /// 删除
+ ///
+ [Description("删除")]
+ DELETED = 3
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/NoticeTypeEnum.cs b/Admin.NET.Core/Enum/NoticeTypeEnum.cs
new file mode 100644
index 0000000..387bf29
--- /dev/null
+++ b/Admin.NET.Core/Enum/NoticeTypeEnum.cs
@@ -0,0 +1,26 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 通知公告状类型枚举
+///
+[Description("通知公告状类型枚举")]
+public enum NoticeTypeEnum
+{
+ ///
+ /// 通知
+ ///
+ [Description("通知")]
+ NOTICE = 1,
+
+ ///
+ /// 公告
+ ///
+ [Description("公告")]
+ ANNOUNCEMENT = 2,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/NoticeUserStatusEnum.cs b/Admin.NET.Core/Enum/NoticeUserStatusEnum.cs
new file mode 100644
index 0000000..a22fc26
--- /dev/null
+++ b/Admin.NET.Core/Enum/NoticeUserStatusEnum.cs
@@ -0,0 +1,26 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 通知公告用户状态枚举
+///
+[Description("通知公告用户状态枚举")]
+public enum NoticeUserStatusEnum
+{
+ ///
+ /// 未读
+ ///
+ [Description("未读")]
+ UNREAD = 0,
+
+ ///
+ /// 已读
+ ///
+ [Description("已读"), Theme("info")]
+ READ = 1
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/PlatformTypeEnum.cs b/Admin.NET.Core/Enum/PlatformTypeEnum.cs
new file mode 100644
index 0000000..38f985b
--- /dev/null
+++ b/Admin.NET.Core/Enum/PlatformTypeEnum.cs
@@ -0,0 +1,44 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 平台类型枚举
+///
+[Description("平台类型枚举")]
+public enum PlatformTypeEnum
+{
+ ///
+ /// 微信公众号
+ ///
+ [Description("微信公众号")]
+ 微信公众号 = 1,
+
+ ///
+ /// 微信小程序
+ ///
+ [Description("微信小程序")]
+ 微信小程序 = 2,
+
+ ///
+ /// QQ
+ ///
+ [Description("QQ")]
+ QQ = 3,
+
+ ///
+ /// 支付宝
+ ///
+ [Description("支付宝")]
+ Alipay = 4,
+
+ ///
+ /// Gitee
+ ///
+ [Description("Gitee")]
+ Gitee = 5,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/PrintTypeEnum.cs b/Admin.NET.Core/Enum/PrintTypeEnum.cs
new file mode 100644
index 0000000..422972f
--- /dev/null
+++ b/Admin.NET.Core/Enum/PrintTypeEnum.cs
@@ -0,0 +1,26 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 打印类型枚举
+///
+[Description("打印类型枚举")]
+public enum PrintTypeEnum
+{
+ ///
+ /// 浏览器打印
+ ///
+ [Description("浏览器打印")]
+ Browser = 1,
+
+ ///
+ /// 浏览器打印
+ ///
+ [Description("客户端打印")]
+ Client = 2,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/RequestTypeEnum.cs b/Admin.NET.Core/Enum/RequestTypeEnum.cs
new file mode 100644
index 0000000..f1f4aee
--- /dev/null
+++ b/Admin.NET.Core/Enum/RequestTypeEnum.cs
@@ -0,0 +1,39 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// HTTP请求类型
+///
+[Description("HTTP请求类型")]
+public enum RequestTypeEnum
+{
+ ///
+ /// 执行内部方法
+ ///
+ Run = 0,
+
+ ///
+ /// GET
+ ///
+ Get = 1,
+
+ ///
+ /// POST
+ ///
+ Post = 2,
+
+ ///
+ /// PUT
+ ///
+ Put = 3,
+
+ ///
+ /// DELETE
+ ///
+ Delete = 4
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/StatusEnum.cs b/Admin.NET.Core/Enum/StatusEnum.cs
new file mode 100644
index 0000000..246f6dc
--- /dev/null
+++ b/Admin.NET.Core/Enum/StatusEnum.cs
@@ -0,0 +1,26 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 通用状态枚举
+///
+[Description("通用状态枚举")]
+public enum StatusEnum
+{
+ ///
+ /// 启用
+ ///
+ [Description("启用"), Theme("success")]
+ Enable = 1,
+
+ ///
+ /// 停用
+ ///
+ [Description("停用"), Theme("danger")]
+ Disable = 2,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/SysUserEventTypeEnum.cs b/Admin.NET.Core/Enum/SysUserEventTypeEnum.cs
new file mode 100644
index 0000000..7245626
--- /dev/null
+++ b/Admin.NET.Core/Enum/SysUserEventTypeEnum.cs
@@ -0,0 +1,87 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 事件类型-系统用户操作枚举
+///
+[SuppressSniffer]
+[Description("事件类型-系统用户操作枚举")]
+public enum SysUserEventTypeEnum
+{
+ ///
+ /// 增加用户
+ ///
+ [Description("增加用户")]
+ Add = 111,
+
+ ///
+ /// 更新用户
+ ///
+ [Description("更新用户")]
+ Update = 222,
+
+ ///
+ /// 授权用户角色
+ ///
+ [Description("授权用户角色")]
+ UpdateRole = 333,
+
+ ///
+ /// 删除用户
+ ///
+ [Description("删除用户")]
+ Delete = 444,
+
+ ///
+ /// 设置用户状态
+ ///
+ [Description("设置用户状态")]
+ SetStatus = 555,
+
+ ///
+ /// 修改密码
+ ///
+ [Description("修改密码")]
+ ChangePwd = 666,
+
+ ///
+ /// 重置密码
+ ///
+ [Description("重置密码")]
+ ResetPwd = 777,
+
+ ///
+ /// 解除登录锁定
+ ///
+ [Description("解除登录锁定")]
+ UnlockLogin = 888,
+
+ ///
+ /// 注册用户
+ ///
+ [Description("注册用户")]
+ Register = 999,
+
+ ///
+ /// 用户登录
+ ///
+ [Description("用户登录")]
+ Login = 1000,
+
+ ///
+ /// 用户退出
+ ///
+ [Description("用户退出")]
+ LoginOut = 1001,
+
+ ///
+ /// RefreshToken
+ ///
+ [Description("刷新Token")]
+ RefreshToken = 1002,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/TemplateTypeEnum.cs b/Admin.NET.Core/Enum/TemplateTypeEnum.cs
new file mode 100644
index 0000000..9519a7b
--- /dev/null
+++ b/Admin.NET.Core/Enum/TemplateTypeEnum.cs
@@ -0,0 +1,50 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 消息模板类型枚举
+///
+[Description("消息模板类型枚举")]
+public enum TemplateTypeEnum
+{
+ ///
+ /// 通知公告
+ ///
+ [Description("通知")]
+ Notice = 1,
+
+ ///
+ /// 短信
+ ///
+ [Description("短信")]
+ SMS = 2,
+
+ ///
+ /// 邮件
+ ///
+ [Description("邮件")]
+ Email = 3,
+
+ ///
+ /// 微信
+ ///
+ [Description("微信")]
+ Wechat = 4,
+
+ ///
+ /// 钉钉
+ ///
+ [Description("钉钉")]
+ DingTalk = 5,
+
+ ///
+ /// 企业微信
+ ///
+ [Description("企业微信")]
+ WeChatWork = 7
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/TenantTypeEnum.cs b/Admin.NET.Core/Enum/TenantTypeEnum.cs
new file mode 100644
index 0000000..c9eeb90
--- /dev/null
+++ b/Admin.NET.Core/Enum/TenantTypeEnum.cs
@@ -0,0 +1,26 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 租户类型枚举
+///
+[Description("租户类型枚举")]
+public enum TenantTypeEnum
+{
+ ///
+ /// ID隔离
+ ///
+ [Description("ID隔离")]
+ Id = 0,
+
+ ///
+ /// 库隔离
+ ///
+ [Description("库隔离")]
+ Db = 1,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/WechatReturnCodeEnum.cs b/Admin.NET.Core/Enum/WechatReturnCodeEnum.cs
new file mode 100644
index 0000000..ba30a3e
--- /dev/null
+++ b/Admin.NET.Core/Enum/WechatReturnCodeEnum.cs
@@ -0,0 +1,289 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 微信开发返回码
+///
+[Description("微信开发返回码")]
+public enum WechatReturnCodeEnum
+{
+ SenparcWeixinSDK配置错误 = -99, // 0xFFFFFF9D
+ 系统繁忙此时请开发者稍候再试 = -1, // 0xFFFFFFFF
+ 请求成功 = 0,
+ 工商数据返回_企业已注销 = 101, // 0x00000065
+ 工商数据返回_企业不存在或企业信息未更新 = 102, // 0x00000066
+ 工商数据返回_企业法定代表人姓名不一致 = 103, // 0x00000067
+ 工商数据返回_企业法定代表人身份证号码不一致 = 104, // 0x00000068
+ 法定代表人身份证号码_工商数据未更新_请5_15个工作日之后尝试 = 105, // 0x00000069
+ 工商数据返回_企业信息或法定代表人信息不一致 = 1000, // 0x000003E8
+ 对方不是粉丝 = 10700, // 0x000029CC
+ 发送消息失败_对方关闭了接收消息 = 10703, // 0x000029CF
+ 发送消息失败_48小时内用户未互动 = 10706, // 0x000029D2
+ POST参数非法 = 20002, // 0x00004E22
+ 获取access_token时AppSecret错误或者access_token无效 = 40001, // 0x00009C41
+
+ ///
+ /// 公众号:不合法的凭证类型
+ /// 小程序:暂无生成权限
+ ///
+ 不合法的凭证类型 = 40002, // 0x00009C42
+
+ 不合法的OpenID = 40003, // 0x00009C43
+ 不合法的媒体文件类型 = 40004, // 0x00009C44
+ 不合法的文件类型 = 40005, // 0x00009C45
+ 不合法的文件大小 = 40006, // 0x00009C46
+ 不合法的媒体文件id = 40007, // 0x00009C47
+ 不合法的消息类型_40008 = 40008, // 0x00009C48
+ 不合法的图片文件大小 = 40009, // 0x00009C49
+ 不合法的语音文件大小 = 40010, // 0x00009C4A
+ 不合法的视频文件大小 = 40011, // 0x00009C4B
+ 不合法的缩略图文件大小 = 40012, // 0x00009C4C
+
+ ///
+ /// 微信:不合法的APPID
+ /// 小程序:生成权限被封禁
+ ///
+ 不合法的APPID = 40013, // 0x00009C4D
+
+ 不合法的access_token = 40014, // 0x00009C4E
+ 不合法的菜单类型 = 40015, // 0x00009C4F
+ 不合法的按钮个数1 = 40016, // 0x00009C50
+ 不合法的按钮个数2 = 40017, // 0x00009C51
+ 不合法的按钮名字长度 = 40018, // 0x00009C52
+ 不合法的按钮KEY长度 = 40019, // 0x00009C53
+ 不合法的按钮URL长度 = 40020, // 0x00009C54
+ 不合法的菜单版本号 = 40021, // 0x00009C55
+ 不合法的子菜单级数 = 40022, // 0x00009C56
+ 不合法的子菜单按钮个数 = 40023, // 0x00009C57
+ 不合法的子菜单按钮类型 = 40024, // 0x00009C58
+ 不合法的子菜单按钮名字长度 = 40025, // 0x00009C59
+ 不合法的子菜单按钮KEY长度 = 40026, // 0x00009C5A
+ 不合法的子菜单按钮URL长度 = 40027, // 0x00009C5B
+ 不合法的自定义菜单使用用户 = 40028, // 0x00009C5C
+ 不合法的oauth_code = 40029, // 0x00009C5D
+ 不合法的refresh_token = 40030, // 0x00009C5E
+ 不合法的openid列表 = 40031, // 0x00009C5F
+ 不合法的openid列表长度 = 40032, // 0x00009C60
+ 不合法的请求字符不能包含uxxxx格式的字符 = 40033, // 0x00009C61
+ 不合法的参数 = 40035, // 0x00009C63
+ template_id不正确 = 40037, // 0x00009C65
+ 不合法的请求格式 = 40038, // 0x00009C66
+ 不合法的URL长度 = 40039, // 0x00009C67
+ 不合法的分组id = 40050, // 0x00009C72
+ 分组名字不合法 = 40051, // 0x00009C73
+
+ ///
+ /// 公众号:输入参数有误
+ /// 小程序:参数expire_time填写错误
+ ///
+ 输入参数有误 = 40097, // 0x00009CA1
+
+ appsecret不正确 = 40125, // 0x00009CBD
+ 调用接口的IP地址不在白名单中 = 40164, // 0x00009CE4
+ 参数path填写错误 = 40165, // 0x00009CE5
+ 小程序Appid不存在 = 40166, // 0x00009CE6
+ 参数query填写错误 = 40212, // 0x00009D14
+ 缺少access_token参数 = 41001, // 0x0000A029
+ 缺少appid参数 = 41002, // 0x0000A02A
+ 缺少refresh_token参数 = 41003, // 0x0000A02B
+ 缺少secret参数 = 41004, // 0x0000A02C
+ 缺少多媒体文件数据 = 41005, // 0x0000A02D
+ 缺少media_id参数 = 41006, // 0x0000A02E
+ 缺少子菜单数据 = 41007, // 0x0000A02F
+ 缺少oauth_code = 41008, // 0x0000A030
+ 缺少openid = 41009, // 0x0000A031
+ form_id不正确_或者过期 = 41028, // 0x0000A044
+ form_id已被使用 = 41029, // 0x0000A045
+ page不正确 = 41030, // 0x0000A046
+ access_token超时 = 42001, // 0x0000A411
+ refresh_token超时 = 42002, // 0x0000A412
+ oauth_code超时 = 42003, // 0x0000A413
+ 需要GET请求 = 43001, // 0x0000A7F9
+ 需要POST请求 = 43002, // 0x0000A7FA
+ 需要HTTPS请求 = 43003, // 0x0000A7FB
+ 需要接收者关注 = 43004, // 0x0000A7FC
+ 需要好友关系 = 43005, // 0x0000A7FD
+
+ /// [小程序订阅消息]用户拒绝接受消息,如果用户之前曾经订阅过,则表示用户取消了订阅关系
+ 用户拒绝接受消息 = 43101, // 0x0000A85D
+
+ 没有权限 = 43104, // 0x0000A860
+ 多媒体文件为空 = 44001, // 0x0000ABE1
+ POST的数据包为空 = 44002, // 0x0000ABE2
+ 图文消息内容为空 = 44003, // 0x0000ABE3
+ 文本消息内容为空 = 44004, // 0x0000ABE4
+ 多媒体文件大小超过限制 = 45001, // 0x0000AFC9
+ 消息内容超过限制 = 45002, // 0x0000AFCA
+ 标题字段超过限制 = 45003, // 0x0000AFCB
+ 描述字段超过限制 = 45004, // 0x0000AFCC
+ 链接字段超过限制 = 45005, // 0x0000AFCD
+ 图片链接字段超过限制 = 45006, // 0x0000AFCE
+ 语音播放时间超过限制 = 45007, // 0x0000AFCF
+ 图文消息超过限制 = 45008, // 0x0000AFD0
+ 接口调用超过限制 = 45009, // 0x0000AFD1
+ 创建菜单个数超过限制 = 45010, // 0x0000AFD2
+ 回复时间超过限制 = 45015, // 0x0000AFD7
+ 系统分组不允许修改 = 45016, // 0x0000AFD8
+ 分组名字过长 = 45017, // 0x0000AFD9
+ 分组数量超过上限 = 45018, // 0x0000AFDA
+ 超出响应数量限制 = 45047, // 0x0000AFF7
+ 创建的标签数过多请注意不能超过100个 = 45056, // 0x0000B000
+ 标签名非法请注意不能和其他标签重名 = 45157, // 0x0000B065
+ 标签名长度超过30个字节 = 45158, // 0x0000B066
+ 不存在媒体数据 = 46001, // 0x0000B3B1
+ 不存在的菜单版本 = 46002, // 0x0000B3B2
+ 不存在的菜单数据 = 46003, // 0x0000B3B3
+ 解析JSON_XML内容错误 = 47001, // 0x0000B799
+
+ /// [小程序订阅消息]模板参数不准确,可能为空或者不满足规则,errmsg会提示具体是哪个字段出错
+ 模板参数不准确 = 47003, // 0x0000B79B
+
+ api功能未授权 = 48001, // 0x0000BB81
+ 用户未授权该api = 50001, // 0x0000C351
+ 名称格式不合法 = 53010, // 0x0000CF12
+ 名称检测命中频率限制 = 53011, // 0x0000CF13
+ 禁止使用该名称 = 53012, // 0x0000CF14
+ 公众号_名称与已有公众号名称重复_小程序_该名称与已有小程序名称重复 = 53013, // 0x0000CF15
+ 公众号_公众号已有_名称A_时_需与该帐号相同主体才可申请_名称A_小程序_小程序已有_名称A_时_需与该帐号相同主体才可申请_名称A_ = 53014, // 0x0000CF16
+ 公众号_该名称与已有小程序名称重复_需与该小程序帐号相同主体才可申请_小程序_该名称与已有公众号名称重复_需与该公众号帐号相同主体才可申请 = 53015, // 0x0000CF17
+ 公众号_该名称与已有多个小程序名称重复_暂不支持申请_小程序_该名称与已有多个公众号名称重复_暂不支持申请 = 53016, // 0x0000CF18
+ 公众号_小程序已有_名称A_时_需与该帐号相同主体才可申请_名称A_小程序_公众号已有_名称A_时_需与该帐号相同主体才可申请_名称A = 53017, // 0x0000CF19
+ 名称命中微信号 = 53018, // 0x0000CF1A
+ 名称在保护期内 = 53019, // 0x0000CF1B
+ 法人姓名与微信号不一致 = 61070, // 0x0000EE8E
+ 系统错误system_error = 61450, // 0x0000F00A
+ 参数错误invalid_parameter = 61451, // 0x0000F00B
+ 无效客服账号invalid_kf_account = 61452, // 0x0000F00C
+ 客服帐号已存在kf_account_exsited = 61453, // 0x0000F00D
+
+ ///
+ /// 客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)(invalid kf_acount length)
+ ///
+ 客服帐号名长度超过限制 = 61454, // 0x0000F00E
+
+ ///
+ /// 客服帐号名包含非法字符(仅允许英文+数字)(illegal character in kf_account)
+ ///
+ 客服帐号名包含非法字符 = 61455, // 0x0000F00F
+
+ /// 客服帐号个数超过限制(10个客服账号)(kf_account count exceeded)
+ 客服帐号个数超过限制 = 61456, // 0x0000F010
+
+ 无效头像文件类型invalid_file_type = 61457, // 0x0000F011
+ 日期格式错误 = 61500, // 0x0000F03C
+ 日期范围错误 = 61501, // 0x0000F03D
+ 发送消息失败_该用户已被加入黑名单_无法向此发送消息 = 62751, // 0x0000F51F
+ 门店不存在 = 65115, // 0x0000FE5B
+ 该门店状态不允许更新 = 65118, // 0x0000FE5E
+ 标签格式错误 = 85006, // 0x00014C0E
+ 页面路径错误 = 85007, // 0x00014C0F
+ 类目填写错误 = 85008, // 0x00014C10
+ 已经有正在审核的版本 = 85009, // 0x00014C11
+ item_list有项目为空 = 85010, // 0x00014C12
+ 标题填写错误 = 85011, // 0x00014C13
+ 无效的审核id = 85012, // 0x00014C14
+ 版本输入错误 = 85015, // 0x00014C17
+ 没有审核版本 = 85019, // 0x00014C1B
+ 审核状态未满足发布 = 85020, // 0x00014C1C
+ 状态不可变 = 85021, // 0x00014C1D
+ action非法 = 85022, // 0x00014C1E
+ 审核列表填写的项目数不在1到5以内 = 85023, // 0x00014C1F
+ 需要补充相应资料_填写org_code和other_files参数 = 85024, // 0x00014C20
+ 管理员手机登记数量已超过上限 = 85025, // 0x00014C21
+ 该微信号已绑定5个管理员 = 85026, // 0x00014C22
+ 管理员身份证已登记过5次 = 85027, // 0x00014C23
+ 该主体登记数量已超过上限 = 85028, // 0x00014C24
+ 商家名称已被占用 = 85029, // 0x00014C25
+ 不能使用该名称 = 85031, // 0x00014C27
+ 该名称在侵权投诉保护期 = 85032, // 0x00014C28
+ 名称包含违规内容或微信等保留字 = 85033, // 0x00014C29
+ 商家名称在改名15天保护期内 = 85034, // 0x00014C2A
+ 需与该帐号相同主体才可申请 = 85035, // 0x00014C2B
+ 介绍中含有虚假混淆内容 = 85036, // 0x00014C2C
+ 头像或者简介修改达到每个月上限 = 85049, // 0x00014C39
+ 正在审核中_请勿重复提交 = 85050, // 0x00014C3A
+ 请先成功创建门店后再调用 = 85053, // 0x00014C3D
+ 临时mediaid无效 = 85056, // 0x00014C40
+ 链接错误 = 85066, // 0x00014C4A
+ 测试链接不是子链接 = 85068, // 0x00014C4C
+ 校验文件失败 = 85069, // 0x00014C4D
+ 个人类型小程序无法设置二维码规则 = 85070, // 0x00014C4E
+ 已添加该链接_请勿重复添加 = 85071, // 0x00014C4F
+ 该链接已被占用 = 85072, // 0x00014C50
+ 二维码规则已满 = 85073, // 0x00014C51
+ 小程序未发布_小程序必须先发布代码才可以发布二维码跳转规则 = 85074, // 0x00014C52
+ 个人类型小程序无法设置二维码规则1 = 85075, // 0x00014C53
+ 小程序没有线上版本_不能进行灰度 = 85079, // 0x00014C57
+ 小程序提交的审核未审核通过 = 85080, // 0x00014C58
+ 无效的发布比例 = 85081, // 0x00014C59
+ 当前的发布比例需要比之前设置的高 = 85082, // 0x00014C5A
+ 小程序提审数量已达本月上限 = 85085, // 0x00014C5D
+ 提交代码审核之前需提前上传代码 = 85086, // 0x00014C5E
+ 小程序已使用_api_navigateToMiniProgram_请声明跳转_appid_列表后再次提交 = 85087, // 0x00014C5F
+ 不是由第三方代小程序进行调用 = 86000, // 0x00014FF0
+ 不存在第三方的已经提交的代码 = 86001, // 0x00014FF1
+ 小程序还未设置昵称_头像_简介_请先设置完后再重新提交 = 86002, // 0x00014FF2
+ 无效微信号 = 86004, // 0x00014FF4
+
+ ///
+ /// 小程序为“签名错误”。对应公众号: 87009, “errmsg” : “reply is not exists” //该回复不存在
+ ///
+ 签名错误 = 87009, // 0x000153E1
+
+ 现网已经在灰度发布_不能进行版本回退 = 87011, // 0x000153E3
+ 该版本不能回退_可能的原因_1_无上一个线上版用于回退_2_此版本为已回退版本_不能回退_3_此版本为回退功能上线之前的版本_不能回退 = 87012, // 0x000153E4
+ 内容含有违法违规内容 = 87014, // 0x000153E6
+ 没有留言权限 = 88000, // 0x000157C0
+ 该图文不存在 = 88001, // 0x000157C1
+ 文章存在敏感信息 = 88002, // 0x000157C2
+ 精选评论数已达上限 = 88003, // 0x000157C3
+ 已被用户删除_无法精选 = 88004, // 0x000157C4
+ 已经回复过了 = 88005, // 0x000157C5
+ 回复超过长度限制或为0 = 88007, // 0x000157C7
+ 该评论不存在 = 88008, // 0x000157C8
+ 获取评论数目不合法 = 88010, // 0x000157CA
+ 该公众号_小程序已经绑定了开放平台帐号 = 89000, // 0x00015BA8
+ 业务域名无更改_无需重复设置 = 89019, // 0x00015BBB
+ 尚未设置小程序业务域名_请先在第三方平台中设置小程序业务域名后在调用本接口 = 89020, // 0x00015BBC
+ 请求保存的域名不是第三方平台中已设置的小程序业务域名或子域名 = 89021, // 0x00015BBD
+ 业务域名数量超过限制_最多可以添加100个业务域名 = 89029, // 0x00015BC5
+ 个人小程序不支持调用_setwebviewdomain_接口 = 89231, // 0x00015C8F
+ 内部错误 = 89247, // 0x00015C9F
+ 企业代码类型无效_请选择正确类型填写 = 89248, // 0x00015CA0
+ 该主体已有任务执行中_距上次任务24h后再试 = 89249, // 0x00015CA1
+ 未找到该任务 = 89250, // 0x00015CA2
+ 待法人人脸核身校验 = 89251, // 0x00015CA3
+ 法人_企业信息一致性校验中 = 89252, // 0x00015CA4
+ 缺少参数 = 89253, // 0x00015CA5
+ 第三方权限集不全_补全权限集全网发布后生效 = 89254, // 0x00015CA6
+ 系统不稳定_请稍后再试_如多次失败请通过社区反馈 = 89401, // 0x00015D39
+ 该审核单不在待审核队列_请检查是否已提交审核或已审完 = 89402, // 0x00015D3A
+ 本单属于平台不支持加急种类_请等待正常审核流程 = 89403, // 0x00015D3B
+ 本单已加速成功_请勿重复提交 = 89404, // 0x00015D3C
+ 本月加急额度不足_请提升提审质量以获取更多额度 = 89405, // 0x00015D3D
+ 该经营资质已添加_请勿重复添加 = 92000, // 0x00016760
+ 附近地点添加数量达到上线_无法继续添加 = 92002, // 0x00016762
+ 地点已被其它小程序占用 = 92003, // 0x00016763
+ 附近功能被封禁 = 92004, // 0x00016764
+ 地点正在审核中 = 92005, // 0x00016765
+ 地点正在展示小程序 = 92006, // 0x00016766
+ 地点审核失败 = 92007, // 0x00016767
+ 程序未展示在该地点 = 92008, // 0x00016768
+ 小程序未上架或不可见 = 92009, // 0x00016769
+ 地点不存在 = 93010, // 0x00016B52
+ 个人类型小程序不可用 = 93011, // 0x00016B53
+ 已下发的模板消息法人并未确认且已超时_24h_未进行身份证校验 = 100001, // 0x000186A1
+ 已下发的模板消息法人并未确认且已超时_24h_未进行人脸识别校验 = 100002, // 0x000186A2
+ 已下发的模板消息法人并未确认且已超时_24h = 100003, // 0x000186A3
+ 此账号已被封禁_无法操作 = 200011, // 0x00030D4B
+ 私有模板数已达上限_上限_50_个 = 200012, // 0x00030D4C
+ 此模版已被封禁_无法选用 = 200013, // 0x00030D4D
+ 模版tid参数错误 = 200014, // 0x00030D4E
+ 关键词列表kidList参数错误 = 200020, // 0x00030D54
+ 场景描述sceneDesc参数错误 = 200021, // 0x00030D55
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/WeekEnum.cs b/Admin.NET.Core/Enum/WeekEnum.cs
new file mode 100644
index 0000000..279c1c6
--- /dev/null
+++ b/Admin.NET.Core/Enum/WeekEnum.cs
@@ -0,0 +1,56 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 周枚举
+///
+[Description("周枚举")]
+public enum WeekEnum
+{
+ ///
+ /// 周一
+ ///
+ [Description("周一")]
+ Monday = 1,
+
+ ///
+ /// 周二
+ ///
+ [Description("周二")]
+ Tuesday = 2,
+
+ ///
+ /// 周三
+ ///
+ [Description("周三")]
+ Wednesday = 3,
+
+ ///
+ /// 周四
+ ///
+ [Description("周四")]
+ Thursday = 4,
+
+ ///
+ /// 周五
+ ///
+ [Description("周五")]
+ Friday = 5,
+
+ ///
+ /// 周六
+ ///
+ [Description("周六")]
+ Saturday = 6,
+
+ ///
+ /// 周日
+ ///
+ [Description("周日")]
+ Sunday = 7,
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Enum/YesNoEnum.cs b/Admin.NET.Core/Enum/YesNoEnum.cs
new file mode 100644
index 0000000..d26d141
--- /dev/null
+++ b/Admin.NET.Core/Enum/YesNoEnum.cs
@@ -0,0 +1,26 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 是否枚举
+///
+[Description("是否枚举")]
+public enum YesNoEnum
+{
+ ///
+ /// 是
+ ///
+ [Description("是"), Theme("success")]
+ Y = 1,
+
+ ///
+ /// 否
+ ///
+ [Description("否"), Theme("danger")]
+ N = 2
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/EventBus/AppEventSubscriber.cs b/Admin.NET.Core/EventBus/AppEventSubscriber.cs
new file mode 100644
index 0000000..e44ffd5
--- /dev/null
+++ b/Admin.NET.Core/EventBus/AppEventSubscriber.cs
@@ -0,0 +1,58 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 事件订阅
+///
+public class AppEventSubscriber : IEventSubscriber, ISingleton, IDisposable
+{
+ private static readonly ISugarQueryable SysTenantQueryable = App.GetService().Queryable();
+ private readonly IServiceScope _serviceScope;
+
+ public AppEventSubscriber(IServiceScopeFactory scopeFactory)
+ {
+ _serviceScope = scopeFactory.CreateScope();
+ }
+
+ ///
+ /// 增加异常日志
+ ///
+ ///
+ ///
+ [EventSubscribe(CommonConst.AddExLog)]
+ public async Task CreateExLog(EventHandlerExecutingContext context)
+ {
+ // 切换日志独立数据库
+ var db = SqlSugarSetup.ITenant.IsAnyConnection(SqlSugarConst.LogConfigId)
+ ? SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.LogConfigId)
+ : SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
+ await db.CopyNew().Insertable((SysLogEx)context.Source.Payload).ExecuteCommandAsync();
+ }
+
+ ///
+ /// 发送异常邮件
+ ///
+ ///
+ ///
+ [EventSubscribe(CommonConst.SendErrorMail)]
+ public async Task SendOrderErrorMail(EventHandlerExecutingContext context)
+ {
+ long.TryParse(App.HttpContext?.User.FindFirst(ClaimConst.TenantId)?.Value, out var tenantId);
+ var tenant = await SysTenantQueryable.FirstAsync(t => t.Id == tenantId);
+ var title = $"{tenant?.Title} 系统异常";
+ await _serviceScope.ServiceProvider.GetRequiredService().SendEmail(JSON.Serialize(context.Source.Payload), title);
+ }
+
+ ///
+ /// 释放服务作用域
+ ///
+ public void Dispose()
+ {
+ _serviceScope.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/EventBus/EventConsumer.cs b/Admin.NET.Core/EventBus/EventConsumer.cs
new file mode 100644
index 0000000..971d2e7
--- /dev/null
+++ b/Admin.NET.Core/EventBus/EventConsumer.cs
@@ -0,0 +1,118 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// Redis 消息扩展
+///
+///
+public class EventConsumer : IDisposable
+{
+ ///
+ ///
+ ///
+ private Task _consumerTask;
+
+ ///
+ ///
+ ///
+ private CancellationTokenSource _consumerCts;
+
+ ///
+ /// 消费者
+ ///
+ public IProducerConsumer Consumer { get; }
+
+ ///
+ /// 消息回调
+ ///
+ public event EventHandler Received;
+
+ ///
+ /// 构造函数
+ ///
+ ///
+ public EventConsumer(IProducerConsumer consumer) => Consumer = consumer;
+
+ ///
+ /// 启动
+ ///
+ ///
+ public void Start()
+ {
+ if (Consumer is null)
+ {
+ throw new InvalidOperationException("Subscribe first using the Consumer.Subscribe() function");
+ }
+ if (_consumerTask != null)
+ {
+ return;
+ }
+ _consumerCts = new CancellationTokenSource();
+ var ct = _consumerCts.Token;
+ _consumerTask = Task.Factory.StartNew(async () =>
+ {
+ while (!ct.IsCancellationRequested)
+ {
+ try
+ {
+ var cr = Consumer.TakeOne(10);
+ if (cr == null) continue;
+ Received?.Invoke(this, cr);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"消息消费异常: {ex.Message}");
+ await Task.Delay(1000); // 短暂等待后继续尝试
+ }
+ }
+ }, ct, TaskCreationOptions.LongRunning, TaskScheduler.Default);
+ }
+
+ ///
+ /// 停止
+ ///
+ ///
+ public async Task Stop()
+ {
+ if (_consumerCts == null || _consumerTask == null) return;
+ _consumerCts.Cancel();
+ try
+ {
+ await _consumerTask;
+ }
+ finally
+ {
+ _consumerTask = null;
+ _consumerCts = null;
+ }
+ }
+
+ ///
+ /// 释放
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// 释放
+ ///
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_consumerTask != null)
+ {
+ Stop().Wait();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/EventBus/EventHandlerMonitor.cs b/Admin.NET.Core/EventBus/EventHandlerMonitor.cs
new file mode 100644
index 0000000..7f229ed
--- /dev/null
+++ b/Admin.NET.Core/EventBus/EventHandlerMonitor.cs
@@ -0,0 +1,28 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+public class EventHandlerMonitor : IEventHandlerMonitor
+{
+ public Task OnExecutingAsync(EventHandlerExecutingContext context)
+ {
+ //_logger.LogInformation("执行之前:{EventId}", context.Source.EventId);
+ return Task.CompletedTask;
+ }
+
+ public Task OnExecutedAsync(EventHandlerExecutedContext context)
+ {
+ //_logger.LogInformation("执行之后:{EventId}", context.Source.EventId);
+
+ if (context.Exception != null)
+ {
+ Log.Error($"EventHandlerMonitor.OnExecutedAsync 执行出错啦:{context.Source.EventId}", context.Exception);
+ }
+
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/EventBus/RabbitMQEventSourceStore.cs b/Admin.NET.Core/EventBus/RabbitMQEventSourceStore.cs
new file mode 100644
index 0000000..5c28f6c
--- /dev/null
+++ b/Admin.NET.Core/EventBus/RabbitMQEventSourceStore.cs
@@ -0,0 +1,146 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using RabbitMQ.Client;
+using RabbitMQ.Client.Events;
+using System.Threading.Channels;
+
+namespace Admin.NET.Core;
+
+///
+/// RabbitMQ自定义事件源存储器
+///
+public class RabbitMQEventSourceStore : IEventSourceStorer, IDisposable
+{
+ ///
+ /// 内存通道事件源存储器
+ ///
+ private Channel _channelEventSource;
+
+ ///
+ /// 路由键
+ ///
+ private string _routeKey;
+
+ ///
+ /// 连接对象
+ ///
+ private IConnection _connection;
+
+ ///
+ /// 通道对象
+ ///
+ private IChannel _channel;
+
+ ///
+ /// 构造函数
+ ///
+ /// 连接工厂
+ /// 路由键
+ /// 存储器最多能够处理多少消息,超过该容量进入等待写入
+ public RabbitMQEventSourceStore(ConnectionFactory factory, string routeKey, int capacity)
+ {
+ InitEventSourceStore(factory, routeKey, capacity).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// 初始化事件源存储器
+ ///
+ /// 连接工厂
+ /// 路由键
+ /// 存储器最多能够处理多少消息,超过该容量进入等待写入
+ private async Task InitEventSourceStore(ConnectionFactory factory, string routeKey, int capacity)
+ {
+ // 配置通道(超出默认容量后进入等待)
+ var boundedChannelOptions = new BoundedChannelOptions(capacity)
+ {
+ FullMode = BoundedChannelFullMode.Wait
+ };
+ // 创建有限容量通道
+ _channelEventSource = Channel.CreateBounded(boundedChannelOptions);
+
+ // 创建连接
+ _connection = await factory.CreateConnectionAsync();
+ // 路由键名
+ _routeKey = routeKey;
+
+ // 创建通道
+ _channel = await _connection.CreateChannelAsync();
+
+ // 声明路由队列
+ await _channel.QueueDeclareAsync(routeKey, false, false, false, null);
+
+ // 创建消息订阅者
+ var consumer = new AsyncEventingBasicConsumer(_channel);
+
+ // 订阅消息并写入内存 Channel
+ consumer.ReceivedAsync += async (ch, ea) =>
+ {
+ // 读取原始消息
+ var stringEventSource = Encoding.UTF8.GetString(ea.Body.ToArray());
+
+ // 转换为 IEventSource,如果自定义了 EventSource,注意属性是可读可写
+ var eventSource = JSON.Deserialize(stringEventSource);
+
+ // 写入内存管道存储器
+ await _channelEventSource.Writer.WriteAsync(eventSource);
+
+ // 确认该消息已被消费
+ await _channel.BasicAckAsync(ea.DeliveryTag, false);
+ };
+
+ // 启动消费者且设置为手动应答消息
+ await _channel.BasicConsumeAsync(routeKey, false, consumer);
+ }
+
+ ///
+ /// 将事件源写入存储器
+ ///
+ /// 事件源对象
+ /// 取消任务 Token
+ ///
+ public async ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)
+ {
+ if (eventSource == default)
+ throw new ArgumentNullException(nameof(eventSource));
+
+ // 判断是否是 ChannelEventSource 或自定义的 EventSource
+ if (eventSource is ChannelEventSource source)
+ {
+ // 序列化及发布
+ var data = Encoding.UTF8.GetBytes(JSON.Serialize(source));
+ var props = new BasicProperties();
+ props.ContentType = "text/plain";
+ props.DeliveryMode = DeliveryModes.Persistent;
+ await _channel.BasicPublishAsync("", _routeKey, false, props, data);
+ }
+ else
+ {
+ // 处理动态订阅
+ await _channelEventSource.Writer.WriteAsync(eventSource, cancellationToken);
+ }
+ }
+
+ ///
+ /// 从存储器中读取一条事件源
+ ///
+ /// 取消任务 Token
+ /// 事件源对象
+ public async ValueTask ReadAsync(CancellationToken cancellationToken)
+ {
+ var eventSource = await _channelEventSource.Reader.ReadAsync(cancellationToken);
+ return eventSource;
+ }
+
+ ///
+ /// 释放非托管资源
+ ///
+ public void Dispose()
+ {
+ _channel.Dispose();
+ _connection.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs b/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs
new file mode 100644
index 0000000..f507e7b
--- /dev/null
+++ b/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs
@@ -0,0 +1,165 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using NewLife.Caching.Queues;
+using Newtonsoft.Json;
+using System.Threading.Channels;
+
+namespace Admin.NET.Core;
+
+///
+/// Redis自定义事件源存储器
+///
+///
+/// 在集群部署时,一般每一个消息只由一个服务节点消费一次。
+/// 有些特殊情情要通知到服务器群中的每一个节点(比如需要强制加载某些配置、重点服务等),
+/// 在这种情况下就要以“broadcast:”开头来定义EventId,
+/// 本系统会把“broadcast:”开头的事件视为“广播消息”保证集群中的每一个服务节点都能消费得到这个消息
+///
+public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable
+{
+ ///
+ /// 消费者
+ ///
+ private readonly EventConsumer _eventConsumer;
+
+ ///
+ /// 内存通道事件源存储器
+ ///
+ private readonly Channel _channel;
+
+ private IProducerConsumer _queueSingle;
+
+ private RedisStream _queueBroadcast;
+
+ private ILogger _logger;
+
+ ///
+ /// 构造函数
+ ///
+ /// Redis 连接对象
+ /// 路由键
+ /// 存储器最多能够处理多少消息,超过该容量进入等待写入
+ public RedisEventSourceStorer(ICacheProvider cacheProvider, string routeKey, int capacity)
+ {
+ _logger = App.GetRequiredService>();
+
+ // 配置通道,设置超出默认容量后进入等待
+ var boundedChannelOptions = new BoundedChannelOptions(capacity)
+ {
+ FullMode = BoundedChannelFullMode.Wait
+ };
+
+ // 创建有限容量通道
+ _channel = Channel.CreateBounded(boundedChannelOptions);
+
+ //_redis = redis as FullRedis;
+
+ // 创建广播消息订阅者,即所有服务器节点都能收到消息(用来发布重启、Reload配置等消息)
+ FullRedis redis = (FullRedis)cacheProvider.Cache;
+ var clusterOpt = App.GetConfig("Cluster", true);
+ _queueBroadcast = redis.GetStream(routeKey + ":broadcast");
+ _queueBroadcast.Group = clusterOpt.ServerId;//根据服务器标识分配到不同的分组里
+ _queueBroadcast.Expire = TimeSpan.FromSeconds(10);//消息10秒过期()
+ _queueBroadcast.ConsumeAsync(OnConsumeBroadcast);
+
+ // 创建队列消息订阅者,只要有一个服务节点消费了消息即可
+ _queueSingle = redis.GetQueue(routeKey + ":single");
+ _eventConsumer = new EventConsumer(_queueSingle);
+
+ // 订阅消息写入 Channel
+ _eventConsumer.Received += async (send, cr) =>
+ {
+ // var oriColor = Console.ForegroundColor;
+ try
+ {
+ ChannelEventSource ces = (ChannelEventSource)cr;
+ await ConsumeChannelEventSourceAsync(ces, ces.CancellationToken);
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "处理Received中的消息产生错误!");
+ }
+ };
+ _eventConsumer.Start();
+ }
+
+ private async Task OnConsumeBroadcast(string source, Message message, CancellationToken token)
+ {
+ ChannelEventSource ces = JsonConvert.DeserializeObject(source);
+ await ConsumeChannelEventSourceAsync(ces, token);
+ }
+
+ private async Task ConsumeChannelEventSourceAsync(ChannelEventSource ces, CancellationToken cancel = default)
+ {
+ // 打印测试事件
+ if (ces.EventId != null && ces.EventId.IndexOf(":Test") > 0)
+ {
+ var oriColor = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine($"有消息要处理{ces.EventId},{ces.Payload}");
+ Console.ForegroundColor = oriColor;
+ }
+ await _channel.Writer.WriteAsync(ces, cancel);
+ }
+
+ ///
+ /// 将事件源写入存储器
+ ///
+ /// 事件源对象
+ /// 取消任务 Token
+ ///
+ public async ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)
+ {
+ // 空检查
+ if (eventSource == default)
+ throw new ArgumentNullException(nameof(eventSource));
+
+ // 这里判断是否是 ChannelEventSource 或者 自定义的 EventSource
+ if (eventSource is ChannelEventSource source)
+ {
+ // 异步发布
+ await Task.Factory.StartNew(() =>
+ {
+ if (source.EventId != null && source.EventId.StartsWith("broadcast:"))
+ {
+ string str = JsonConvert.SerializeObject(source);
+ _queueBroadcast.Add(str);
+ }
+ else
+ {
+ _queueSingle.Add(source);
+ }
+ }, cancellationToken, TaskCreationOptions.LongRunning, System.Threading.Tasks.TaskScheduler.Default);
+ }
+ else
+ {
+ // 处理动态订阅问题
+ await _channel.Writer.WriteAsync(eventSource, cancellationToken);
+ }
+ }
+
+ ///
+ /// 从存储器中读取一条事件源
+ ///
+ /// 取消任务 Token
+ /// 事件源对象
+ public async ValueTask ReadAsync(CancellationToken cancellationToken)
+ {
+ // 读取一条事件源
+ var eventSource = await _channel.Reader.ReadAsync(cancellationToken);
+ return eventSource;
+ }
+
+ ///
+ /// 释放非托管资源
+ ///
+ public async void Dispose()
+ {
+ await _eventConsumer.Stop();
+ GC.SuppressFinalize(this);
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/EventBus/RedisQueue.cs b/Admin.NET.Core/EventBus/RedisQueue.cs
new file mode 100644
index 0000000..3478e25
--- /dev/null
+++ b/Admin.NET.Core/EventBus/RedisQueue.cs
@@ -0,0 +1,202 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using NewLife.Caching.Queues;
+
+namespace Admin.NET.Core;
+
+///
+/// Redis 消息队列
+///
+public static class RedisQueue
+{
+ private static ICacheProvider _cacheProvider = App.GetRequiredService();
+
+ /// 创建Redis消息队列。默认消费一次,指定消费者group时使用STREAM结构,支持多消费组共享消息
+ ///
+ /// 使用队列时,可根据是否设置消费组来决定使用简单队列还是完整队列。 简单队列(如RedisQueue)可用作命令队列,Topic很多,但几乎没有消息。 完整队列(如RedisStream)可用作消息队列,Topic很少,但消息很多,并且支持多消费组。
+ ///
+ ///
+ /// 主题
+ /// 消费组。未指定消费组时使用简单队列(如RedisQueue),指定消费组时使用完整队列(如RedisStream)
+ ///
+ public static IProducerConsumer GetQueue(String topic, String group = null)
+ {
+ // 队列需要单列
+ var key = $"myStream:{topic}";
+ if (_cacheProvider.InnerCache.TryGetValue>(key, out var queue)) return queue;
+
+ queue = _cacheProvider.GetQueue(topic, group);
+ _cacheProvider.Cache.Set(key, queue);
+
+ return queue;
+ }
+
+ ///
+ /// 获取可信队列,需要确认
+ ///
+ ///
+ ///
+ ///
+ public static RedisReliableQueue GetRedisReliableQueue(string topic)
+ {
+ // 队列需要单列
+ var key = $"myQueue:{topic}";
+ if (_cacheProvider.InnerCache.TryGetValue>(key, out var queue)) return queue;
+
+ queue = (_cacheProvider.Cache as FullRedis).GetReliableQueue(topic);
+ _cacheProvider.Cache.Set(key, queue);
+
+ return queue;
+ }
+
+ ///
+ /// 可信队列回滚
+ ///
+ ///
+ ///
+ ///
+ public static int RollbackAllAck(string topic, int retryInterval = 60)
+ {
+ var queue = GetRedisReliableQueue(topic);
+ queue.RetryInterval = retryInterval;
+ return queue.RollbackAllAck();
+ }
+
+ ///
+ /// 发送一个数据列表到可信队列
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int AddReliableQueueList(string topic, List value)
+ {
+ var queue = GetRedisReliableQueue(topic);
+ var count = queue.Count;
+ var result = queue.Add(value.ToArray());
+ return result - count;
+ }
+
+ ///
+ /// 发送一条数据到可信队列
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int AddReliableQueue(string topic, T value)
+ {
+ var queue = GetRedisReliableQueue(topic);
+ var count = queue.Count;
+ var result = queue.Add(value);
+ return result - count;
+ }
+
+ ///
+ /// 获取延迟队列
+ ///
+ ///
+ ///
+ ///
+ public static RedisDelayQueue GetDelayQueue(string topic)
+ {
+ // 队列需要单列
+ var key = $"myDelay:{topic}";
+ if (_cacheProvider.InnerCache.TryGetValue>(key, out var queue)) return queue;
+
+ queue = (_cacheProvider.Cache as FullRedis).GetDelayQueue(topic);
+ _cacheProvider.Cache.Set(key, queue);
+
+ return queue;
+ }
+
+ ///
+ /// 发送一条数据到延迟队列
+ ///
+ ///
+ ///
+ /// 延迟时间。单位秒
+ ///
+ ///
+ public static int AddDelayQueue(string topic, T value, int delay)
+ {
+ var queue = GetDelayQueue(topic);
+ return queue.Add(value, delay);
+ }
+
+ ///
+ /// 发送数据列表到延迟队列
+ ///
+ ///
+ ///
+ ///
+ /// 延迟时间。单位秒
+ ///
+ public static int AddDelayQueue(string topic, List value, int delay)
+ {
+ var queue = GetDelayQueue(topic);
+ queue.Delay = delay;
+ return queue.Add(value.ToArray());
+ }
+
+ ///
+ /// 在可信队列获取一条数据
+ ///
+ ///
+ ///
+ ///
+ public static T ReliableTakeOne(string topic)
+ {
+ var queue = GetRedisReliableQueue(topic);
+ return queue.TakeOne(1);
+ }
+
+ ///
+ /// 异步在可信队列获取一条数据
+ ///
+ ///
+ ///
+ ///
+ public static async Task ReliableTakeOneAsync(string topic)
+ {
+ var queue = GetRedisReliableQueue(topic);
+ return await queue.TakeOneAsync(1);
+ }
+
+ ///
+ /// 在可信队列获取多条数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List ReliableTake(string topic, int count)
+ {
+ var queue = GetRedisReliableQueue(topic);
+ return queue.Take(count).ToList();
+ }
+
+ ///
+ /// 申请分布式锁
+ ///
+ /// 要锁定的key
+ /// 申请锁等待的时间,单位毫秒
+ /// 锁过期时间,超过该时间没有主动是放则自动是放,必须整数秒,单位毫秒
+ /// 失败时是否抛出异常,如不抛出异常,可通过判断返回null得知申请锁失败
+ ///
+ public static IDisposable? BeginCacheLock(string key, int msTimeout = 500, int msExpire = 10000, bool throwOnFailure = true)
+ {
+ try
+ {
+ return _cacheProvider.Cache.AcquireLock(key, msTimeout, msExpire, throwOnFailure);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/EventBus/RetryEventHandlerExecutor.cs b/Admin.NET.Core/EventBus/RetryEventHandlerExecutor.cs
new file mode 100644
index 0000000..59f9cec
--- /dev/null
+++ b/Admin.NET.Core/EventBus/RetryEventHandlerExecutor.cs
@@ -0,0 +1,44 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 事件执行器-超时控制、失败重试熔断等等
+///
+public class RetryEventHandlerExecutor : IEventHandlerExecutor
+{
+ public async Task ExecuteAsync(EventHandlerExecutingContext context, Func handler)
+ {
+ var eventSubscribeAttribute = context.Attribute;
+ // 判断是否自定义了重试失败回调服务
+ var fallbackPolicyService = eventSubscribeAttribute?.FallbackPolicy == null
+ ? null
+ : App.GetRequiredService(eventSubscribeAttribute.FallbackPolicy) as IEventFallbackPolicy;
+
+ await Retry.InvokeAsync(async () =>
+ {
+ try
+ {
+ await handler(context);
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"Invoke EventHandler {context.Source.EventId} Error", ex);
+ throw;
+ }
+ }
+ , eventSubscribeAttribute?.NumRetries ?? 0
+ , eventSubscribeAttribute?.RetryTimeout ?? 1000
+ , exceptionTypes: eventSubscribeAttribute?.ExceptionTypes
+ , fallbackPolicy: fallbackPolicyService == null ? null : async (Exception ex) => { await fallbackPolicyService.CallbackAsync(context, ex); }
+ , retryAction: (total, times) =>
+ {
+ // 输出重试日志
+ Log.Warning($"Retrying {times}/{total} times for EventHandler {context.Source.EventId}");
+ });
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Extension/ConsoleLogoSetup.cs b/Admin.NET.Core/Extension/ConsoleLogoSetup.cs
new file mode 100644
index 0000000..be20e97
--- /dev/null
+++ b/Admin.NET.Core/Extension/ConsoleLogoSetup.cs
@@ -0,0 +1,27 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 控制台logo
+///
+public static class ConsoleLogoSetup
+{
+ public static void AddConsoleLogo(this IServiceCollection services)
+ {
+ Console.ForegroundColor = ConsoleColor.Blue;
+ Console.WriteLine(@"
+ _ _ _ _ ______ _______
+ /\ | | (_) | \ | | ____|__ __|
+ / \ __| |_ __ ___ _ _ __ | \| | |__ | |
+ / /\ \ / _` | '_ ` _ \| | '_ \ | . ` | __| | |
+ / ____ \ (_| | | | | | | | | | |_| |\ | |____ | |
+ /_/ \_\__,_|_| |_| |_|_|_| |_(_)_| \_|______| |_| ");
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine(@"让.NET更简单、更通用、更流行!");
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Extension/DataTypeExtension.cs b/Admin.NET.Core/Extension/DataTypeExtension.cs
new file mode 100644
index 0000000..0f9d4ab
--- /dev/null
+++ b/Admin.NET.Core/Extension/DataTypeExtension.cs
@@ -0,0 +1,109 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 基本数据类型扩展(作为NewLife.Core的Utility的补充)
+///
+public static class DataTypeExtension
+{
+ /// 转为SByte整数,转换失败时返回默认值。
+ ///
+ /// 待转换对象
+ /// 默认值。待转换对象无效时使用
+ ///
+ public static sbyte ToSByte(this object value, sbyte defaultValue = default)
+ {
+ if (value is sbyte num) return num;
+ if (value == null || value == DBNull.Value) return defaultValue;
+
+ if (sbyte.TryParse(value.ToString(), out var result))
+ return result;
+ else
+ return defaultValue;
+ }
+
+ /// 转为Byte整数,转换失败时返回默认值。
+ ///
+ /// 待转换对象
+ /// 默认值。待转换对象无效时使用
+ ///
+ public static byte ToByte(this object value, byte defaultValue = default)
+ {
+ if (value is byte num) return num;
+ if (value == null || value == DBNull.Value) return defaultValue;
+
+ if (byte.TryParse(value.ToString(), out var result))
+ return result;
+ else
+ return defaultValue;
+ }
+
+ /// 转为Int16整数,转换失败时返回默认值。
+ ///
+ /// 待转换对象
+ /// 默认值。待转换对象无效时使用
+ ///
+ public static short ToInt16(this object value, short defaultValue = default)
+ {
+ if (value is short num) return num;
+ if (value == null || value == DBNull.Value) return defaultValue;
+
+ if (short.TryParse(value.ToString(), out var result))
+ return result;
+ else
+ return defaultValue;
+ }
+
+ /// 转为UInt16整数,转换失败时返回默认值。
+ ///
+ /// 待转换对象
+ /// 默认值。待转换对象无效时使用
+ ///
+ public static ushort ToUInt16(this object value, ushort defaultValue = default)
+ {
+ if (value is ushort num) return num;
+ if (value == null || value == DBNull.Value) return defaultValue;
+
+ if (ushort.TryParse(value.ToString(), out var result))
+ return result;
+ else
+ return defaultValue;
+ }
+
+ /// 转为UInt32整数,转换失败时返回默认值。
+ ///
+ /// 待转换对象
+ /// 默认值。待转换对象无效时使用
+ ///
+ public static uint ToUInt32(this object value, uint defaultValue = default)
+ {
+ if (value is uint num) return num;
+ if (value == null || value == DBNull.Value) return defaultValue;
+
+ if (uint.TryParse(value.ToString(), out var result))
+ return result;
+ else
+ return defaultValue;
+ }
+
+ /// 转为UInt64整数,转换失败时返回默认值。
+ ///
+ /// 待转换对象
+ /// 默认值。待转换对象无效时使用
+ ///
+ public static ulong ToUInt64(this object value, ulong defaultValue = default)
+ {
+ if (value is ulong num) return num;
+ if (value == null || value == DBNull.Value) return defaultValue;
+
+ if (ulong.TryParse(value.ToString(), out var result))
+ return result;
+ else
+ return defaultValue;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Extension/EnumExtension.cs b/Admin.NET.Core/Extension/EnumExtension.cs
new file mode 100644
index 0000000..6900d76
--- /dev/null
+++ b/Admin.NET.Core/Extension/EnumExtension.cs
@@ -0,0 +1,239 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 枚举拓展
+///
+public static class EnumExtension
+{
+ // 枚举显示字典缓存
+ private static readonly ConcurrentDictionary> EnumDisplayValueDict = new();
+
+ // 枚举值字典缓存
+ private static readonly ConcurrentDictionary> EnumNameValueDict = new();
+
+ // 枚举类型缓存
+ private static ConcurrentDictionary _enumTypeDict;
+
+ ///
+ /// 获取枚举对象Key与名称的字典(缓存)
+ ///
+ ///
+ ///
+ public static Dictionary GetEnumDictionary(this Type enumType)
+ {
+ if (!enumType.IsEnum)
+ throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
+
+ // 查询缓存
+ var enumDic = EnumNameValueDict.TryGetValue(enumType, out var value) ? value : new Dictionary();
+ if (enumDic.Count != 0)
+ return enumDic;
+ // 取枚举类型的Key/Value字典集合
+ enumDic = GetEnumDictionaryItems(enumType);
+
+ // 缓存
+ EnumNameValueDict[enumType] = enumDic;
+
+ return enumDic;
+ }
+
+ ///
+ /// 获取枚举对象Key与名称的字典
+ ///
+ ///
+ ///
+ private static Dictionary GetEnumDictionaryItems(this Type enumType)
+ {
+ // 获取类型的字段,初始化一个有限长度的字典
+ var enumFields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
+ Dictionary enumDic = new(enumFields.Length);
+
+ // 遍历字段数组获取key和name
+ foreach (var enumField in enumFields)
+ {
+ var intValue = (int)enumField.GetValue(enumType)!;
+ enumDic[intValue] = enumField.Name;
+ }
+
+ return enumDic;
+ }
+
+ ///
+ /// 获取枚举类型key与描述的字典(缓存)
+ ///
+ ///
+ ///
+ ///
+ public static Dictionary GetEnumDescDictionary(this Type enumType)
+ {
+ if (!enumType.IsEnum)
+ throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
+
+ // 查询缓存
+ var enumDic = EnumDisplayValueDict.TryGetValue(enumType, out var value)
+ ? value
+ : new Dictionary();
+ if (enumDic.Count != 0)
+ return enumDic;
+ // 取枚举类型的Key/Value字典集合
+ enumDic = GetEnumDescDictionaryItems(enumType);
+
+ // 缓存
+ EnumDisplayValueDict[enumType] = enumDic;
+
+ return enumDic;
+ }
+
+ ///
+ /// 获取枚举类型key与描述的字典(没有描述则获取name)
+ ///
+ ///
+ ///
+ ///
+ private static Dictionary GetEnumDescDictionaryItems(this Type enumType)
+ {
+ // 获取类型的字段,初始化一个有限长度的字典
+ var enumFields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
+ Dictionary enumDic = new(enumFields.Length);
+
+ // 遍历字段数组获取key和name
+ foreach (var enumField in enumFields)
+ {
+ var intValue = (int)enumField.GetValue(enumType)!;
+ var desc = enumField.GetDescriptionValue();
+ enumDic[intValue] = desc != null && !string.IsNullOrEmpty(desc.Description) ? desc.Description : enumField.Name;
+ }
+
+ return enumDic;
+ }
+
+ ///
+ /// 从程序集中查找指定枚举类型
+ ///
+ ///
+ ///
+ ///
+ public static Type TryToGetEnumType(Assembly assembly, string typeName)
+ {
+ // 枚举缓存为空则重新加载枚举类型字典
+ _enumTypeDict ??= LoadEnumTypeDict(assembly);
+
+ // 按名称查找
+ return _enumTypeDict.TryGetValue(typeName, out var value) ? value : null;
+ }
+
+ ///
+ /// 从程序集中加载所有枚举类型
+ ///
+ ///
+ ///
+ private static ConcurrentDictionary LoadEnumTypeDict(Assembly assembly)
+ {
+ // 取程序集中所有类型
+ var typeArray = assembly.GetTypes();
+
+ // 过滤非枚举类型,转成字典格式并返回
+ var dict = typeArray.Where(o => o.IsEnum).ToDictionary(o => o.Name, o => o);
+ ConcurrentDictionary enumTypeDict = new(dict);
+ return enumTypeDict;
+ }
+
+ ///
+ /// 获取枚举的Description
+ ///
+ ///
+ ///
+ public static string GetEnumDescription(this Enum value)
+ {
+ return value.GetType().GetField(value.ToString())?.GetCustomAttribute()?.Description;
+ }
+
+ ///
+ /// 获取枚举的Description
+ ///
+ ///
+ ///
+ public static string GetEnumDescription(this object value)
+ {
+ return value.GetType().GetField(value.ToString()!)?.GetCustomAttribute()?.Description;
+ }
+
+ ///
+ /// 获取枚举的Theme
+ ///
+ ///
+ ///
+ public static string GetTheme(this object value)
+ {
+ return value.GetType().GetField(value.ToString()!)?.GetCustomAttribute()?.Theme;
+ }
+
+ ///
+ /// 将枚举转成枚举信息集合
+ ///
+ ///
+ ///
+ public static List EnumToList(this Type type)
+ {
+ if (!type.IsEnum)
+ throw new ArgumentException("Type '" + type.Name + "' is not an enum.");
+ var arr = Enum.GetNames(type);
+ return arr.Select(sl =>
+ {
+ var item = Enum.Parse(type, sl);
+ return new EnumEntity
+ {
+ Name = item.ToString(),
+ Describe = item.GetEnumDescription() ?? item.ToString(),
+ Theme = item.GetTheme() ?? string.Empty,
+ Value = item.GetHashCode()
+ };
+ }).ToList();
+ }
+
+ ///
+ /// 枚举ToList
+ ///
+ ///
+ ///
+ ///
+ public static List EnumToList(this Type type)
+ {
+ if (!type.IsEnum)
+ throw new ArgumentException("Type '" + type.Name + "' is not an enum.");
+ var arr = Enum.GetNames(type);
+ return arr.Select(name => (T)Enum.Parse(type, name)).ToList();
+ }
+}
+
+///
+/// 枚举实体
+///
+public class EnumEntity
+{
+ ///
+ /// 枚举的描述
+ ///
+ public string Describe { get; set; }
+
+ ///
+ /// 枚举的样式
+ ///
+ public string Theme { get; set; }
+
+ ///
+ /// 枚举名称
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 枚举对象的值
+ ///
+ public int Value { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Extension/EnumerableExtension.cs b/Admin.NET.Core/Extension/EnumerableExtension.cs
new file mode 100644
index 0000000..de6c71e
--- /dev/null
+++ b/Admin.NET.Core/Extension/EnumerableExtension.cs
@@ -0,0 +1,109 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 数据集合拓展类
+///
+public static class EnumerableExtension
+{
+ private static readonly ConcurrentDictionary PropertyCache = new();
+
+ ///
+ /// 查询有父子关系的数据集
+ ///
+ /// 数据集
+ /// 主键ID字段
+ /// 父级字段
+ /// 顶级节点父级字段值
+ /// 是否包含顶级节点本身
+ ///
+ public static IEnumerable ToChildList(this IEnumerable list,
+ Expression> idExpression,
+ Expression> parentIdExpression,
+ object topParentIdValue,
+ bool isContainOneself = true)
+ {
+ if (list == null || !list.Any()) return Enumerable.Empty();
+
+ var propId = GetPropertyInfo(idExpression);
+ var propParentId = GetPropertyInfo(parentIdExpression);
+
+ // 查找所有顶级节点
+ var topNodes = list.Where(item => Equals(propId.GetValue(item), topParentIdValue)).ToList();
+
+ return TraverseHierarchy(list, propId, propParentId, topNodes, isContainOneself);
+ }
+
+ ///
+ /// 查询有父子关系的数据集
+ ///
+ /// 数据集
+ /// 主键ID字段
+ /// 父级字段
+ /// 顶级节点的选择条件
+ /// 是否包含顶级节点本身
+ ///
+ public static IEnumerable ToChildList(this IEnumerable list,
+ Expression> idExpression,
+ Expression> parentIdExpression,
+ Expression> topLevelPredicate,
+ bool isContainOneself = true)
+ {
+ if (list == null || !list.Any()) return Enumerable.Empty();
+
+ // 获取顶级节点
+ var topNodes = list.Where(topLevelPredicate.Compile()).ToList();
+
+ if (!topNodes.Any()) return Enumerable.Empty();
+
+ var idPropertyInfo = GetPropertyInfo(idExpression);
+ var parentPropertyInfo = GetPropertyInfo(parentIdExpression);
+
+ return TraverseHierarchy(list, idPropertyInfo, parentPropertyInfo, topNodes, isContainOneself);
+ }
+
+ ///
+ /// 辅助方法,从表达式中提取属性信息并使用临时缓存
+ ///
+ private static PropertyInfo GetPropertyInfo(Expression> expression)
+ {
+ // 使用 ConcurrentDictionary 确保线程安全
+ return PropertyCache.GetOrAdd(typeof(T).FullName + "." + ((MemberExpression)expression.Body).Member.Name, k =>
+ {
+ if (expression.Body is UnaryExpression { Operand: MemberExpression member }) return (PropertyInfo)member.Member;
+ if (expression.Body is MemberExpression memberExpression) return (PropertyInfo)memberExpression.Member;
+ throw Oops.Oh("表达式必须是一个属性访问: " + expression);
+ });
+ }
+
+ ///
+ /// 使用队列遍历层级结构
+ ///
+ private static IEnumerable TraverseHierarchy(IEnumerable list,
+ PropertyInfo idPropertyInfo,
+ PropertyInfo parentPropertyInfo,
+ List topNodes,
+ bool isContainOneself)
+ {
+ var queue = new Queue(topNodes);
+ var result = new HashSet(topNodes);
+
+ while (queue.Count > 0)
+ {
+ var currentNode = queue.Dequeue();
+ var children = list.Where(item => Equals(parentPropertyInfo.GetValue(item), idPropertyInfo.GetValue(currentNode))).ToList();
+ children.Where(child => result.Add(child)).ForEach(child => queue.Enqueue(child));
+ }
+ if (isContainOneself) return result;
+
+ // 如果不需要包含顶级节点本身,则移除它们
+ topNodes.ForEach(e => result.Remove(e));
+
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Extension/HttpContextExtension.cs b/Admin.NET.Core/Extension/HttpContextExtension.cs
new file mode 100644
index 0000000..88074a7
--- /dev/null
+++ b/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.Core/Extension/ListExtensions.cs b/Admin.NET.Core/Extension/ListExtensions.cs
new file mode 100644
index 0000000..dcf9e9c
--- /dev/null
+++ b/Admin.NET.Core/Extension/ListExtensions.cs
@@ -0,0 +1,48 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+public static class ListExtensions
+{
+ public static async Task ForEachAsync(this List list, Func func)
+ {
+ foreach (var value in list)
+ {
+ await func(value);
+ }
+ }
+
+ public static async Task ForEachAsync(this IEnumerable source, Func action)
+ {
+ foreach (var value in source)
+ {
+ await action(value);
+ }
+ }
+
+ public static void ForEach(this IEnumerable enumerable, Action consumer)
+ {
+ foreach (T item in enumerable)
+ {
+ consumer(item);
+ }
+ }
+
+ public static void AddRange(this IList list, IEnumerable items)
+ {
+ if (list is List list2)
+ {
+ list2.AddRange(items);
+ return;
+ }
+
+ foreach (T item in items)
+ {
+ list.Add(item);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Extension/ObjectExtension.cs b/Admin.NET.Core/Extension/ObjectExtension.cs
new file mode 100644
index 0000000..21fd46b
--- /dev/null
+++ b/Admin.NET.Core/Extension/ObjectExtension.cs
@@ -0,0 +1,521 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using Newtonsoft.Json;
+
+namespace Admin.NET.Core;
+
+///
+/// 对象拓展
+///
+[SuppressSniffer]
+public static partial class ObjectExtension
+{
+ ///
+ /// 类型属性列表映射表
+ ///
+ private static readonly ConcurrentDictionary PropertyCache = new();
+
+ ///
+ /// 脱敏特性缓存映射表
+ ///
+ private static readonly ConcurrentDictionary AttributeCache = new();
+
+ ///
+ /// 判断类型是否实现某个泛型
+ ///
+ /// 类型
+ /// 泛型类型
+ /// bool
+ public static bool HasImplementedRawGeneric(this Type type, Type generic)
+ {
+ // 检查接口类型
+ var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
+ if (isTheRawGenericType) return true;
+
+ // 检查类型
+ while (type != null && type != typeof(object))
+ {
+ isTheRawGenericType = IsTheRawGenericType(type);
+ if (isTheRawGenericType) return true;
+ type = type.BaseType;
+ }
+
+ return false;
+
+ // 判断逻辑
+ bool IsTheRawGenericType(Type type) => generic == (type.IsGenericType ? type.GetGenericTypeDefinition() : type);
+ }
+
+ ///
+ /// 将字典转化为QueryString格式
+ ///
+ ///
+ ///
+ ///
+ public static string ToQueryString(this Dictionary dict, bool urlEncode = true)
+ {
+ return string.Join("&", dict.Select(p => $"{(urlEncode ? p.Key?.UrlEncode() : "")}={(urlEncode ? p.Value?.UrlEncode() : "")}"));
+ }
+
+ ///
+ /// 将字符串URL编码
+ ///
+ ///
+ ///
+ public static string UrlEncode(this string str)
+ {
+ return string.IsNullOrEmpty(str) ? "" : System.Uri.EscapeDataString(str);
+ }
+
+ ///
+ /// 对象序列化成Json字符串
+ ///
+ ///
+ ///
+ public static string ToJson(this object obj)
+ {
+ var jsonSettings = SetNewtonsoftJsonSetting();
+ return JSON.GetJsonSerializer().Serialize(obj, jsonSettings);
+ }
+
+ private static JsonSerializerSettings SetNewtonsoftJsonSetting()
+ {
+ JsonSerializerSettings setting = new JsonSerializerSettings();
+ setting.DateFormatHandling = DateFormatHandling.IsoDateFormat;
+ setting.DateTimeZoneHandling = DateTimeZoneHandling.Local;
+ setting.DateFormatString = "yyyy-MM-dd HH:mm:ss"; // 时间格式化
+ setting.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; // 忽略循环引用
+ //setting.ContractResolver = new HelErpContractResolver("StartTime", customName);
+ return setting;
+ }
+
+ ///
+ /// Json字符串反序列化成对象
+ ///
+ ///
+ ///
+ ///
+ public static T ToObject(this string json)
+ {
+ return JSON.GetJsonSerializer().Deserialize(json);
+ }
+
+ ///
+ /// 将object转换为long,若失败则返回0
+ ///
+ ///
+ ///
+ public static long ParseToLong(this object obj)
+ {
+ try
+ {
+ return long.Parse(obj.ToString());
+ }
+ catch
+ {
+ return 0L;
+ }
+ }
+
+ ///
+ /// 将object转换为long,若失败则返回指定值
+ ///
+ ///
+ ///
+ ///
+ public static long ParseToLong(this string str, long defaultValue)
+ {
+ try
+ {
+ return long.Parse(str);
+ }
+ catch
+ {
+ return defaultValue;
+ }
+ }
+
+ ///
+ /// 将object转换为double,若失败则返回0
+ ///
+ ///
+ ///
+ public static double ParseToDouble(this object obj)
+ {
+ try
+ {
+ return double.Parse(obj.ToString());
+ }
+ catch
+ {
+ return 0;
+ }
+ }
+
+ ///
+ /// 将object转换为double,若失败则返回指定值
+ ///
+ ///
+ ///
+ ///
+ public static double ParseToDouble(this object str, double defaultValue)
+ {
+ try
+ {
+ return double.Parse(str.ToString());
+ }
+ catch
+ {
+ return defaultValue;
+ }
+ }
+
+ ///
+ /// 将string转换为DateTime,若失败则返回日期最小值
+ ///
+ ///
+ ///
+ public static DateTime ParseToDateTime(this string str)
+ {
+ try
+ {
+ if (string.IsNullOrWhiteSpace(str))
+ {
+ return DateTime.MinValue;
+ }
+ if (str.Contains('-') || str.Contains('/'))
+ {
+ return DateTime.Parse(str);
+ }
+ else
+ {
+ int length = str.Length;
+ switch (length)
+ {
+ case 4:
+ return DateTime.ParseExact(str, "yyyy", System.Globalization.CultureInfo.CurrentCulture);
+
+ case 6:
+ return DateTime.ParseExact(str, "yyyyMM", System.Globalization.CultureInfo.CurrentCulture);
+
+ case 8:
+ return DateTime.ParseExact(str, "yyyyMMdd", System.Globalization.CultureInfo.CurrentCulture);
+
+ case 10:
+ return DateTime.ParseExact(str, "yyyyMMddHH", System.Globalization.CultureInfo.CurrentCulture);
+
+ case 12:
+ return DateTime.ParseExact(str, "yyyyMMddHHmm", System.Globalization.CultureInfo.CurrentCulture);
+
+ case 14:
+ return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);
+
+ default:
+ return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);
+ }
+ }
+ }
+ catch
+ {
+ return DateTime.MinValue;
+ }
+ }
+
+ ///
+ /// 将string转换为DateTime,若失败则返回默认值
+ ///
+ ///
+ ///
+ ///
+ public static DateTime ParseToDateTime(this string str, DateTime? defaultValue)
+ {
+ try
+ {
+ if (string.IsNullOrWhiteSpace(str))
+ {
+ return defaultValue.GetValueOrDefault();
+ }
+ if (str.Contains('-') || str.Contains('/'))
+ {
+ return DateTime.Parse(str);
+ }
+ else
+ {
+ int length = str.Length;
+ switch (length)
+ {
+ case 4:
+ return DateTime.ParseExact(str, "yyyy", System.Globalization.CultureInfo.CurrentCulture);
+
+ case 6:
+ return DateTime.ParseExact(str, "yyyyMM", System.Globalization.CultureInfo.CurrentCulture);
+
+ case 8:
+ return DateTime.ParseExact(str, "yyyyMMdd", System.Globalization.CultureInfo.CurrentCulture);
+
+ case 10:
+ return DateTime.ParseExact(str, "yyyyMMddHH", System.Globalization.CultureInfo.CurrentCulture);
+
+ case 12:
+ return DateTime.ParseExact(str, "yyyyMMddHHmm", System.Globalization.CultureInfo.CurrentCulture);
+
+ case 14:
+ return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);
+
+ default:
+ return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);
+ }
+ }
+ }
+ catch
+ {
+ return defaultValue.GetValueOrDefault();
+ }
+ }
+
+ ///
+ /// 将 string 时间日期格式转换成字符串 如 {yyyy} => 2024
+ ///
+ ///
+ ///
+ public static string ParseToDateTimeForRep(this string str)
+ {
+ if (string.IsNullOrWhiteSpace(str))
+ str = $"{DateTime.Now.Year}/{DateTime.Now.Month}/{DateTime.Now.Day}";
+
+ var date = DateTime.Now;
+ var reg = new Regex(@"(\{.+?})");
+ var match = reg.Matches(str);
+ match.ToList().ForEach(u =>
+ {
+ var temp = date.ToString(u.ToString().Substring(1, u.Length - 2));
+ str = str.Replace(u.ToString(), temp);
+ });
+ return str;
+ }
+
+ ///
+ /// 是否有值
+ ///
+ ///
+ ///
+ public static bool IsNullOrEmpty(this object obj)
+ {
+ return obj == null || string.IsNullOrEmpty(obj.ToString());
+ }
+
+ ///
+ /// 字符串掩码
+ ///
+ /// 字符串
+ /// 掩码符
+ ///
+ public static string Mask(this string str, char mask = '*')
+ {
+ if (string.IsNullOrWhiteSpace(str?.Trim()))
+ return str;
+
+ str = str.Trim();
+ var masks = mask.ToString().PadLeft(4, mask);
+ return str.Length switch
+ {
+ >= 11 => Regex.Replace(str, "(.{3}).*(.{4})", $"$1{masks}$2"),
+ 10 => Regex.Replace(str, "(.{3}).*(.{3})", $"$1{masks}$2"),
+ 9 => Regex.Replace(str, "(.{2}).*(.{3})", $"$1{masks}$2"),
+ 8 => Regex.Replace(str, "(.{2}).*(.{2})", $"$1{masks}$2"),
+ 7 => Regex.Replace(str, "(.{1}).*(.{2})", $"$1{masks}$2"),
+ 6 => Regex.Replace(str, "(.{1}).*(.{1})", $"$1{masks}$2"),
+ _ => Regex.Replace(str, "(.{1}).*", $"$1{masks}")
+ };
+ }
+
+ ///
+ /// 身份证号掩码
+ ///
+ /// 身份证号
+ /// 掩码符
+ ///
+ public static string MaskIdCard(this string idCard, char mask = '*')
+ {
+ if (!idCard.TryValidate(ValidationTypes.IDCard).IsValid) return idCard;
+
+ var masks = mask.ToString().PadLeft(8, mask);
+ return Regex.Replace(idCard, @"^(.{6})(.*)(.{4})$", $"$1{masks}$3");
+ }
+
+ ///
+ /// 邮箱掩码
+ ///
+ /// 邮箱
+ /// 掩码符
+ ///
+ public static string MaskEmail(this string email, char mask = '*')
+ {
+ if (!email.TryValidate(ValidationTypes.EmailAddress).IsValid) return email;
+
+ var pos = email.IndexOf("@");
+ return Mask(email[..pos], mask) + email[pos..];
+ }
+
+ ///
+ /// 将字符串转为值类型,若没有得到或者错误返回为空
+ ///
+ /// 指定值类型
+ /// 传入字符串
+ /// 可空值
+ public static T? ParseTo(this string str) where T : struct
+ {
+ try
+ {
+ if (!string.IsNullOrWhiteSpace(str))
+ {
+ MethodInfo method = typeof(T).GetMethod("Parse", new Type[] { typeof(string) });
+ if (method != null)
+ {
+ T result = (T)method.Invoke(null, new string[] { str });
+ return result;
+ }
+ }
+ }
+ catch
+ {
+ }
+ return null;
+ }
+
+ ///
+ /// 将字符串转为值类型,若没有得到或者错误返回为空
+ ///
+ /// 传入字符串
+ /// 目标类型
+ /// 可空值
+ public static object ParseTo(this string str, Type type)
+ {
+ try
+ {
+ if (type.Name == "String")
+ return str;
+
+ if (!string.IsNullOrWhiteSpace(str))
+ {
+ var _type = type;
+ if (type.Name.StartsWith("Nullable"))
+ _type = type.GetGenericArguments()[0];
+
+ MethodInfo method = _type.GetMethod("Parse", new Type[] { typeof(string) });
+ if (method != null)
+ return method.Invoke(null, new string[] { str });
+ }
+ }
+ catch
+ {
+ }
+ return null;
+ }
+
+ ///
+ /// 将一个对象属性值赋给另一个指定对象属性, 只复制相同属性的
+ ///
+ /// 原数据对象
+ /// 目标数据对象
+ /// 属性集,键为原属性,值为目标属性
+ /// 属性集,目标不修改的属性
+ public static void CopyTo(object src, object target, Dictionary changeProperties = null, string[] unChangeProperties = null)
+ {
+ if (src == null || target == null)
+ throw new ArgumentException("src == null || target == null ");
+
+ var SourceType = src.GetType();
+ var TargetType = target.GetType();
+
+ if (changeProperties == null || changeProperties.Count == 0)
+ {
+ var fields = TargetType.GetProperties();
+ changeProperties = fields.Select(m => m.Name).ToDictionary(m => m);
+ }
+
+ if (unChangeProperties == null || unChangeProperties.Length == 0)
+ {
+ foreach (var item in changeProperties)
+ {
+ var srcProperty = SourceType.GetProperty(item.Key);
+ if (srcProperty != null)
+ {
+ var sourceVal = srcProperty.GetValue(src, null);
+
+ var tarProperty = TargetType.GetProperty(item.Value);
+ tarProperty?.SetValue(target, sourceVal, null);
+ }
+ }
+ }
+ else
+ {
+ foreach (var item in changeProperties)
+ {
+ if (!unChangeProperties.Any(m => m == item.Value))
+ {
+ var srcProperty = SourceType.GetProperty(item.Key);
+ if (srcProperty != null)
+ {
+ var sourceVal = srcProperty.GetValue(src, null);
+
+ var tarProperty = TargetType.GetProperty(item.Value);
+ tarProperty?.SetValue(target, sourceVal, null);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// 深复制
+ ///
+ /// 深复制源对象
+ /// 对象
+ ///
+ public static T DeepCopy(this T obj)
+ {
+ var jsonSettings = SetNewtonsoftJsonSetting();
+ var json = JSON.Serialize(obj, jsonSettings);
+ return JSON.Deserialize(json);
+ }
+
+ ///
+ /// 对带有特性字段进行脱敏处理
+ ///
+ public static T MaskSensitiveData(this T obj) where T : class
+ {
+ if (obj == null) return null;
+
+ var type = typeof(T);
+
+ // 获取或缓存属性集合
+ var properties = PropertyCache.GetOrAdd(type, t =>
+ t.GetProperties(BindingFlags.Public | BindingFlags.Instance)
+ .Where(p => p.PropertyType == typeof(string) && p.GetCustomAttribute() != null)
+ .ToArray());
+
+ // 并行处理可写属性
+ Parallel.ForEach(properties, prop =>
+ {
+ if (!prop.CanWrite) return;
+
+ // 获取或缓存特性
+ var maskAttr = AttributeCache.GetOrAdd(prop, p => p.GetCustomAttribute());
+
+ if (maskAttr == null) return;
+
+ // 处理非空字符串
+ if (prop.GetValue(obj) is string { Length: > 0 } value)
+ {
+ prop.SetValue(obj, maskAttr.Mask(value));
+ }
+ });
+
+ return obj;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET.Core/Extension/RepositoryExtension.cs b/Admin.NET.Core/Extension/RepositoryExtension.cs
new file mode 100644
index 0000000..e52918e
--- /dev/null
+++ b/Admin.NET.Core/Extension/RepositoryExtension.cs
@@ -0,0 +1,454 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using MapsterMapper;
+
+namespace Admin.NET.Core;
+
+public static class RepositoryExtension
+{
+ ///
+ /// 实体假删除 _rep.FakeDelete(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int FakeDelete(this ISugarRepository repository, T entity) where T : EntityBaseDel, new()
+ {
+ return repository.Context.FakeDelete(entity);
+ }
+
+ ///
+ /// 实体假删除 db.FakeDelete(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int FakeDelete(this ISqlSugarClient db, T entity) where T : EntityBaseDel, new()
+ {
+ return db.Updateable(entity).AS().ReSetValue(x => { x.IsDelete = true; })
+ .IgnoreColumns(ignoreAllNullColumns: true)
+ .EnableDiffLogEvent() // 记录差异日志
+ .UpdateColumns(x => new { x.IsDelete, x.DeleteTime, x.UpdateTime, x.UpdateUserId }) // 允许更新的字段-AOP拦截自动设置UpdateTime、UpdateUserId
+ .ExecuteCommand();
+ }
+
+ ///
+ /// 实体集合批量假删除 _rep.FakeDelete(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int FakeDelete(this ISugarRepository repository, List entity) where T : EntityBaseDel, new()
+ {
+ return repository.Context.FakeDelete(entity);
+ }
+
+ ///
+ /// 实体集合批量假删除 db.FakeDelete(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int FakeDelete(this ISqlSugarClient db, List entity) where T : EntityBaseDel, new()
+ {
+ return db.Updateable(entity).AS().ReSetValue(x => { x.IsDelete = true; })
+ .IgnoreColumns(ignoreAllNullColumns: true)
+ .EnableDiffLogEvent() // 记录差异日志
+ .UpdateColumns(x => new { x.IsDelete, x.DeleteTime, x.UpdateTime, x.UpdateUserId }) // 允许更新的字段-AOP拦截自动设置UpdateTime、UpdateUserId
+ .ExecuteCommand();
+ }
+
+ ///
+ /// 实体假删除异步 _rep.FakeDeleteAsync(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Task FakeDeleteAsync(this ISugarRepository repository, T entity) where T : EntityBaseDel, new()
+ {
+ return repository.Context.FakeDeleteAsync(entity);
+ }
+
+ ///
+ /// 实体假删除 db.FakeDelete(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Task FakeDeleteAsync(this ISqlSugarClient db, T entity) where T : EntityBaseDel, new()
+ {
+ return db.Updateable(entity).AS().ReSetValue(x => { x.IsDelete = true; })
+ .IgnoreColumns(ignoreAllNullColumns: true)
+ .EnableDiffLogEvent() // 记录差异日志
+ .UpdateColumns(x => new { x.IsDelete, x.DeleteTime, x.UpdateTime, x.UpdateUserId }) // 允许更新的字段-AOP拦截自动设置UpdateTime、UpdateUserId
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 实体集合批量假删除异步 _rep.FakeDeleteAsync(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Task FakeDeleteAsync(this ISugarRepository repository, List entity) where T : EntityBaseDel, new()
+ {
+ return repository.Context.FakeDeleteAsync(entity);
+ }
+
+ ///
+ /// 实体集合批量假删除 db.FakeDelete(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Task FakeDeleteAsync(this ISqlSugarClient db, List entity) where T : EntityBaseDel, new()
+ {
+ return db.Updateable(entity).AS().ReSetValue(x => { x.IsDelete = true; })
+ .IgnoreColumns(ignoreAllNullColumns: true)
+ .EnableDiffLogEvent() // 记录差异日志
+ .UpdateColumns(x => new { x.IsDelete, x.DeleteTime, x.UpdateTime, x.UpdateUserId }) // 允许更新的字段-AOP拦截自动设置UpdateTime、UpdateUserId
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 排序方式(默认降序)
+ ///
+ ///
+ ///
+ ///
+ /// 默认排序字段
+ /// 是否降序
+ ///
+ public static ISugarQueryable OrderBuilder(this ISugarQueryable queryable, BasePageInput pageInput, string prefix = "", string defaultSortField = "Id", bool descSort = true)
+ {
+ var iSqlBuilder = InstanceFactory.GetSqlBuilderWithContext(queryable.Context);
+
+ // 约定默认每张表都有Id排序
+ var orderStr = string.IsNullOrWhiteSpace(defaultSortField) ? "" : $"{prefix}{iSqlBuilder.GetTranslationColumnName(defaultSortField)}" + (descSort ? " Desc" : " Asc");
+
+ TypeAdapterConfig typeAdapterConfig = new();
+ typeAdapterConfig.ForType().IgnoreNullValues(true);
+ Mapper mapper = new(typeAdapterConfig); // 务必将mapper设为单实例
+ var nowPagerInput = mapper.Map(pageInput);
+ // 排序是否可用-排序字段为非空才启用排序,排序顺序默认为倒序
+ if (!string.IsNullOrEmpty(nowPagerInput.Field))
+ {
+ nowPagerInput.Field = Regex.Replace(nowPagerInput.Field, @"[\s;()\-'@=/%]", ""); //过滤掉一些关键字符防止构造特殊SQL语句注入
+ var orderByDbName = queryable.Context.EntityMaintenance.GetDbColumnName(nowPagerInput.Field);//防止注入,类中只要不存在属性名就会报错
+ orderStr = $"{prefix}{iSqlBuilder.GetTranslationColumnName(orderByDbName)} {(string.IsNullOrEmpty(nowPagerInput.Order) || nowPagerInput.Order.Equals(nowPagerInput.DescStr, StringComparison.OrdinalIgnoreCase) ? "Desc" : "Asc")}";
+ }
+ return queryable.OrderByIF(!string.IsNullOrWhiteSpace(orderStr), orderStr);
+ }
+
+ ///
+ /// 更新实体并记录差异日志 _rep.UpdateWithDiffLog(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int UpdateWithDiffLog(this ISugarRepository repository, T entity, bool ignoreAllNullColumns = true) where T : EntityBase, new()
+ {
+ return repository.Context.UpdateWithDiffLog(entity, ignoreAllNullColumns);
+ }
+
+ ///
+ /// 更新实体并记录差异日志 _rep.UpdateWithDiffLog(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int UpdateWithDiffLog(this ISqlSugarClient db, T entity, bool ignoreAllNullColumns = true) where T : EntityBase, new()
+ {
+ return db.Updateable(entity).AS()
+ .IgnoreColumns(ignoreAllNullColumns: ignoreAllNullColumns)
+ .EnableDiffLogEvent()
+ .ExecuteCommand();
+ }
+
+ ///
+ /// 更新实体并记录差异日志 _rep.UpdateWithDiffLogAsync(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Task UpdateWithDiffLogAsync(this ISugarRepository repository, T entity, bool ignoreAllNullColumns = true) where T : EntityBase, new()
+ {
+ return repository.Context.UpdateWithDiffLogAsync(entity, ignoreAllNullColumns);
+ }
+
+ ///
+ /// 更新实体并记录差异日志 _rep.UpdateWithDiffLogAsync(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Task UpdateWithDiffLogAsync(this ISqlSugarClient db, T entity, bool ignoreAllNullColumns = true) where T : EntityBase, new()
+ {
+ return db.Updateable(entity)
+ .IgnoreColumns(ignoreAllNullColumns: ignoreAllNullColumns)
+ .EnableDiffLogEvent()
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 新增实体并记录差异日志 _rep.InsertWithDiffLog(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int InsertWithDiffLog(this ISugarRepository repository, T entity) where T : EntityBase, new()
+ {
+ return repository.Context.InsertWithDiffLog(entity);
+ }
+
+ ///
+ /// 新增实体并记录差异日志 _rep.InsertWithDiffLog(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int InsertWithDiffLog(this ISqlSugarClient db, T entity) where T : EntityBase, new()
+ {
+ return db.Insertable(entity).AS().EnableDiffLogEvent().ExecuteCommand();
+ }
+
+ ///
+ /// 新增实体并记录差异日志 _rep.InsertWithDiffLogAsync(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Task InsertWithDiffLogAsync(this ISugarRepository repository, T entity) where T : EntityBase, new()
+ {
+ return repository.Context.InsertWithDiffLogAsync(entity);
+ }
+
+ ///
+ /// 新增实体并记录差异日志 _rep.InsertWithDiffLog(entity)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Task InsertWithDiffLogAsync(this ISqlSugarClient db, T entity) where T : EntityBase, new()
+ {
+ return db.Insertable(entity).AS().EnableDiffLogEvent().ExecuteCommandAsync();
+ }
+
+ ///
+ /// 多库查询
+ ///
+ ///
+ ///
+ public static ISugarQueryable AS(this ISugarQueryable queryable)
+ {
+ var info = GetTableInfo();
+ return queryable.AS($"{info.Item1}.{info.Item2}");
+ }
+
+ ///
+ /// 多库查询
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static ISugarQueryable AS(this ISugarQueryable queryable)
+ {
+ var info = GetTableInfo();
+ return queryable.AS($"{info.Item1}.{info.Item2}");
+ }
+
+ ///
+ /// 多库更新
+ ///
+ ///
+ ///
+ public static IUpdateable AS(this IUpdateable updateable) where T : EntityBase, new()
+ {
+ var info = GetTableInfo();
+ return updateable.AS($"{info.Item1}.{info.Item2}");
+ }
+
+ ///
+ /// 多库新增
+ ///
+ ///
+ ///
+ public static IInsertable AS(this IInsertable insertable) where T : EntityBase, new()
+ {
+ var info = GetTableInfo();
+ return insertable.AS($"{info.Item1}.{info.Item2}");
+ }
+
+ ///
+ /// 多库删除
+ ///
+ ///
+ ///
+ public static IDeleteable AS(this IDeleteable deleteable) where T : EntityBase, new()
+ {
+ var info = GetTableInfo();
+ return deleteable.AS($"{info.Item1}.{info.Item2}");
+ }
+
+ ///
+ /// 根据实体类型获取表信息
+ ///
+ ///
+ ///
+ private static Tuple GetTableInfo()
+ {
+ var entityType = typeof(T);
+ var attr = entityType.GetCustomAttribute();
+ var configId = attr == null ? SqlSugarConst.MainConfigId : attr.configId.ToString();
+ var tableName = entityType.GetCustomAttribute().TableName;
+ return new Tuple(configId, tableName);
+ }
+
+ ///
+ /// 禁用过滤器-适用于更新和删除操作(只对当前请求有效,禁止使用异步)
+ ///
+ ///
+ /// 禁止异步
+ ///
+ public static void RunWithoutFilter(this ISugarRepository repository, Action action)
+ {
+ repository.Context.QueryFilter.ClearAndBackup(); // 清空并备份过滤器
+ action.Invoke();
+ repository.Context.QueryFilter.Restore(); // 还原过滤器
+
+ // 用例
+ //_rep.RunWithoutFilter(() =>
+ //{
+ // 执行更新或者删除
+ // 禁止使用异步函数
+ //});
+ }
+
+ ///
+ /// 忽略租户
+ ///
+ ///
+ /// 是否忽略 默认true
+ ///
+ public static ISugarQueryable IgnoreTenant(this ISugarQueryable queryable, bool ignore = true)
+ {
+ return ignore ? queryable.ClearFilter() : queryable;
+ }
+
+ ///
+ /// 只更新某些列
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IUpdateable OnlyUpdateColumn(this IUpdateable updateable) where T : EntityBase, new() where R : class, new()
+ {
+ if (updateable.UpdateBuilder.UpdateColumns == null)
+ updateable.UpdateBuilder.UpdateColumns = new List();
+
+ foreach (PropertyInfo info in typeof(R).GetProperties())
+ {
+ // 判断是否是相同属性
+ if (typeof(T).GetProperty(info.Name) != null)
+ updateable.UpdateBuilder.UpdateColumns.Add(info.Name);
+ }
+ return updateable;
+ }
+
+ ///
+ /// 导航只更新(主表)某些列
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static UpdateNavRootOptions OnlyNavUpdateColumn(this T t, R r)
+ {
+ UpdateNavRootOptions uNOption = new UpdateNavRootOptions();
+ var updateColumns = new List();
+
+ foreach (PropertyInfo info in r.GetType().GetProperties())
+ {
+ //判断是否是相同属性
+ PropertyInfo pro = t.GetType().GetProperty(info.Name);
+ var attr = pro.GetCustomAttribute();
+ if (pro != null && attr != null && !attr.IsPrimaryKey)
+ updateColumns.Add(info.Name);
+ }
+ uNOption.UpdateColumns = updateColumns.ToArray();
+ return uNOption;
+ }
+
+ ///
+ /// 批量列表in查询
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task> BulkListQuery(this ISugarQueryable queryable,
+ Expression, bool>> exp,
+ IEnumerable queryList,
+ CancellationToken stoppingToken) where T1 : class, new()
+ {
+ // 创建临时表 (用真表兼容性好,表名随机)
+ var tableName = "Temp" + SnowFlakeSingle.Instance.NextId();
+ try
+ {
+ var type = queryable.Context.DynamicBuilder().CreateClass(tableName, new SugarTable())
+ .CreateProperty("ColumnName", typeof(string), new SugarColumn() { IsPrimaryKey = true }) // 主键不要自增
+ .BuilderType();
+ // 创建表
+ queryable.Context.CodeFirst.InitTables(type);
+ var insertData = queryList.Select(it => new SingleColumnEntity() { ColumnName = it }).ToList();
+ // 插入临时表
+ queryable.Context.Fastest