mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-04-20 05:02:50 +08:00
feat: ✨ 前端表格高级筛选 (#100)
* chore: 🔨 css 基础单位 [skip ci] * fix: 🐛 ca2263 System.Enum.GetValues<TEnum>() [skip ci] * feat: ✨ 前端表格高级筛选 [skip ci]
This commit is contained in:
parent
1dc953a2b2
commit
3847d6fdbb
@ -1,56 +1,58 @@
|
||||
# 此文件为 EditorConfig 配置文件,用于设置跨编辑器的代码格式化规则。
|
||||
# root = true 表示此文件是根配置文件。
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
ij_xml_attribute_wrap = off
|
||||
ij_xml_text_wrap = off
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = true
|
||||
charset = utf-8 # 文件字符集为 UTF-8
|
||||
end_of_line = lf # 行结束符为 LF
|
||||
ij_xml_attribute_wrap = off # IntelliJ IDEA 中 XML 属性不换行
|
||||
ij_xml_text_wrap = off # IntelliJ IDEA 中 XML 文本不换行
|
||||
indent_size = 4 # 缩进大小为 4 个空格
|
||||
indent_style = space # 使用空格进行缩进
|
||||
insert_final_newline = false # 不在文件末尾插入空行
|
||||
trim_trailing_whitespace = true # 删除行尾的空格
|
||||
|
||||
[{*.json,*.yml}]
|
||||
indent_size = 2
|
||||
indent_size = 2 # 对于 JSON 和 YAML 文件,缩进大小为 2 个空格
|
||||
|
||||
[*.cs]
|
||||
dotnet_analyzer_diagnostic.severity = warning
|
||||
dotnet_analyzer_diagnostic.severity = warning # 设置 C# 文件中所有 dotnet_analyzer_diagnostic 的严重性级别为 warning
|
||||
|
||||
# ReSharper properties
|
||||
resharper_align_linq_query = true
|
||||
resharper_align_multiline_argument = true
|
||||
resharper_align_multiline_array_and_object_initializer = true
|
||||
resharper_align_multiline_binary_patterns = true
|
||||
resharper_align_multiline_calls_chain = true
|
||||
resharper_align_multiline_extends_list = true
|
||||
resharper_align_multiline_parameter = true
|
||||
resharper_align_multiline_property_pattern = true
|
||||
resharper_align_multiline_switch_expression = true
|
||||
resharper_align_multiple_declaration = true
|
||||
resharper_align_multline_type_parameter_constrains = true
|
||||
resharper_align_multline_type_parameter_list = true
|
||||
resharper_align_tuple_components = true
|
||||
resharper_allow_comment_after_lbrace = true
|
||||
resharper_blank_lines_before_single_line_comment = 1
|
||||
resharper_csharp_empty_block_style = together_same_line
|
||||
resharper_csharp_outdent_commas = true
|
||||
resharper_csharp_place_type_constraints_on_same_line = false
|
||||
resharper_csharp_stick_comment = false
|
||||
resharper_csharp_wrap_before_comma = true
|
||||
resharper_indent_nested_for_stmt = true
|
||||
resharper_indent_nested_foreach_stmt = true
|
||||
resharper_indent_nested_while_stmt = true
|
||||
resharper_indent_preprocessor_if = usual_indent
|
||||
resharper_indent_preprocessor_other = usual_indent
|
||||
resharper_int_align = true
|
||||
resharper_keep_existing_arrangement = false
|
||||
resharper_place_linq_into_on_new_line = false
|
||||
resharper_place_simple_embedded_statement_on_same_line = false
|
||||
resharper_place_simple_switch_expression_on_single_line = true
|
||||
resharper_wrap_before_eq = true
|
||||
resharper_wrap_chained_method_calls = chop_if_long
|
||||
resharper_wrap_switch_expression = chop_if_long
|
||||
resharper_align_linq_query = true # 启用对LINQ查询的对齐
|
||||
resharper_align_multiline_argument = true # 启用多行参数的对齐
|
||||
resharper_align_multiline_array_and_object_initializer = true # 启用多行数组和对象初始化器的对齐
|
||||
resharper_align_multiline_binary_patterns = true # 启用多行二元模式的对齐
|
||||
resharper_align_multiline_calls_chain = true # 启用多行调用链的对齐
|
||||
resharper_align_multiline_extends_list = true # 启用多行扩展列表的对齐
|
||||
resharper_align_multiline_parameter = true # 启用多行参数的对齐
|
||||
resharper_align_multiline_property_pattern = true # 启用多行属性模式的对齐
|
||||
resharper_align_multiline_switch_expression = true # 启用多行切换表达式的对齐
|
||||
resharper_align_multiple_declaration = true # 启用多个声明的对齐
|
||||
resharper_align_multline_type_parameter_constrains = true # 启用多行类型参数约束的对齐
|
||||
resharper_align_multline_type_parameter_list = true # 启用多行类型参数列表的对齐
|
||||
resharper_align_tuple_components = true # 启用元组组件的对齐
|
||||
resharper_allow_comment_after_lbrace = true # 允许在大括号前添加注释
|
||||
resharper_blank_lines_before_single_line_comment = 1 # 在单行注释前添加空行
|
||||
resharper_csharp_empty_block_style = together_same_line # 设置空块的样式为“在一起,在同一行”
|
||||
resharper_csharp_outdent_commas = true # 是否将逗号后的代码退缩
|
||||
resharper_csharp_place_type_constraints_on_same_line = false # 在类型约束上是否保持在同一行
|
||||
resharper_csharp_stick_comment = false # 是否将注释粘贴在代码行的末尾
|
||||
resharper_csharp_wrap_before_comma = true # 在逗号前是否添加换行
|
||||
resharper_indent_nested_for_stmt = true # 是否对嵌套的for语句进行缩进
|
||||
resharper_indent_nested_foreach_stmt = true # 是否对嵌套的foreach语句进行缩进
|
||||
resharper_indent_nested_while_stmt = true # 是否对嵌套的while语句进行缩进
|
||||
resharper_indent_preprocessor_if = usual_indent # 设置预处理器指令`if`的缩进方式
|
||||
resharper_indent_preprocessor_other = usual_indent # 设置其他预处理器指令的缩进方式
|
||||
resharper_int_align = true # 启用整数对齐
|
||||
resharper_keep_existing_arrangement = false # 在重新排列时是否保留现有的布局
|
||||
resharper_place_linq_into_on_new_line = false # 是否将LINQ表达式放在新行
|
||||
resharper_place_simple_embedded_statement_on_same_line = false # 是否将简单的嵌入式语句放在同一行
|
||||
resharper_place_simple_switch_expression_on_single_line = true # 是否将简单的切换表达式放在单行
|
||||
resharper_wrap_before_eq = true # 在等号前是否添加换行
|
||||
resharper_wrap_chained_method_calls = chop_if_long # 是否拆分链式方法调用
|
||||
resharper_wrap_switch_expression = chop_if_long # 是否拆分切换表达式
|
||||
|
||||
# Microsoft .NET properties
|
||||
csharp_indent_braces = false
|
||||
csharp_new_line_before_open_brace = local_functions, methods, types
|
||||
csharp_indent_braces = false # 设置为false表示花括号不跟随代码行缩进
|
||||
csharp_new_line_before_open_brace = local_functions, methods, types # 这里设置为local_functions, methods, types,表示在局部函数、方法和类型定义的开放花括号前应换行
|
@ -25,7 +25,7 @@
|
||||
<Title>$(AssemblyName)</Title>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MinVer" Version="5.0.0-beta.1">
|
||||
<PackageReference Include="MinVer" Version="5.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:9.0.0-preview.1 AS base
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:9.0.0-preview.3 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 8080
|
||||
RUN apt update
|
||||
|
@ -5,6 +5,7 @@
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/ReSpeller/ReSpellerEnabled/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Aigc/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Biji/@EntryIndexedValue">True</s:Boolean>
|
||||
@ -19,10 +20,15 @@
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Decaptcha/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Depts/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=FFFFFF/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=FLG/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=FLGL/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Furion/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=GETDATE/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Haojia/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Meituan/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=PWD/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=RGX/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=RGXL/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Responsing/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Smzdm/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tabao/@EntryIndexedValue">True</s:Boolean>
|
||||
@ -71,12 +77,14 @@
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /></s:String>
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_RECORD_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue"><Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=236f7aa5_002D7b06_002D43ca_002Dbf2a_002D9b31bfcff09a/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="AA_BB" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=669e5282_002Dfb4b_002D4e90_002D91e7_002D07d269d04b60/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a0b4bc4d_002Dd13b_002D4a37_002Db37e_002Dc9c6864e4302/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"><ElementKinds><Kind Name="NAMESPACE" /><Kind Name="CLASS" /><Kind Name="STRUCT" /><Kind Name="ENUM" /><Kind Name="DELEGATE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=c873eafb_002Dd57f_002D481d_002D8c93_002D77f6863c2f88/@EntryIndexedValue"><Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String>
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue"><?xml version="1.0" encoding="utf-16"?>
|
||||
<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns">
|
||||
|
@ -84,5 +84,6 @@
|
||||
重设密码
|
||||
链接
|
||||
错误
|
||||
随机排序
|
||||
顺序排序
|
||||
高中
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"cz-git": "^1.8.0",
|
||||
"cz-git": "^1.9.1",
|
||||
"commitizen": "^4.3.0",
|
||||
"prettier": "^3.2.5",
|
||||
"standard-version": "^9.5.0"
|
||||
|
@ -10,6 +10,7 @@ while ($null -eq $types[$prefix])
|
||||
$prefix = Read-Host "请选择版本类型`n" $( & { param($i) $i | ForEach-Object { "$_ : $( $types[$_][0] )($( $types[$_][1] ))`n" } } $types.Keys | Sort-Object )
|
||||
}
|
||||
git checkout main
|
||||
git pull
|
||||
git branch -D release
|
||||
git checkout -b release
|
||||
./node_modules/.bin/standard-version -r $types[$prefix][0]
|
||||
|
@ -10,11 +10,11 @@
|
||||
"packages": [
|
||||
{
|
||||
"packageName": "FreeSql.NS",
|
||||
"version": "3.2.802-preview20231010-ns1"
|
||||
"version": "3.2.821-ns1"
|
||||
},
|
||||
{
|
||||
"packageName": "FreeSql.DbContext.NS",
|
||||
"version": "3.2.802-preview20231010-ns1"
|
||||
"version": "3.2.821-ns1"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
"packages": [
|
||||
{
|
||||
"packageName": "Furion.Pure.NS",
|
||||
"version": "4.9.1.31-ns2"
|
||||
"version": "4.9.2.19-ns3"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -27,6 +27,11 @@ public interface ICrudModule<in TCreateReq, TCreateRsp, TQueryReq, TQueryRsp, in
|
||||
/// </summary>
|
||||
Task<int> BulkDeleteAsync(BulkReq<TDelReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 实体计数
|
||||
/// </summary>
|
||||
Task<long> CountAsync(QueryReq<TQueryReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 创建实体
|
||||
/// </summary>
|
||||
|
@ -6,10 +6,7 @@ namespace NetAdmin.Application.Repositories;
|
||||
/// <summary>
|
||||
/// 默认仓储
|
||||
/// </summary>
|
||||
public sealed class DefaultRepository<TEntity>(
|
||||
IFreeSql fSql //
|
||||
, UnitOfWorkManager uowManger //
|
||||
, ContextUserToken userToken) //
|
||||
public sealed class DefaultRepository<TEntity>(IFreeSql fSql, UnitOfWorkManager uowManger, ContextUserToken userToken)
|
||||
: DefaultRepository<TEntity, long>(fSql, uowManger)
|
||||
where TEntity : EntityBase
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ public static class ServiceCollectionExtensions
|
||||
(Startup.Args.InsertSeedData ? FreeSqlInitMethods.InsertSeedData : FreeSqlInitMethods.None), freeSql => {
|
||||
// 数据权限过滤器
|
||||
_ = freeSql.GlobalFilter.ApplyOnlyIf<IFieldOwner>( //
|
||||
Chars.FLG_GLOBAL_FILTER_DATA
|
||||
Chars.FLG_FREE_SQL_GLOBAL_FILTER_DATA
|
||||
, () => ContextUserInfo.Create()?.Roles.All(x => x.DataScope == DataScopes.Self) ?? false
|
||||
, a => a.OwnerId == ContextUserInfo.Create().Id);
|
||||
});
|
||||
|
@ -26,17 +26,17 @@ namespace NetAdmin.BizServer.Host
|
||||
/// <summary>
|
||||
/// 配置应用程序中间件
|
||||
/// </summary>
|
||||
public void Configure(IApplicationBuilder app)
|
||||
public void Configure(IApplicationBuilder app, IHostApplicationLifetime lifeTime)
|
||||
{
|
||||
_ = app //
|
||||
.UseRealIp() // 使用RealIp中间件,用于获取真实客户端IP地址
|
||||
.EnableBuffering() // 启用请求体缓冲,允许多次读取请求体
|
||||
.UseMiddleware<RequestAuditMiddleware>() // 使用RequestAuditMiddleware中间件,执行请求审计
|
||||
_ = app //
|
||||
.UseMiddleware<SafetyShopHostMiddleware>() // 安全停机中间件
|
||||
.EnableBuffering() // 启用请求体缓冲,允许多次读取请求体
|
||||
.UseMiddleware<RequestAuditMiddleware>() // 使用RequestAuditMiddleware中间件,执行请求审计
|
||||
#if DEBUG
|
||||
.UseOpenApiSkin() // 使用OpenApiSkin中间件(仅在调试模式下),提供Swagger UI皮肤
|
||||
#else
|
||||
.UseVueAdmin() // 托管管理后台,仅在非调试模式下
|
||||
.UseHttpMetrics() // 使用HttpMetrics中间件,启用HTTP性能监控
|
||||
.UseVueAdmin() // 托管管理后台,仅在非调试模式下
|
||||
.UseHttpMetrics() // 使用HttpMetrics中间件,启用HTTP性能监控
|
||||
#endif
|
||||
.UseInject(string.Empty) // 使用Inject中间件,Furion脚手架的依赖注入支持
|
||||
.UseUnifyResultStatusCodes() // 使用UnifyResultStatusCodes中间件,用于统一处理结果状态码
|
||||
@ -46,6 +46,7 @@ namespace NetAdmin.BizServer.Host
|
||||
.UseAuthorization() // 使用Authorization中间件,启用授权
|
||||
.UseMiddleware<RemoveNullNodeMiddleware>() // 使用RemoveNullNodeMiddleware中间件,删除JSON中的空节点
|
||||
.UseEndpoints(); // 配置端点以处理请求
|
||||
_ = lifeTime.ApplicationStopping.Register(SafetyShopHostMiddleware.OnStopping);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -19,8 +19,8 @@ namespace NetAdmin.BizServer.Tests;
|
||||
/// 所有测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper) :
|
||||
WebApiTestBase<Startup>(factory, testOutputHelper), IToolsModule, ICacheModule, IApiModule, IConfigModule
|
||||
public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IToolsModule, ICacheModule, IApiModule, IConfigModule
|
||||
|
||||
{
|
||||
/// <inheritdoc cref="ICrudModule{TCreateReq,TCreateRsp,TQueryReq,TQueryRsp,TUpdateReq,TUpdateRsp,TDelReq}.BulkDeleteAsync" />
|
||||
@ -38,6 +38,18 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryConfigReq> req)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryConfigRsp> CreateAsync(CreateConfigReq req)
|
||||
{
|
||||
|
@ -41,7 +41,12 @@ public abstract class DistributedCache<TService>(IDistributedCache cache, TServi
|
||||
protected async Task<T> GetAsync<T>(string key)
|
||||
{
|
||||
var cacheRead = await Cache.GetStringAsync(key).ConfigureAwait(false);
|
||||
return cacheRead != null ? cacheRead.ToObject<T>() : default;
|
||||
try {
|
||||
return cacheRead != null ? cacheRead.ToObject<T>() : default;
|
||||
}
|
||||
catch (JsonException) {
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -10,7 +10,7 @@ public sealed class ChineseNameAttribute : RegexAttribute
|
||||
/// Initializes a new instance of the <see cref="ChineseNameAttribute" /> class.
|
||||
/// </summary>
|
||||
public ChineseNameAttribute() //
|
||||
: base(Chars.RGX_CHINESE_NAME)
|
||||
: base(Chars.RGXL_CHINESE_NAME)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.中文姓名);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
|
@ -10,7 +10,7 @@ public sealed class CronAttribute : RegexAttribute
|
||||
/// Initializes a new instance of the <see cref="CronAttribute" /> class.
|
||||
/// </summary>
|
||||
public CronAttribute() //
|
||||
: base(Chars.RGX_CRON)
|
||||
: base(Chars.RGXL_CRON)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.时间表达式);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
|
@ -10,7 +10,7 @@ public sealed class EmailAttribute : RegexAttribute
|
||||
/// Initializes a new instance of the <see cref="EmailAttribute" /> class.
|
||||
/// </summary>
|
||||
public EmailAttribute() //
|
||||
: base(Chars.RGX_EMAIL)
|
||||
: base(Chars.RGXL_EMAIL)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.电子邮箱);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// Api接口表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Api))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_Api))]
|
||||
public record Sys_Api : ImmutableEntity<string>, IFieldSummary
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 配置表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Config))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_Config))]
|
||||
public record Sys_Config : VersionEntity, IFieldEnabled
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 部门表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Dept))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_Dept))]
|
||||
public record Sys_Dept : VersionEntity, IFieldEnabled, IFieldSummary, IFieldSort
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 字典目录表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_DicCatalog))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_DicCatalog))]
|
||||
[Index($"idx_{{tablename}}_{nameof(Code)}", nameof(Code), true)]
|
||||
public record Sys_DicCatalog : VersionEntity
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 字典内容表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_DicContent))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_DicContent))]
|
||||
[Index($"idx_{{tablename}}_{nameof(CatalogId)}_{nameof(Key)}", $"{nameof(CatalogId)},{nameof(Key)}", true)]
|
||||
[Index($"idx_{{tablename}}_{nameof(CatalogId)}_{nameof(Value)}", $"{nameof(CatalogId)},{nameof(Value)}", true)]
|
||||
public record Sys_DicContent : VersionEntity
|
||||
|
@ -8,7 +8,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 计划作业表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Job))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_Job))]
|
||||
public record Sys_Job : VersionEntity, IFieldEnabled, IFieldSummary
|
||||
{
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 计划作业执行记录表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_JobRecord))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_JobRecord))]
|
||||
[Index($"idx_{{tablename}}_{nameof(JobId)}_{nameof(TimeId)}", $"{nameof(JobId)},{nameof(TimeId)}", true)]
|
||||
public record Sys_JobRecord : LiteImmutableEntity
|
||||
{
|
||||
|
@ -7,7 +7,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 菜单表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Menu))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_Menu))]
|
||||
[Index($"idx_{{tablename}}_{nameof(Name)}", nameof(Name), true)]
|
||||
public record Sys_Menu : VersionEntity, IFieldSort
|
||||
{
|
||||
|
@ -6,7 +6,9 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 请求日志表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RequestLog))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_RequestLog))]
|
||||
[Index($"idx_{{tablename}}_{nameof(ApiId)}", nameof(ApiId), false)]
|
||||
[Index($"idx_{{tablename}}_{nameof(CreatedTime)}", nameof(CreatedTime), false)]
|
||||
public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -8,7 +8,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 角色表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Role))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_Role))]
|
||||
[Index("idx_{tablename}_01", nameof(Name), true)]
|
||||
public record Sys_Role : VersionEntity, IFieldSort, IFieldEnabled, IFieldSummary, IRegister
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 角色-接口映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleApi))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_RoleApi))]
|
||||
public record Sys_RoleApi : ImmutableEntity
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 角色-部门映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleDept))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_RoleDept))]
|
||||
[Index($"idx_{{tablename}}_{nameof(RoleId)}_{nameof(DeptId)}", $"{nameof(RoleId)},{nameof(DeptId)}", true)]
|
||||
public record Sys_RoleDept : ImmutableEntity
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 角色-菜单映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleMenu))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_RoleMenu))]
|
||||
[Index($"idx_{{tablename}}_{nameof(RoleId)}_{nameof(MenuId)}", $"{nameof(RoleId)},{nameof(MenuId)}", true)]
|
||||
public record Sys_RoleMenu : ImmutableEntity
|
||||
{
|
||||
|
@ -8,7 +8,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 站内信表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_SiteMsg))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_SiteMsg))]
|
||||
public record Sys_SiteMsg : VersionEntity, IRegister, IFieldSummary
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 站内信-部门映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_SiteMsgDept))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_SiteMsgDept))]
|
||||
[Index($"idx_{{tablename}}_{nameof(DeptId)}_{nameof(SiteMsgId)}", $"{nameof(DeptId)},{nameof(SiteMsgId)}", true)]
|
||||
public record Sys_SiteMsgDept : ImmutableEntity
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 站内信标记表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_SiteMsgFlag))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_SiteMsgFlag))]
|
||||
[Index($"idx_{{tablename}}_{nameof(SiteMsgId)}_{nameof(UserId)}", $"{nameof(SiteMsgId)},{nameof(UserId)}", true)]
|
||||
public record Sys_SiteMsgFlag : MutableEntity
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 站内信-角色映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_SiteMsgRole))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_SiteMsgRole))]
|
||||
[Index($"idx_{{tablename}}_{nameof(RoleId)}_{nameof(SiteMsgId)}", $"{nameof(RoleId)},{nameof(SiteMsgId)}", true)]
|
||||
public record Sys_SiteMsgRole : ImmutableEntity
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 站内信-用户映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_SiteMsgUser))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_SiteMsgUser))]
|
||||
[Index($"idx_{{tablename}}_{nameof(UserId)}_{nameof(SiteMsgId)}", $"{nameof(UserId)},{nameof(SiteMsgId)}", true)]
|
||||
public record Sys_SiteMsgUser : ImmutableEntity
|
||||
{
|
||||
|
@ -7,7 +7,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 用户基本信息表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_User))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_User))]
|
||||
[Index($"idx_{{tablename}}_{nameof(UserName)}", nameof(UserName), true)]
|
||||
[Index($"idx_{{tablename}}_{nameof(Mobile)}", nameof(Mobile), true)]
|
||||
[Index($"idx_{{tablename}}_{nameof(Email)}", nameof(Email), true)]
|
||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 用户档案表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_UserProfile))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_UserProfile))]
|
||||
public record Sys_UserProfile : VersionEntity, IRegister
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 用户-角色映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_UserRole))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_UserRole))]
|
||||
public record Sys_UserRole : VersionEntity
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
/// <summary>
|
||||
/// 验证码表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_VerifyCode))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_VerifyCode))]
|
||||
public record Sys_VerifyCode : VersionEntity
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -5,5 +5,5 @@ namespace NetAdmin.Domain.DbMaps.Tpl;
|
||||
/// <summary>
|
||||
/// 示例表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Tpl_Example))]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Tpl_Example))]
|
||||
public record Tpl_Example : VersionEntity;
|
@ -11,6 +11,6 @@ public sealed record BulkReq<T> : DataAbstraction
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.请求对象不能为空))]
|
||||
[MinLength(1)]
|
||||
[MaxLength(Numbers.BULK_REQ_LIMIT)]
|
||||
[MaxLength(Numbers.MAX_LIMIT_BULK_REQ)]
|
||||
public IEnumerable<T> Items { get; init; }
|
||||
}
|
@ -7,10 +7,10 @@ public sealed record PagedQueryReq<T> : QueryReq<T>, IPagedInfo
|
||||
where T : DataAbstraction, new()
|
||||
{
|
||||
/// <inheritdoc cref="IPagedInfo.Page" />
|
||||
[Range(1, Numbers.QUERY_MAX_PAGE_NO)]
|
||||
[Range(1, Numbers.MAX_LIMIT_QUERY_PAGE_NO)]
|
||||
public int Page { get; init; } = 1;
|
||||
|
||||
/// <inheritdoc cref="IPagedInfo.PageSize" />
|
||||
[Range(1, Numbers.QUERY_MAX_PAGE_SIZE)]
|
||||
public int PageSize { get; init; } = Numbers.QUERY_DEF_PAGE_SIZE;
|
||||
[Range(1, Numbers.MAX_LIMIT_QUERY_PAGE_SIZE)]
|
||||
public int PageSize { get; init; } = Numbers.DEF_PAGE_SIZE_QUERY;
|
||||
}
|
@ -9,8 +9,8 @@ public record QueryReq<T> : DataAbstraction
|
||||
/// <summary>
|
||||
/// 取前n条
|
||||
/// </summary>
|
||||
[Range(1, Numbers.QUERY_LIMIT)]
|
||||
public int Count { get; init; } = Numbers.QUERY_LIMIT;
|
||||
[Range(1, Numbers.MAX_LIMIT_QUERY)]
|
||||
public int Count { get; init; } = Numbers.MAX_LIMIT_QUERY;
|
||||
|
||||
/// <summary>
|
||||
/// 动态查询条件
|
||||
|
@ -21,6 +21,16 @@ public sealed record GetAllEntriesRsp : DataAbstraction
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绝对过期时间
|
||||
/// </summary>
|
||||
public DateTime? AbsExpTime => AbsExp == -1 ? null : DateTime.FromBinary(AbsExp).ToLocalTime();
|
||||
|
||||
/// <summary>
|
||||
/// 滑动过期时间
|
||||
/// </summary>
|
||||
public DateTime? SldExpTime => SldExp == -1 ? null : DateTime.FromBinary(SldExp).ToLocalTime();
|
||||
|
||||
/// <summary>
|
||||
/// 绝对过期时间
|
||||
/// </summary>
|
||||
|
@ -10,6 +10,10 @@ namespace NetAdmin.Domain.Dto.Sys.Config;
|
||||
/// </summary>
|
||||
public sealed record QueryConfigRsp : Sys_Config
|
||||
{
|
||||
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override DateTime CreatedTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override bool Enabled { get; init; }
|
||||
|
@ -17,7 +17,7 @@ public record CreateSiteMsgReq : Sys_SiteMsg
|
||||
/// 部门编号列表
|
||||
/// </summary>
|
||||
[MinLength(1)]
|
||||
[MaxLength(Numbers.BULK_REQ_LIMIT)]
|
||||
[MaxLength(Numbers.MAX_LIMIT_BULK_REQ)]
|
||||
public IReadOnlyCollection<long> DeptIds { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_SiteMsg.MsgType" />
|
||||
@ -30,7 +30,7 @@ public record CreateSiteMsgReq : Sys_SiteMsg
|
||||
/// 角色编号列表
|
||||
/// </summary>
|
||||
[MinLength(1)]
|
||||
[MaxLength(Numbers.BULK_REQ_LIMIT)]
|
||||
[MaxLength(Numbers.MAX_LIMIT_BULK_REQ)]
|
||||
public IReadOnlyCollection<long> RoleIds { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_SiteMsg.Title" />
|
||||
@ -42,6 +42,6 @@ public record CreateSiteMsgReq : Sys_SiteMsg
|
||||
/// 用户编号列表
|
||||
/// </summary>
|
||||
[MinLength(1)]
|
||||
[MaxLength(Numbers.BULK_REQ_LIMIT)]
|
||||
[MaxLength(Numbers.MAX_LIMIT_BULK_REQ)]
|
||||
public IReadOnlyCollection<long> UserIds { get; init; }
|
||||
}
|
@ -21,6 +21,10 @@ public sealed record QuerySiteMsgRsp : Sys_SiteMsg
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override DateTime CreatedTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldCreatedUser.CreatedUserName" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string CreatedUserName { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_SiteMsg.Depts" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public new IEnumerable<QueryDeptRsp> Depts { get; init; }
|
||||
|
@ -43,7 +43,7 @@ public abstract record CreateUpdateUserReq : Sys_User
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.角色编号列表不能为空))]
|
||||
[MinLength(1)]
|
||||
[MaxLength(Numbers.BULK_REQ_LIMIT)]
|
||||
[MaxLength(Numbers.MAX_LIMIT_BULK_REQ)]
|
||||
public IReadOnlyCollection<long> RoleIds { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_User.Summary" />
|
||||
|
@ -21,7 +21,7 @@ public sealed record LoginRsp : DataAbstraction
|
||||
public void SetToRspHeader()
|
||||
{
|
||||
// 设置响应报文头
|
||||
App.HttpContext.Response.Headers[Chars.FLG_ACCESS_TOKEN] = AccessToken;
|
||||
App.HttpContext.Response.Headers[Chars.FLG_X_ACCESS_TOKEN] = RefreshToken;
|
||||
App.HttpContext.Response.Headers[Chars.FLG_HTTP_HEADER_VALUE_ACCESS_TOKEN] = AccessToken;
|
||||
App.HttpContext.Response.Headers[Chars.FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN] = RefreshToken;
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ public sealed record SqlCommandAfterEvent : SqlCommandBeforeEvent
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "SQL-{0}: {2} ms {1}", Id, Sql, ElapsedMicroseconds / 1000);
|
||||
return string.Format(CultureInfo.InvariantCulture, "SQL-{0}: {2} ms {1}", Id
|
||||
, Sql?.Sub(0, Numbers.MAX_LIMIT_PRINT_LEN_SQL), ElapsedMicroseconds / 1000);
|
||||
}
|
||||
}
|
@ -40,9 +40,9 @@ public abstract class WorkBase<TLogger>
|
||||
/// </summary>
|
||||
protected Task<IRedLock> GetLockerAsync(string lockId)
|
||||
{
|
||||
return _redLocker.RedLockFactory.CreateLockAsync(lockId, TimeSpan.FromSeconds(Numbers.RED_LOCK_EXPIRY_TIME_SECS)
|
||||
, TimeSpan.FromSeconds(Numbers.RED_LOCK_WAIT_TIME_SECS)
|
||||
, TimeSpan.FromSeconds(Numbers.RED_LOCK_RETRY_TIME_SECS));
|
||||
return _redLocker.RedLockFactory.CreateLockAsync(lockId, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_EXPIRY)
|
||||
, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_WAIT)
|
||||
, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_RETRY));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Host.Controllers;
|
||||
/// <summary>
|
||||
/// 控制器基类
|
||||
/// </summary>
|
||||
public abstract class ControllerBase<TCache, TService>(TCache cache) : IDynamicApiController
|
||||
public abstract class ControllerBase<TCache, TService>(TCache cache = default) : IDynamicApiController
|
||||
where TCache : ICache<IDistributedCache, TService> //
|
||||
where TService : IService
|
||||
{
|
||||
|
@ -1,24 +0,0 @@
|
||||
using NetAdmin.Application.Services;
|
||||
using NetAdmin.Cache;
|
||||
|
||||
namespace NetAdmin.Host.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 健康控制器
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings("Health")]
|
||||
public sealed class HealthController(ICache<IDistributedCache, IService> cache)
|
||||
: ControllerBase<ICache<IDistributedCache, IService>, IService>(cache)
|
||||
{
|
||||
/// <summary>
|
||||
/// 健康检查
|
||||
/// </summary>
|
||||
[AllowAnonymous]
|
||||
[HttpGet]
|
||||
#pragma warning disable CA1822, S3400
|
||||
public string Check()
|
||||
#pragma warning restore S3400, CA1822
|
||||
{
|
||||
return GlobalStatic.ProductVersion;
|
||||
}
|
||||
}
|
28
src/backend/NetAdmin.Host/Controllers/ProbeController.cs
Normal file
28
src/backend/NetAdmin.Host/Controllers/ProbeController.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using NetAdmin.Application.Services;
|
||||
using NetAdmin.Cache;
|
||||
using NetAdmin.Host.Middlewares;
|
||||
|
||||
namespace NetAdmin.Host.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 探针组件
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings("Probe")]
|
||||
public sealed class ProbeController : ControllerBase<ICache<IDistributedCache, IService>, IService>
|
||||
{
|
||||
/// <summary>
|
||||
/// 健康检查
|
||||
/// </summary>
|
||||
[AllowAnonymous]
|
||||
[HttpGet]
|
||||
#pragma warning disable CA1822, S3400
|
||||
public object HealthCheck()
|
||||
#pragma warning restore S3400, CA1822
|
||||
{
|
||||
return new {
|
||||
HostName = Environment.MachineName
|
||||
, CurrentConnections = SafetyShopHostMiddleware.Connections
|
||||
, GlobalStatic.ProductVersion
|
||||
};
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ public static class HttpContextExtensions
|
||||
public static async Task RemoveJsonNodeWithNullValueAsync(this HttpContext me)
|
||||
{
|
||||
// 非json格式,退出
|
||||
if (!(me.Response.ContentType?.Contains(Chars.FLG_APPLICATION_JSON) ?? false)) {
|
||||
if (!(me.Response.ContentType?.Contains(Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_JSON) ?? false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
#if DEBUG
|
||||
using IGeekFan.AspNetCore.Knife4jUI;
|
||||
|
||||
@ -42,16 +41,4 @@ public static class IApplicationBuilderExtensions
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 获取客户端真实Ip
|
||||
/// </summary>
|
||||
public static IApplicationBuilder UseRealIp(this IApplicationBuilder me)
|
||||
{
|
||||
return me.UseForwardedHeaders(new ForwardedHeadersOptions //
|
||||
{
|
||||
ForwardedHeaders = ForwardedHeaders.XForwardedFor |
|
||||
ForwardedHeaders.XForwardedProto
|
||||
});
|
||||
}
|
||||
}
|
@ -105,8 +105,7 @@ public static class ServiceCollectionExtensions
|
||||
public static IServiceCollection AddConsoleFormatter(this IServiceCollection me)
|
||||
{
|
||||
return me.AddConsoleFormatter(options => {
|
||||
var logLevels = Enum.GetValues<LogLevels>()
|
||||
.ToDictionary(x => x, x => x.GetDisplay());
|
||||
var logLevels = Enum.GetValues<LogLevels>().ToDictionary(x => x, x => x.GetDisplay());
|
||||
|
||||
#if DEBUG
|
||||
options.WriteHandler = (message, _, _, _, _) => {
|
||||
@ -242,11 +241,6 @@ public static class ServiceCollectionExtensions
|
||||
, LogMessage message //
|
||||
, Dictionary<LogLevels, DisplayAttribute> logLevels)
|
||||
{
|
||||
// 日志过长
|
||||
if (msg.Length > Numbers.CONSOLE_LINE_LEN_LIMIT) {
|
||||
msg = $"{Ln.日志长度超过限制} {Numbers.CONSOLE_LINE_LEN_LIMIT}";
|
||||
}
|
||||
|
||||
msg = _consoleColors.Aggregate( //
|
||||
msg, (current, regex) => regex.Key.Replace(current, regex.Value));
|
||||
msg = msg.ReplaceLineEndings(string.Empty);
|
||||
|
@ -23,12 +23,12 @@ public abstract class ApiResultHandler<T>
|
||||
/// </summary>
|
||||
public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)
|
||||
{
|
||||
var lineException = context.Exception switch { NetAdminException ex => ex, _ => null };
|
||||
var errorCode = lineException?.Code ?? ErrorCodes.Unhandled;
|
||||
var naException = context.Exception switch { NetAdminException ex => ex, _ => null };
|
||||
var errorCode = naException?.Code ?? ErrorCodes.Unhandled;
|
||||
var result = RestfulResult(errorCode, metadata.Data
|
||||
, lineException is NetAdminValidateException vEx
|
||||
, naException is NetAdminValidateException vEx
|
||||
? vEx.ValidateResults
|
||||
: lineException?.Message ?? errorCode.ResDesc<ErrorCodes>());
|
||||
: naException?.Message ?? errorCode.ResDesc<ErrorCodes>());
|
||||
|
||||
SetErrorCodeToHeader(context.HttpContext, errorCode);
|
||||
|
||||
|
@ -8,7 +8,12 @@ public sealed class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logge
|
||||
/// <inheritdoc />
|
||||
public Task OnExceptionAsync(ExceptionContext context)
|
||||
{
|
||||
logger.Error(context.Exception);
|
||||
if (context.Exception is NetAdminException and not NetAdminUnexpectedException) {
|
||||
logger.Warn(context.Exception);
|
||||
}
|
||||
else {
|
||||
logger.Error(context.Exception);
|
||||
}
|
||||
|
||||
// 将异常设置到HttpContext.Features中 以便中间件能获取到他
|
||||
context.HttpContext.Features.Set<IExceptionHandlerFeature>(
|
||||
|
@ -5,9 +5,6 @@ namespace NetAdmin.Host.Middlewares;
|
||||
/// <summary>
|
||||
/// 请求审计中间件
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 放在所有中间件最前面
|
||||
/// </remarks>
|
||||
public sealed class RequestAuditMiddleware(
|
||||
RequestDelegate next
|
||||
, IOptions<DynamicApiControllerSettingsOptions> dynamicApiControllerSettingsOptions
|
||||
@ -17,7 +14,7 @@ public sealed class RequestAuditMiddleware(
|
||||
= new($"/{dynamicApiControllerSettingsOptions.Value.DefaultRoutePrefix}");
|
||||
|
||||
private readonly PathString _healthCheckRoutePrefix
|
||||
= new($"/{dynamicApiControllerSettingsOptions.Value.DefaultRoutePrefix}/health/check");
|
||||
= new($"/{dynamicApiControllerSettingsOptions.Value.DefaultRoutePrefix}/probe/health.check");
|
||||
|
||||
/// <summary>
|
||||
/// 主函数
|
||||
|
@ -0,0 +1,44 @@
|
||||
namespace NetAdmin.Host.Middlewares;
|
||||
|
||||
/// <summary>
|
||||
/// 安全停机中间件
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 放在所有中间件最前面
|
||||
/// </remarks>
|
||||
public sealed class SafetyShopHostMiddleware(RequestDelegate next)
|
||||
{
|
||||
private static long _connections;
|
||||
private static bool _hostStopping;
|
||||
|
||||
/// <summary>
|
||||
/// 当前连接数
|
||||
/// </summary>
|
||||
public static long Connections => Interlocked.Read(ref _connections);
|
||||
|
||||
/// <summary>
|
||||
/// 停机处理
|
||||
/// </summary>
|
||||
public static void OnStopping()
|
||||
{
|
||||
Volatile.Write(ref _hostStopping, true);
|
||||
while (Interlocked.Read(ref _connections) > 0) {
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 主函数
|
||||
/// </summary>
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
if (Volatile.Read(ref _hostStopping)) {
|
||||
context.Response.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
|
||||
return;
|
||||
}
|
||||
|
||||
_ = Interlocked.Increment(ref _connections);
|
||||
await next(context).ConfigureAwait(false);
|
||||
_ = Interlocked.Decrement(ref _connections);
|
||||
}
|
||||
}
|
@ -36,10 +36,12 @@ public sealed class RequestLogger(
|
||||
_textContentTypes
|
||||
, x => context.Request.ContentType?.Contains(
|
||||
x, StringComparison.OrdinalIgnoreCase) ?? false)
|
||||
? await context.ReadBodyContentAsync().ConfigureAwait(false)
|
||||
? (await context.ReadBodyContentAsync().ConfigureAwait(false))
|
||||
?.Sub(0, Numbers.MAX_LIMIT_PRINT_LEN_CONTENT)
|
||||
: string.Empty
|
||||
, RequestUrl = context.Request.GetRequestUrlAddress()
|
||||
, ResponseBody = responseBody
|
||||
, ResponseBody
|
||||
= responseBody?.Sub(0, Numbers.MAX_LIMIT_PRINT_LEN_CONTENT)
|
||||
, ServerIp = context.GetLocalIpAddressToIPv4()?.IpV4ToInt32()
|
||||
, ApiId = context.Request.Path.Value?.TrimStart('/')
|
||||
, RequestHeaders = context.Request.Headers.Json()
|
||||
@ -51,7 +53,10 @@ public sealed class RequestLogger(
|
||||
, CreatedUserId = associatedUser?.UserId
|
||||
, CreatedUserName = associatedUser?.UserName
|
||||
, CreatedUserAgent = context.Request.Headers.UserAgent.ToString()
|
||||
, CreatedClientIp = context.GetRemoteIpAddressToIPv4()?.IpV4ToInt32()
|
||||
, CreatedClientIp = context.GetRealIpAddress()
|
||||
?.MapToIPv4()
|
||||
.ToString()
|
||||
.IpV4ToInt32()
|
||||
};
|
||||
|
||||
// 打印日志
|
||||
|
@ -59,7 +59,7 @@ public sealed class SqlAuditor : ISingleton
|
||||
private static void SetCreatedClientIp(AuditValueEventArgs e)
|
||||
{
|
||||
if (e.Value is null or 0) {
|
||||
e.Value = App.HttpContext?.GetRemoteIpAddressToIPv4().IpV4ToInt32();
|
||||
e.Value = App.HttpContext?.GetRealIpAddress()?.MapToIPv4().ToString().IpV4ToInt32();
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ public sealed class SqlAuditor : ISingleton
|
||||
private static void SetCreatedUserAgent(AuditValueEventArgs e)
|
||||
{
|
||||
if (e.Value is null or "") {
|
||||
e.Value = App.HttpContext?.Request.Headers[Chars.FLG_HTTP_HEADER_USER_AGENT].ToString();
|
||||
e.Value = App.HttpContext?.Request.Headers[Chars.FLG_HTTP_HEADER_KEY_USER_AGENT].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,8 @@ public sealed record CaptchaOptions : OptionAbstraction
|
||||
{
|
||||
var rtn = new char[32];
|
||||
for (var i = 0; i != 32; i++) {
|
||||
rtn[i] = Chars.FLG_VISIBLE_ASCIIS[
|
||||
(int)(Math.Abs(Math.Sin(_seed * (i + 1))) * Chars.FLG_VISIBLE_ASCIIS.Length)];
|
||||
rtn[i] = Chars.FLGL_VISIBLE_ASCIIS[
|
||||
(int)(Math.Abs(Math.Sin(_seed * (i + 1))) * Chars.FLGL_VISIBLE_ASCIIS.Length)];
|
||||
}
|
||||
|
||||
SecretKey = new string(rtn);
|
||||
|
@ -10,80 +10,78 @@ namespace NetAdmin.Infrastructure.Constant;
|
||||
/// </remarks>
|
||||
public static class Chars
|
||||
{
|
||||
public const string FLG_ACCESS_TOKEN = "ACCESS-TOKEN";
|
||||
public const string FLG_ACCESS_TOKEN_HEADER_KEY = "Authorization";
|
||||
public const string FLG_APPLICATION_JSON = "application/json";
|
||||
public const string FLG_AUTH_SCHEMA = "Bearer";
|
||||
public const string FLG_CONSUL_REG_HOSTNAME = "CONSUL_REG_HOSTNAME";
|
||||
public const string FLG_CONSUL_REG_PORT = "CONSUL_REG_PORT";
|
||||
public const string FLG_CONTEXT_MEMBER_INFO = nameof(FLG_CONTEXT_MEMBER_INFO);
|
||||
public const string FLG_CONTEXT_OWNER_DEPT_ID = nameof(FLG_CONTEXT_OWNER_DEPT_ID);
|
||||
public const string FLG_CONTEXT_USER_ID = nameof(FLG_CONTEXT_USER_ID);
|
||||
public const string FLG_CONTEXT_USER_INFO = nameof(FLG_CONTEXT_USER_INFO);
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR = "nvarchar";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_255 = "nvarchar(255)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_MAX = "nvarchar(max)";
|
||||
public const string FLG_DB_FIELD_TYPE_SMALL_INT = "smallint";
|
||||
public const string FLG_DB_FIELD_TYPE_TEXT = "text";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR = "varchar";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_1022 = "varchar(1022)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_127 = "varchar(127)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_15 = "varchar(15)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_255 = "varchar(255)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_31 = "varchar(31)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_4094 = "varchar(4094)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_510 = "varchar(510)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_63 = "varchar(63)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_7 = "varchar(7)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_MAX = "varchar(max)";
|
||||
public const string FLG_GLOBAL_FILTER_DATA = nameof(FLG_GLOBAL_FILTER_DATA);
|
||||
public const string FLG_GLOBAL_FILTER_DELETE = nameof(FLG_GLOBAL_FILTER_DELETE);
|
||||
public const string FLG_GLOBAL_FILTER_MEMBER = nameof(FLG_GLOBAL_FILTER_MEMBER);
|
||||
public const string FLG_GLOBAL_FILTER_SELF = nameof(FLG_GLOBAL_FILTER_SELF);
|
||||
public const string FLG_GLOBAL_FILTER_TENANT = nameof(FLG_GLOBAL_FILTER_TENANT);
|
||||
public const string FLG_HEALTH_CHECK_PATH_PREFIX = "health/check";
|
||||
public const string FLG_HTTP_HEADER_REFERER = "Referer";
|
||||
public const string FLG_HTTP_HEADER_USER_AGENT = "User-Agent";
|
||||
public const string FLG_HTTP_METHOD_CONNECT = "CONNECT";
|
||||
public const string FLG_HTTP_METHOD_DELETE = "DELETE";
|
||||
public const string FLG_HTTP_METHOD_GET = "GET";
|
||||
public const string FLG_HTTP_METHOD_HEAD = "HEAD";
|
||||
public const string FLG_HTTP_METHOD_OPTIONS = "OPTIONS";
|
||||
public const string FLG_HTTP_METHOD_PATCH = "PATCH";
|
||||
public const string FLG_HTTP_METHOD_POST = "POST";
|
||||
public const string FLG_HTTP_METHOD_PUT = "PUT";
|
||||
public const string FLG_HTTP_METHOD_TRACE = "TRACE";
|
||||
public const string FLG_RANDOM_UNAME_PWD = "VcXlp7WY";
|
||||
public const string FLG_REDIS_INSTANCE_DATA_CACHE = "DataCache";
|
||||
public const string FLG_SNOWFLAKE_WORK_ID = "SNOWFLAKE_WORK_ID";
|
||||
public const string FLG_SYSTEM_PREFIX = "sc_";
|
||||
public const string FLG_TABLE_NAME_PREFIX = "";
|
||||
public const string FLG_CONTEXT_MEMBER_INFO = nameof(FLG_CONTEXT_MEMBER_INFO);
|
||||
public const string FLG_CONTEXT_OWNER_DEPT_ID = nameof(FLG_CONTEXT_OWNER_DEPT_ID);
|
||||
public const string FLG_CONTEXT_USER_ID = nameof(FLG_CONTEXT_USER_ID);
|
||||
public const string FLG_CONTEXT_USER_INFO = nameof(FLG_CONTEXT_USER_INFO);
|
||||
public const string FLG_DB_EXCEPTION_PRIVATE_KEY_CONFLICT = "PRIMARY KEY";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR = "nvarchar";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_1022 = "nvarchar(1022)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_127 = "nvarchar(127)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_15 = "nvarchar(15)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_255 = "nvarchar(255)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_31 = "nvarchar(31)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_4094 = "nvarchar(4094)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_510 = "nvarchar(510)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_63 = "nvarchar(63)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_7 = "nvarchar(7)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_MAX = "nvarchar(max)";
|
||||
public const string FLG_DB_FIELD_TYPE_SMALL_INT = "smallint";
|
||||
public const string FLG_DB_FIELD_TYPE_TEXT = "text";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR = "varchar";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_1022 = "varchar(1022)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_127 = "varchar(127)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_15 = "varchar(15)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_255 = "varchar(255)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_31 = "varchar(31)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_4094 = "varchar(4094)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_510 = "varchar(510)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_63 = "varchar(63)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_7 = "varchar(7)";
|
||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_MAX = "varchar(max)";
|
||||
public const string FLG_DB_TABLE_NAME_PREFIX = "";
|
||||
public const string FLG_FREE_SQL_GLOBAL_FILTER_DATA = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DATA);
|
||||
public const string FLG_FREE_SQL_GLOBAL_FILTER_DELETE = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DELETE);
|
||||
public const string FLG_FREE_SQL_GLOBAL_FILTER_MEMBER = nameof(FLG_FREE_SQL_GLOBAL_FILTER_MEMBER);
|
||||
public const string FLG_FREE_SQL_GLOBAL_FILTER_SELF = nameof(FLG_FREE_SQL_GLOBAL_FILTER_SELF);
|
||||
public const string FLG_FREE_SQL_GLOBAL_FILTER_TENANT = nameof(FLG_FREE_SQL_GLOBAL_FILTER_TENANT);
|
||||
public const string FLG_HTTP_HEADER_KEY_AUTHORIZATION = "Authorization";
|
||||
public const string FLG_HTTP_HEADER_KEY_REFERER = "Referer";
|
||||
public const string FLG_HTTP_HEADER_KEY_USER_AGENT = "User-Agent";
|
||||
public const string FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN = "X-ACCESS-TOKEN";
|
||||
public const string FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN_HEADER_KEY = "X-Authorization";
|
||||
public const string FLG_HTTP_HEADER_KEY_X_FORWARDED_FOR = "X-Forwarded-For";
|
||||
public const string FLG_HTTP_HEADER_KEY_X_REAL_IP = "X-Real-IP";
|
||||
public const string FLG_HTTP_HEADER_VALUE_ACCESS_TOKEN = "ACCESS-TOKEN";
|
||||
public const string FLG_HTTP_HEADER_VALUE_APPLICATION_JSON = "application/json";
|
||||
public const string FLG_HTTP_HEADER_VALUE_APPLICATION_URLENCODED = "application/x-www-form-urlencoded";
|
||||
public const string FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA = "Bearer";
|
||||
public const string FLG_HTTP_METHOD_CONNECT = "CONNECT";
|
||||
public const string FLG_HTTP_METHOD_DELETE = "DELETE";
|
||||
public const string FLG_HTTP_METHOD_GET = "GET";
|
||||
public const string FLG_HTTP_METHOD_HEAD = "HEAD";
|
||||
public const string FLG_HTTP_METHOD_OPTIONS = "OPTIONS";
|
||||
public const string FLG_HTTP_METHOD_PATCH = "PATCH";
|
||||
public const string FLG_HTTP_METHOD_POST = "POST";
|
||||
public const string FLG_HTTP_METHOD_PUT = "PUT";
|
||||
public const string FLG_HTTP_METHOD_TRACE = "TRACE";
|
||||
public const string FLG_PATH_PREFIX_HEALTH_CHECK = "probe/health.check";
|
||||
public const string FLG_RANDOM_UNAME_PWD = "VcXlp7WY";
|
||||
public const string FLG_REDIS_INSTANCE_DATA_CACHE = "DataCache";
|
||||
public const string FLG_SNOWFLAKE_WORK_ID = "SNOWFLAKE_WORK_ID";
|
||||
public const string FLG_SYSTEM_PREFIX = "sc_";
|
||||
|
||||
public const string FLG_UA_MOBILE
|
||||
public const string FLGL_HTTP_HEADER_VALUE_UA_MOBILE
|
||||
= "Mozilla/5.0 (Linux; Android 9; Redmi Note 8 Pro Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.96 Mobile Safari/537.36";
|
||||
|
||||
public const string FLG_UA_PC
|
||||
public const string FLGL_HTTP_HEADER_VALUE_UA_PC
|
||||
= "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36";
|
||||
|
||||
public const string FLG_VISIBLE_ASCIIS
|
||||
public const string FLGL_VISIBLE_ASCIIS
|
||||
= """!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~""";
|
||||
|
||||
public const string FLG_X_ACCESS_TOKEN = "X-ACCESS-TOKEN";
|
||||
public const string FLG_X_ACCESS_TOKEN_HEADER_KEY = "X-Authorization";
|
||||
|
||||
public const string RGX_CERTIFICATE = "^[a-zA-Z0-9-_]+$";
|
||||
|
||||
public const string RGX_CHINESE_NAME
|
||||
= """^(?:赵|钱|孙|李|周|吴|郑|王|冯|陈|褚|卫|蒋|沈|韩|杨|朱|秦|尤|许|何|吕|施|张|孔|曹|严|华|金|魏|陶|姜|戚|谢|邹|喻|柏|水|窦|章|云|苏|潘|葛|奚|范|彭|郎|鲁|韦|昌|马|苗|凤|花|方|俞|任|袁|柳|酆|鲍|史|唐|费|廉|岑|薛|雷|贺|倪|汤|滕|殷|罗|毕|郝|邬|安|常|乐|于|时|傅|皮|卞|齐|康|伍|余|元|卜|顾|孟|平|黄|和|穆|萧|尹|姚|邵|湛|汪|祁|毛|禹|狄|米|贝|明|臧|计|伏|成|戴|谈|宋|茅|庞|熊|纪|舒|屈|项|祝|董|梁|杜|阮|蓝|闵|席|季|麻|强|贾|路|娄|危|江|童|颜|郭|梅|盛|林|刁|钟|徐|邱|骆|高|夏|蔡|田|樊|胡|凌|霍|虞|万|支|柯|昝|管|卢|莫|经|房|裘|缪|干|解|应|宗|丁|宣|贲|邓|郁|单|杭|洪|包|诸|左|石|崔|吉|钮|龚|程|嵇|邢|滑|裴|陆|荣|翁|荀|羊|於|惠|甄|曲|家|封|芮|羿|储|靳|汲|邴|糜|松|井|段|富|巫|乌|焦|巴|弓|牧|隗|山|谷|车|侯|宓|蓬|全|郗|班|仰|秋|仲|伊|宫|宁|仇|栾|暴|甘|钭|厉|戎|祖|武|符|刘|景|詹|束|龙|叶|幸|司|韶|郜|黎|蓟|薄|印|宿|白|怀|蒲|邰|从|鄂|索|咸|籍|赖|卓|蔺|屠|蒙|池|乔|阴|胥|能|苍|双|闻|莘|党|翟|谭|贡|劳|逄|姬|申|扶|堵|冉|宰|郦|雍|郤|璩|桑|桂|濮|牛|寿|通|边|扈|燕|冀|郏|浦|尚|农|温|别|庄|晏|柴|瞿|阎|充|慕|连|茹|习|宦|艾|鱼|容|向|古|易|慎|戈|廖|庾|终|暨|居|衡|步|都|耿|满|弘|匡|国|文|寇|广|禄|阙|东|欧|殳|沃|利|蔚|越|夔|隆|师|巩|厍|聂|晁|勾|敖|融|冷|訾|辛|阚|那|简|饶|空|曾|毋|沙|乜|养|鞠|须|丰|巢|关|蒯|相|查|後|荆|红|游|竺|权|逯|盖|益|桓|公|万俟|司马|上官|欧阳|夏侯|诸葛|闻人|东方|赫连|皇甫|尉迟|公羊|澹台|公冶|宗政|濮阳|淳于|单于|太叔|申屠|公孙|仲孙|轩辕|令狐|钟离|宇文|长孙|慕容|鲜于|闾丘|司徒|司空|亓官|司寇|仉|督|子车|颛孙|端木|巫马|公西|漆雕|乐正|壤驷|公良|拓跋|夹谷|宰父|谷梁|晋|楚|闫|法|汝|鄢|涂|钦|段干|百里|东郭|南门|呼延|归|海|羊舌|微生|岳|帅|缑|亢|况|后|有|琴|梁丘|左丘|东门|西门|商|牟|佘|佴|伯|赏|南宫|墨|哈|谯|笪|年|爱|阳|佟|第五|言|福)[\u4e00-\u9fa5]{1,3}$""";
|
||||
|
||||
public const string RGX_CRON
|
||||
= "^\\s*($|#|\\w+\\s*=|(\\?|\\*|(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?(?:,(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?)*)\\s+(\\?|\\*|(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?(?:,(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?)*)\\s+(\\?|\\*|(?:[01]?\\d|2[0-3])(?:(?:-|\\/|\\,)(?:[01]?\\d|2[0-3]))?(?:,(?:[01]?\\d|2[0-3])(?:(?:-|\\/|\\,)(?:[01]?\\d|2[0-3]))?)*)\\s+(\\?|\\*|(?:0?[1-9]|[12]\\d|3[01])(?:(?:-|\\/|\\,)(?:0?[1-9]|[12]\\d|3[01]))?(?:,(?:0?[1-9]|[12]\\d|3[01])(?:(?:-|\\/|\\,)(?:0?[1-9]|[12]\\d|3[01]))?)*)\\s+(\\?|\\*|(?:[1-9]|1[012])(?:(?:-|\\/|\\,)(?:[1-9]|1[012]))?(?:L|W)?(?:,(?:[1-9]|1[012])(?:(?:-|\\/|\\,)(?:[1-9]|1[012]))?(?:L|W)?)*|\\?|\\*|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:(?:-)(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?(?:,(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:(?:-)(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?)*)\\s+(\\?|\\*|(?:[0-6])(?:(?:-|\\/|\\,|#)(?:[0-6]))?(?:L)?(?:,(?:[0-6])(?:(?:-|\\/|\\,|#)(?:[0-6]))?(?:L)?)*|\\?|\\*|(?:MON|TUE|WED|THU|FRI|SAT|SUN)(?:(?:-)(?:MON|TUE|WED|THU|FRI|SAT|SUN))?(?:,(?:MON|TUE|WED|THU|FRI|SAT|SUN)(?:(?:-)(?:MON|TUE|WED|THU|FRI|SAT|SUN))?)*)(|\\s)+(\\?|\\*|(?:|\\d{4})(?:(?:-|\\/|\\,)(?:|\\d{4}))?(?:,(?:|\\d{4})(?:(?:-|\\/|\\,)(?:|\\d{4}))?)*))$";
|
||||
|
||||
public const string RGX_EMAIL
|
||||
= """^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$""";
|
||||
|
||||
public const string RGX_INVITE_CODE = """^\d{8}$""";
|
||||
|
||||
public const string RGX_CERTIFICATE = "^[a-zA-Z0-9-_]+$";
|
||||
public const string RGX_INVITE_CODE = """^\d{8}$""";
|
||||
public const string RGX_MOBILE = """^1(3\d|4[5-9]|5[0-35-9]|6[6]|7[2-8]|8\d|9[0-35-9])\d{8}$""";
|
||||
public const string RGX_PASSWORD = "^(?![0-9]+$)(?![a-zA-Z]+$).{8,16}$";
|
||||
public const string RGX_PAY_PASSWORD = """^\d{6}$""";
|
||||
@ -93,6 +91,18 @@ public static class Chars
|
||||
public const string RGX_USERNAME = "^[a-zA-Z0-9_]{4,16}$";
|
||||
public const string RGX_VERIFY_CODE = """^\d{4}$""";
|
||||
|
||||
public const string RGXL_CHINESE_NAME
|
||||
= """^(?:赵|钱|孙|李|周|吴|郑|王|冯|陈|褚|卫|蒋|沈|韩|杨|朱|秦|尤|许|何|吕|施|张|孔|曹|严|华|金|魏|陶|姜|戚|谢|邹|喻|柏|水|窦|章|云|苏|潘|葛|奚|范|彭|郎|鲁|韦|昌|马|苗|凤|花|方|俞|任|袁|柳|酆|鲍|史|唐|费|廉|岑|薛|雷|贺|倪|汤|滕|殷|罗|毕|郝|邬|安|常|乐|于|时|傅|皮|卞|齐|康|伍|余|元|卜|顾|孟|平|黄|和|穆|萧|尹|姚|邵|湛|汪|祁|毛|禹|狄|米|贝|明|臧|计|伏|成|戴|谈|宋|茅|庞|熊|纪|舒|屈|项|祝|董|梁|杜|阮|蓝|闵|席|季|麻|强|贾|路|娄|危|江|童|颜|郭|梅|盛|林|刁|钟|徐|邱|骆|高|夏|蔡|田|樊|胡|凌|霍|虞|万|支|柯|昝|管|卢|莫|经|房|裘|缪|干|解|应|宗|丁|宣|贲|邓|郁|单|杭|洪|包|诸|左|石|崔|吉|钮|龚|程|嵇|邢|滑|裴|陆|荣|翁|荀|羊|於|惠|甄|曲|家|封|芮|羿|储|靳|汲|邴|糜|松|井|段|富|巫|乌|焦|巴|弓|牧|隗|山|谷|车|侯|宓|蓬|全|郗|班|仰|秋|仲|伊|宫|宁|仇|栾|暴|甘|钭|厉|戎|祖|武|符|刘|景|詹|束|龙|叶|幸|司|韶|郜|黎|蓟|薄|印|宿|白|怀|蒲|邰|从|鄂|索|咸|籍|赖|卓|蔺|屠|蒙|池|乔|阴|胥|能|苍|双|闻|莘|党|翟|谭|贡|劳|逄|姬|申|扶|堵|冉|宰|郦|雍|郤|璩|桑|桂|濮|牛|寿|通|边|扈|燕|冀|郏|浦|尚|农|温|别|庄|晏|柴|瞿|阎|充|慕|连|茹|习|宦|艾|鱼|容|向|古|易|慎|戈|廖|庾|终|暨|居|衡|步|都|耿|满|弘|匡|国|文|寇|广|禄|阙|东|欧|殳|沃|利|蔚|越|夔|隆|师|巩|厍|聂|晁|勾|敖|融|冷|訾|辛|阚|那|简|饶|空|曾|毋|沙|乜|养|鞠|须|丰|巢|关|蒯|相|查|後|荆|红|游|竺|权|逯|盖|益|桓|公|万俟|司马|上官|欧阳|夏侯|诸葛|闻人|东方|赫连|皇甫|尉迟|公羊|澹台|公冶|宗政|濮阳|淳于|单于|太叔|申屠|公孙|仲孙|轩辕|令狐|钟离|宇文|长孙|慕容|鲜于|闾丘|司徒|司空|亓官|司寇|仉|督|子车|颛孙|端木|巫马|公西|漆雕|乐正|壤驷|公良|拓跋|夹谷|宰父|谷梁|晋|楚|闫|法|汝|鄢|涂|钦|段干|百里|东郭|南门|呼延|归|海|羊舌|微生|岳|帅|缑|亢|况|后|有|琴|梁丘|左丘|东门|西门|商|牟|佘|佴|伯|赏|南宫|墨|哈|谯|笪|年|爱|阳|佟|第五|言|福)[\u4e00-\u9fa5]{1,3}$""";
|
||||
|
||||
public const string RGXL_CRON
|
||||
= "^\\s*($|#|\\w+\\s*=|(\\?|\\*|(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?(?:,(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?)*)\\s+(\\?|\\*|(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?(?:,(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?)*)\\s+(\\?|\\*|(?:[01]?\\d|2[0-3])(?:(?:-|\\/|\\,)(?:[01]?\\d|2[0-3]))?(?:,(?:[01]?\\d|2[0-3])(?:(?:-|\\/|\\,)(?:[01]?\\d|2[0-3]))?)*)\\s+(\\?|\\*|(?:0?[1-9]|[12]\\d|3[01])(?:(?:-|\\/|\\,)(?:0?[1-9]|[12]\\d|3[01]))?(?:,(?:0?[1-9]|[12]\\d|3[01])(?:(?:-|\\/|\\,)(?:0?[1-9]|[12]\\d|3[01]))?)*)\\s+(\\?|\\*|(?:[1-9]|1[012])(?:(?:-|\\/|\\,)(?:[1-9]|1[012]))?(?:L|W)?(?:,(?:[1-9]|1[012])(?:(?:-|\\/|\\,)(?:[1-9]|1[012]))?(?:L|W)?)*|\\?|\\*|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:(?:-)(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?(?:,(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:(?:-)(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?)*)\\s+(\\?|\\*|(?:[0-6])(?:(?:-|\\/|\\,|#)(?:[0-6]))?(?:L)?(?:,(?:[0-6])(?:(?:-|\\/|\\,|#)(?:[0-6]))?(?:L)?)*|\\?|\\*|(?:MON|TUE|WED|THU|FRI|SAT|SUN)(?:(?:-)(?:MON|TUE|WED|THU|FRI|SAT|SUN))?(?:,(?:MON|TUE|WED|THU|FRI|SAT|SUN)(?:(?:-)(?:MON|TUE|WED|THU|FRI|SAT|SUN))?)*)(|\\s)+(\\?|\\*|(?:|\\d{4})(?:(?:-|\\/|\\,)(?:|\\d{4}))?(?:,(?:|\\d{4})(?:(?:-|\\/|\\,)(?:|\\d{4}))?)*))$";
|
||||
|
||||
public const string RGXL_EMAIL
|
||||
= """^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$""";
|
||||
|
||||
public const string RGXL_IP_V4
|
||||
= @"^(25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})){3}$";
|
||||
|
||||
public const string TPL_DATE_HH_MM_SS_FFFFFF = "HH:mm:ss.ffffff";
|
||||
public const string TPL_DATE_YYYY_MM_DD = "yyyy-MM-dd";
|
||||
public const string TPL_DATE_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
|
||||
|
@ -10,17 +10,22 @@ namespace NetAdmin.Infrastructure.Constant;
|
||||
/// </remarks>
|
||||
public static class Numbers
|
||||
{
|
||||
public const int BULK_REQ_LIMIT = 100; // 批量请求允许的最大数量
|
||||
public const int CONSOLE_LINE_LEN_LIMIT = 8192; // 控制台输出的最大长度
|
||||
public const long DEF_SORT_VAL = 100; // 排序默认值
|
||||
public const long DIC_CATALOG_ID_GEO_AREA = 379794295185413; // 字典目录编号-行政区划字典
|
||||
public const int HTTP_STATUS_BIZ_FAIL = 900; // Http状态码-业务异常
|
||||
public const int QUERY_DEF_PAGE_SIZE = 20; // 分页查询默认的页容量
|
||||
public const int QUERY_LIMIT = 100; // 非分页查询允许返回的最大条数
|
||||
public const int QUERY_MAX_PAGE_NO = 1000; // 分页查询允许最大的页码
|
||||
public const int QUERY_MAX_PAGE_SIZE = 100; // 分页查询允许最大的页容量
|
||||
public const int RED_LOCK_EXPIRY_TIME_SECS = 30; // red lock: 锁锁定过期时间,锁区域内的逻辑执行如果超过过期时间,锁将被释放
|
||||
public const int RED_LOCK_RETRY_TIME_SECS = 1; // red lock: 锁等待时间内,多久尝试获取一次
|
||||
public const int RED_LOCK_WAIT_TIME_SECS = 10; // red lock: 锁等待时间,相同的 resource 如果当前的锁被其他线程占用,最多等待时间
|
||||
public const int TIMEOUT_SECS_JOB = 600; // 超时时间:作业
|
||||
public const int DEF_PAGE_SIZE_QUERY = 20; // 分页查询默认的页容量
|
||||
public const long DEF_SORT_VAL = 100; // 排序默认值
|
||||
|
||||
public const int HTTP_STATUS_BIZ_FAIL = 900; // Http状态码-业务异常
|
||||
public const long ID_DIC_CATALOG_GEO_AREA = 379794295185413; // 唯一编号:字典目录-行政区划字典
|
||||
|
||||
public const int MAX_LIMIT_BULK_REQ = 100; // 最大限制:批量请求数
|
||||
public const int MAX_LIMIT_PRINT_LEN_CONTENT = 4096; // 最大限制:打印长度(HTTP 内容)
|
||||
public const int MAX_LIMIT_PRINT_LEN_SQL = 4096; // 最大限制:打印长度(SQL 语句)
|
||||
public const int MAX_LIMIT_QUERY = 1000; // 最大限制:非分页查询条数
|
||||
public const int MAX_LIMIT_QUERY_PAGE_NO = 10000; // 最大限制:分页查询页码
|
||||
public const int MAX_LIMIT_QUERY_PAGE_SIZE = 100; // 最大限制:分页查询页容量
|
||||
|
||||
public const int SECS_CACHE_DEFAULT = 60; // 秒:缓存时间-默认
|
||||
public const int SECS_RED_LOCK_EXPIRY = 30; // 秒:RedLock-锁过期时间,锁区域内的逻辑执行如果超过过期时间,锁将被释放
|
||||
public const int SECS_RED_LOCK_RETRY = 1; // 秒:RedLock-锁等待时间内,多久尝试获取一次
|
||||
public const int SECS_RED_LOCK_WAIT = 10; // 秒:RedLock-锁等待时间,相同的 resource 如果当前的锁被其他线程占用,最多等待时间
|
||||
public const int SECS_TIMEOUT_JOB = 600; // 秒:超时时间-作业
|
||||
}
|
@ -19,4 +19,12 @@ public enum Orders
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.倒序排序))]
|
||||
Descending = 2
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// 随机排序
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.随机排序))]
|
||||
Random = 3
|
||||
}
|
@ -4,5 +4,5 @@ namespace NetAdmin.Infrastructure.Exceptions;
|
||||
/// 加锁失败异常
|
||||
/// </summary>
|
||||
#pragma warning disable RCS1194
|
||||
public sealed class NetAdminGetLockerException : NetAdminUnexpectedException;
|
||||
public sealed class NetAdminGetLockerException : NetAdminException;
|
||||
#pragma warning restore RCS1194
|
@ -0,0 +1,25 @@
|
||||
namespace NetAdmin.Infrastructure.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// HttpContext 扩展方法
|
||||
/// </summary>
|
||||
public static class HttpContextExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取客户端真实IP
|
||||
/// </summary>
|
||||
public static IPAddress GetRealIpAddress(this HttpContext me)
|
||||
{
|
||||
#pragma warning disable IDE0046
|
||||
if (me.Request.Headers.TryGetValue(Chars.FLG_HTTP_HEADER_KEY_X_FORWARDED_FOR, out var ips1) &&
|
||||
#pragma warning restore IDE0046
|
||||
IPAddress.TryParse(ips1.FirstOrDefault()?.Split(',').FirstOrDefault(), out var ip1)) {
|
||||
return ip1;
|
||||
}
|
||||
|
||||
return me.Request.Headers.TryGetValue(Chars.FLG_HTTP_HEADER_KEY_X_REAL_IP, out var ips2) &&
|
||||
IPAddress.TryParse(ips2.FirstOrDefault()?.Split(',').FirstOrDefault(), out var ip2)
|
||||
? ip2
|
||||
: me.Connection.RemoteIpAddress;
|
||||
}
|
||||
}
|
@ -19,7 +19,8 @@ public static class HttpRequestMessageExtensions
|
||||
/// </summary>
|
||||
public static async Task<HttpRequestMessage> LogAsync<T>(this HttpRequestMessage me, ILogger<T> logger)
|
||||
{
|
||||
logger.Info($"HTTP Request: {await me.BuildJsonAsync().ConfigureAwait(false)}");
|
||||
logger.Info(
|
||||
$"HTTP Request: {(await me.BuildJsonAsync().ConfigureAwait(false))?.Sub(0, Numbers.MAX_LIMIT_PRINT_LEN_CONTENT)}");
|
||||
return me;
|
||||
}
|
||||
}
|
@ -11,7 +11,9 @@ public static class HttpResponseMessageExtensions
|
||||
public static async Task LogAsync<T>(this HttpResponseMessage me, ILogger<T> logger
|
||||
, Func<string, string> bodyPreHandle = null)
|
||||
{
|
||||
logger.Info(await me.BuildJsonAsync(bodyPreHandle).ConfigureAwait(false));
|
||||
logger.Info(
|
||||
(await me.BuildJsonAsync(bodyPreHandle).ConfigureAwait(false))?.Sub(
|
||||
0, Numbers.MAX_LIMIT_PRINT_LEN_CONTENT));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -20,7 +22,8 @@ public static class HttpResponseMessageExtensions
|
||||
public static async Task LogExceptionAsync<T>(this HttpResponseMessage me, string errors, ILogger<T> logger
|
||||
, Func<string, string> bodyHandle = null)
|
||||
{
|
||||
logger.Warn($"{errors}: {await me.BuildJsonAsync(bodyHandle).ConfigureAwait(false)}");
|
||||
logger.Warn(
|
||||
$"{errors}: {(await me.BuildJsonAsync(bodyHandle).ConfigureAwait(false))?.Sub(0, Numbers.MAX_LIMIT_PRINT_LEN_CONTENT)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -7,12 +7,12 @@
|
||||
<Import Project="$(SolutionDir)/build/prebuild.targets"/>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Cronos" Version="0.8.4"/>
|
||||
<PackageReference Include="FreeSql.DbContext.NS" Version="3.2.813-preview20240208-ns1"/>
|
||||
<PackageReference Include="FreeSql.Provider.Sqlite.NS" Version="3.2.813-preview20240208-ns1"/>
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.1.31"/>
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.1.31-ns2"/>
|
||||
<PackageReference Include="Furion.Pure.NS" Version="4.9.1.31-ns2"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0-preview.1.24081.5"/>
|
||||
<PackageReference Include="FreeSql.DbContext.NS" Version="3.2.821-ns1"/>
|
||||
<PackageReference Include="FreeSql.Provider.Sqlite.NS" Version="3.2.821-ns1"/>
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.2.19"/>
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.2.19-ns3"/>
|
||||
<PackageReference Include="Furion.Pure.NS" Version="4.9.2.19-ns3"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.1"/>
|
||||
<PackageReference Include="Minio" Version="6.0.2"/>
|
||||
<PackageReference Include="NSExt" Version="2.1.0"/>
|
||||
<PackageReference Include="RedLock.net" Version="2.3.2"/>
|
||||
|
@ -315,8 +315,9 @@ public sealed class UserAgentParser
|
||||
|
||||
private bool SetPlatform()
|
||||
{
|
||||
var kv = _platforms.First(x => //
|
||||
Regex.IsMatch(_agent, $"{Regex.Escape(x.Key)}", RegexOptions.IgnoreCase));
|
||||
var kv = _platforms.FirstOrDefault(x => //
|
||||
Regex.IsMatch(_agent, $"{Regex.Escape(x.Key)}"
|
||||
, RegexOptions.IgnoreCase));
|
||||
|
||||
if (kv.Key == null) {
|
||||
Platform = "Unknown Platform";
|
||||
|
@ -297,8 +297,8 @@
|
||||
// 数据缓存
|
||||
{
|
||||
"Name": "DataCache",
|
||||
"ConnStr": "localhost:6379",
|
||||
"Database": 0
|
||||
"ConnStr": "localhost:6379,abortConnect=false",
|
||||
"DataBase": 0,
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -24,12 +24,12 @@ public sealed class Startup : Host.Startup
|
||||
/// <summary>
|
||||
/// 配置应用程序中间件
|
||||
/// </summary>
|
||||
public void Configure(IApplicationBuilder app)
|
||||
public void Configure(IApplicationBuilder app, IHostApplicationLifetime lifeTime)
|
||||
{
|
||||
_ = app //
|
||||
.UseRealIp() // 使用RealIp中间件,用于获取真实客户端IP地址
|
||||
.EnableBuffering() // 启用请求体缓冲,允许多次读取请求体
|
||||
.UseMiddleware<RequestAuditMiddleware>() // 使用RequestAuditMiddleware中间件,执行请求审计
|
||||
_ = app //
|
||||
.UseMiddleware<SafetyShopHostMiddleware>() // 安全停机中间件
|
||||
.EnableBuffering() // 启用请求体缓冲,允许多次读取请求体
|
||||
.UseMiddleware<RequestAuditMiddleware>() // 使用RequestAuditMiddleware中间件,执行请求审计
|
||||
#if DEBUG
|
||||
.UseOpenApiSkin() // 使用OpenApiSkin中间件(仅在调试模式下),提供Swagger UI皮肤
|
||||
#else
|
||||
@ -41,6 +41,7 @@ public sealed class Startup : Host.Startup
|
||||
.UseRouting() // 使用Routing中间件,配置路由映射
|
||||
.UseMiddleware<RemoveNullNodeMiddleware>() // 使用RemoveNullNodeMiddleware中间件,删除JSON中的空节点
|
||||
.UseEndpoints(); // 配置端点以处理请求
|
||||
_ = lifeTime.ApplicationStopping.Register(SafetyShopHostMiddleware.OnStopping);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -21,6 +21,13 @@ public sealed class ApiService(
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryApiRsp> CreateAsync(CreateApiReq req)
|
||||
{
|
||||
@ -140,9 +147,12 @@ public sealed class ApiService(
|
||||
|
||||
private ISelect<Sys_Api> QueryInternal(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.CreatedTime), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.CreatedTime);
|
||||
|
@ -10,11 +10,21 @@ namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
public sealed class CacheService(IConnectionMultiplexer connectionMultiplexer) //
|
||||
: ServiceBase<ICacheService>, ICacheService
|
||||
{
|
||||
private readonly InstanceNode _redisInstance;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CacheService" /> class.
|
||||
/// </summary>
|
||||
public CacheService(IConnectionMultiplexer connectionMultiplexer, IOptions<RedisOptions> redisOptions) //
|
||||
: this(connectionMultiplexer) //
|
||||
{
|
||||
_redisInstance = redisOptions.Value.Instances.First(x => x.Name == Chars.FLG_REDIS_INSTANCE_DATA_CACHE);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<CacheStatisticsRsp> CacheStatisticsAsync()
|
||||
{
|
||||
var database = connectionMultiplexer.GetDatabase();
|
||||
|
||||
var database = connectionMultiplexer.GetDatabase(_redisInstance.Database);
|
||||
return new CacheStatisticsRsp((string)await database.ExecuteAsync("info").ConfigureAwait(false)) {
|
||||
DbSize = (long)await database.ExecuteAsync("dbSize").ConfigureAwait(false)
|
||||
};
|
||||
@ -24,7 +34,7 @@ public sealed class CacheService(IConnectionMultiplexer connectionMultiplexer) /
|
||||
public async Task<PagedQueryRsp<GetAllEntriesRsp>> GetAllEntriesAsync(PagedQueryReq<GetAllEntriesReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var database = connectionMultiplexer.GetDatabase((int?)req.Filter?.DbIndex ?? 0);
|
||||
var database = connectionMultiplexer.GetDatabase(_redisInstance.Database);
|
||||
var redisResults = (RedisResult[])await database
|
||||
.ExecuteAsync("scan", (req.Page - 1) * req.PageSize, "count"
|
||||
, req.PageSize)
|
||||
|
@ -26,6 +26,13 @@ public sealed class ConfigService(DefaultRepository<Sys_Config> rpo) //
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryConfigReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryConfigRsp> CreateAsync(CreateConfigReq req)
|
||||
{
|
||||
@ -113,8 +120,12 @@ public sealed class ConfigService(DefaultRepository<Sys_Config> rpo) //
|
||||
.Include(a => a.UserRegisterRole)
|
||||
.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereIf( //
|
||||
req.Filter?.Enabled.HasValue ?? false, a => a.Enabled == req.Filter.Enabled.Value)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
req.Filter?.Enabled.HasValue ?? false, a => a.Enabled == req.Filter.Enabled.Value);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
@ -18,17 +18,28 @@ public sealed class ConstantService : ServiceBase<IConstantService>, IConstantSe
|
||||
/// <inheritdoc />
|
||||
public IDictionary<string, Dictionary<string, string[]>> GetEnums()
|
||||
{
|
||||
return App.EffectiveTypes.Where(x => x.IsEnum && x.GetCustomAttribute<ExportAttribute>(false) != null)
|
||||
.ToDictionary(x => x.Name, x => //
|
||||
x.GetEnumValues()
|
||||
.Cast<Enum>()
|
||||
.ToDictionary( //
|
||||
y => y.ToString()
|
||||
, y => new[] {
|
||||
Convert.ToInt64(y, CultureInfo.InvariantCulture)
|
||||
.ToString(CultureInfo.InvariantCulture)
|
||||
, y.ResDesc<Ln>()
|
||||
}));
|
||||
var ret = App.EffectiveTypes.Where(x => x.IsEnum && x.GetCustomAttribute<ExportAttribute>(false) != null)
|
||||
.ToDictionary(x => x.Name, x => //
|
||||
x.GetEnumValues()
|
||||
.Cast<Enum>()
|
||||
.ToDictionary( //
|
||||
y => y.ToString()
|
||||
, y => new[] {
|
||||
Convert.ToInt64(y, CultureInfo.InvariantCulture)
|
||||
.ToString(CultureInfo.InvariantCulture)
|
||||
, y.ResDesc<Ln>()
|
||||
}));
|
||||
|
||||
ret.Add($"{nameof(HttpStatusCode)}s", Enum.GetNames<HttpStatusCode>()
|
||||
.ToDictionary( //
|
||||
x => x, x => new[] {
|
||||
Convert.ToInt64( //
|
||||
Enum.Parse<HttpStatusCode>(x)
|
||||
, CultureInfo.InvariantCulture)
|
||||
.ToString(CultureInfo.InvariantCulture)
|
||||
, x
|
||||
}));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -25,6 +25,13 @@ public sealed class DeptService(DefaultRepository<Sys_Dept> rpo) //
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryDeptReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">Parent_department_does_not_exist</exception>
|
||||
public async Task<QueryDeptRsp> CreateAsync(CreateDeptReq req)
|
||||
@ -88,12 +95,11 @@ public sealed class DeptService(DefaultRepository<Sys_Dept> rpo) //
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminUnexpectedException">NetAdminUnexpectedException</exception>
|
||||
public async Task<QueryDeptRsp> UpdateAsync(UpdateDeptReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return await Rpo.UpdateDiy.SetSource(req).ExecuteAffrowsAsync().ConfigureAwait(false) <= 0
|
||||
? throw new NetAdminUnexpectedException()
|
||||
? null
|
||||
: (await QueryInternal(new QueryReq<QueryDeptReq> { Filter = new QueryDeptReq { Id = req.Id } }, true)
|
||||
.ToTreeListAsync()
|
||||
.ConfigureAwait(false))[0]
|
||||
@ -118,6 +124,10 @@ public sealed class DeptService(DefaultRepository<Sys_Dept> rpo) //
|
||||
ret = ret.AsTreeCte();
|
||||
}
|
||||
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Sort), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
|
@ -25,6 +25,13 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryDicCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">The_parent_node_does_not_exist</exception>
|
||||
public async Task<QueryDicCatalogRsp> CreateAsync(CreateDicCatalogReq req)
|
||||
@ -88,7 +95,6 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">The_parent_node_does_not_exist</exception>
|
||||
/// <exception cref="NetAdminUnexpectedException">NetAdminUnexpectedException</exception>
|
||||
public async Task<QueryDicCatalogRsp> UpdateAsync(UpdateDicCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
@ -98,7 +104,7 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
}
|
||||
|
||||
if (await Rpo.UpdateDiy.SetSource(req).ExecuteAffrowsAsync().ConfigureAwait(false) <= 0) {
|
||||
throw new NetAdminUnexpectedException();
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = await Rpo.Where(a => a.Id == req.Id).ToOneAsync().ConfigureAwait(false);
|
||||
@ -113,9 +119,12 @@ public sealed class DicCatalogService(DefaultRepository<Sys_DicCatalog> rpo) //
|
||||
|
||||
private ISelect<Sys_DicCatalog> QueryInternal(QueryReq<QueryDicCatalogReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
@ -25,6 +25,13 @@ public sealed class DicContentService(DefaultRepository<Sys_DicContent> rpo) //
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">Dictionary_directory_does_not_exist</exception>
|
||||
public async Task<QueryDicContentRsp> CreateAsync(CreateDicContentReq req)
|
||||
@ -90,7 +97,6 @@ public sealed class DicContentService(DefaultRepository<Sys_DicContent> rpo) //
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">Dictionary_directory_does_not_exist</exception>
|
||||
/// <exception cref="NetAdminUnexpectedException">NetAdminUnexpectedException</exception>
|
||||
public async Task<QueryDicContentRsp> UpdateAsync(UpdateDicContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
@ -103,7 +109,7 @@ public sealed class DicContentService(DefaultRepository<Sys_DicContent> rpo) //
|
||||
}
|
||||
|
||||
if (await Rpo.UpdateDiy.SetSource(req).ExecuteAffrowsAsync().ConfigureAwait(false) <= 0) {
|
||||
throw new NetAdminUnexpectedException();
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = await Rpo.Where(a => a.Id == req.Id).ToOneAsync().ConfigureAwait(false);
|
||||
@ -118,9 +124,12 @@ public sealed class DicContentService(DefaultRepository<Sys_DicContent> rpo) //
|
||||
|
||||
private ISelect<Sys_DicContent> QueryInternal(QueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
@ -26,6 +26,13 @@ public sealed class JobRecordService(DefaultRepository<Sys_JobRecord> rpo) //
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryJobRecordRsp> CreateAsync(CreateJobRecordReq req)
|
||||
{
|
||||
@ -106,8 +113,12 @@ public sealed class JobRecordService(DefaultRepository<Sys_JobRecord> rpo) //
|
||||
.WhereDynamic(req.Filter)
|
||||
.WhereIf( //
|
||||
req.Keywords?.Length > 0
|
||||
, a => a.JobId == req.Keywords.Int64Try(0) || a.Id == req.Keywords.Int64Try(0))
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
, a => a.JobId == req.Keywords.Int64Try(0) || a.Id == req.Keywords.Int64Try(0));
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
@ -29,6 +29,13 @@ public sealed class JobService(DefaultRepository<Sys_Job> rpo, IJobRecordService
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryJobRsp> CreateAsync(CreateJobReq req)
|
||||
{
|
||||
@ -119,13 +126,14 @@ public sealed class JobService(DefaultRepository<Sys_Job> rpo, IJobRecordService
|
||||
}
|
||||
]
|
||||
};
|
||||
var job = await QueryInternal(new QueryReq<QueryJobReq> { DynamicFilter = df, Count = 1 }, true)
|
||||
.Where(a => !Rpo.Orm.Select<Sys_JobRecord>()
|
||||
.As("b")
|
||||
.Where(b => b.JobId == a.Id && b.TimeId == a.NextTimeId)
|
||||
.Any())
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
var job
|
||||
= await QueryInternal(new QueryReq<QueryJobReq> { DynamicFilter = df, Count = 1, Order = Orders.Random })
|
||||
.Where(a => !Rpo.Orm.Select<Sys_JobRecord>()
|
||||
.As("b")
|
||||
.Where(b => b.JobId == a.Id && b.TimeId == a.NextTimeId)
|
||||
.Any())
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return job == null
|
||||
? null
|
||||
: await UpdateAsync(job.Adapt<UpdateJobReq>() with {
|
||||
@ -175,7 +183,7 @@ public sealed class JobService(DefaultRepository<Sys_Job> rpo, IJobRecordService
|
||||
{
|
||||
return Rpo.UpdateDiy.Set(a => a.Status == JobStatues.Idle)
|
||||
.Where(a => a.Status == JobStatues.Running &&
|
||||
a.LastExecTime < DateTime.Now.AddSeconds(-Numbers.TIMEOUT_SECS_JOB))
|
||||
a.LastExecTime < DateTime.Now.AddSeconds(-Numbers.SECS_TIMEOUT_JOB))
|
||||
.ExecuteAffrowsAsync();
|
||||
}
|
||||
|
||||
@ -211,17 +219,23 @@ public sealed class JobService(DefaultRepository<Sys_Job> rpo, IJobRecordService
|
||||
.GetNextOccurrence(DateTime.UtcNow, TimeZoneInfo.Utc);
|
||||
}
|
||||
|
||||
private ISelect<Sys_Job> QueryInternal(QueryReq<QueryJobReq> req, bool orderByRandom = false)
|
||||
private ISelect<Sys_Job> QueryInternal(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.Include(a => a.User)
|
||||
.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.WhereIf( //
|
||||
req.Keywords?.Length > 0
|
||||
, a => a.Id == req.Keywords.Int64Try(0) || a.JobName.Contains(req.Keywords))
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
return !orderByRandom && (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true)
|
||||
? ret.OrderByDescending(a => a.LastExecTime)
|
||||
: ret.OrderByRandom();
|
||||
, a => a.Id == req.Keywords.Int64Try(0) || a.JobName.Contains(req.Keywords));
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.LastExecTime), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.LastExecTime);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -25,6 +25,13 @@ public sealed class MenuService(DefaultRepository<Sys_Menu> rpo, IUserService us
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryMenuReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryMenuRsp> CreateAsync(CreateMenuReq req)
|
||||
{
|
||||
@ -37,12 +44,12 @@ public sealed class MenuService(DefaultRepository<Sys_Menu> rpo, IUserService us
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var effect = await Rpo.DeleteAsync(a => a.Id == req.Id).ConfigureAwait(false);
|
||||
effect += await Rpo.Orm.Delete<Sys_RoleMenu>()
|
||||
.Where(a => a.MenuId == req.Id)
|
||||
.ExecuteAffrowsAsync()
|
||||
.ConfigureAwait(false);
|
||||
return effect;
|
||||
var ret = await Rpo.DeleteAsync(a => a.Id == req.Id).ConfigureAwait(false);
|
||||
_ = await Rpo.Orm.Delete<Sys_RoleMenu>()
|
||||
.Where(a => a.MenuId == req.Id)
|
||||
.ExecuteAffrowsAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -76,12 +83,11 @@ public sealed class MenuService(DefaultRepository<Sys_Menu> rpo, IUserService us
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminUnexpectedException">NetAdminUnexpectedException</exception>
|
||||
public async Task<QueryMenuRsp> UpdateAsync(UpdateMenuReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (await Rpo.UpdateDiy.SetSource(req).ExecuteAffrowsAsync().ConfigureAwait(false) <= 0) {
|
||||
throw new NetAdminUnexpectedException();
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = await Rpo.Where(a => a.Id == req.Id).ToOneAsync().ConfigureAwait(false);
|
||||
@ -124,11 +130,12 @@ public sealed class MenuService(DefaultRepository<Sys_Menu> rpo, IUserService us
|
||||
|
||||
private ISelect<Sys_Menu> QueryInternal(QueryReq<QueryMenuReq> req)
|
||||
{
|
||||
return Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending)
|
||||
.OrderByDescending(a => a.Sort)
|
||||
.OrderBy(a => a.Name)
|
||||
.OrderBy(a => a.Id);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
return req.Order == Orders.Random
|
||||
? ret.OrderByRandom()
|
||||
: ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending)
|
||||
.OrderByDescending(a => a.Sort)
|
||||
.OrderBy(a => a.Name)
|
||||
.OrderBy(a => a.Id);
|
||||
}
|
||||
}
|
@ -25,6 +25,13 @@ public sealed class RequestLogService(DefaultRepository<Sys_RequestLog> rpo) //
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryRequestLogRsp> CreateAsync(CreateRequestLogReq req)
|
||||
{
|
||||
@ -106,10 +113,12 @@ public sealed class RequestLogService(DefaultRepository<Sys_RequestLog> rpo) //
|
||||
|
||||
private ISelect<Sys_RequestLog> QueryInternal(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.Include(a => a.Api)
|
||||
.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.Include(a => a.Api).WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.CreatedTime), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.CreatedTime);
|
||||
|
@ -25,6 +25,13 @@ public sealed class RoleService(DefaultRepository<Sys_Role> rpo) //
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryRoleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryRoleRsp> CreateAsync(CreateRoleReq req)
|
||||
{
|
||||
@ -116,8 +123,12 @@ public sealed class RoleService(DefaultRepository<Sys_Role> rpo) //
|
||||
.WhereIf( //
|
||||
req.Keywords?.Length > 0
|
||||
, a => a.Id == req.Keywords.Int64Try(0) || a.Name.Contains(req.Keywords) ||
|
||||
a.Summary.Contains(req.Keywords))
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
a.Summary.Contains(req.Keywords));
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Sort), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Sort);
|
||||
|
@ -26,6 +26,13 @@ public sealed class SiteMsgDeptService(DefaultRepository<Sys_SiteMsgDept> rpo) /
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QuerySiteMsgDeptReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgDeptRsp> CreateAsync(CreateSiteMsgDeptReq req)
|
||||
{
|
||||
@ -102,9 +109,12 @@ public sealed class SiteMsgDeptService(DefaultRepository<Sys_SiteMsgDept> rpo) /
|
||||
|
||||
private ISelect<Sys_SiteMsgDept> QueryInternal(QueryReq<QuerySiteMsgDeptReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
@ -26,6 +26,13 @@ public sealed class SiteMsgFlagService(DefaultRepository<Sys_SiteMsgFlag> rpo) /
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QuerySiteMsgFlagReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgFlagRsp> CreateAsync(CreateSiteMsgFlagReq req)
|
||||
{
|
||||
@ -108,9 +115,12 @@ public sealed class SiteMsgFlagService(DefaultRepository<Sys_SiteMsgFlag> rpo) /
|
||||
|
||||
private ISelect<Sys_SiteMsgFlag> QueryInternal(QueryReq<QuerySiteMsgFlagReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
@ -26,6 +26,13 @@ public sealed class SiteMsgRoleService(DefaultRepository<Sys_SiteMsgRole> rpo) /
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QuerySiteMsgRoleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgRoleRsp> CreateAsync(CreateSiteMsgRoleReq req)
|
||||
{
|
||||
@ -102,9 +109,12 @@ public sealed class SiteMsgRoleService(DefaultRepository<Sys_SiteMsgRole> rpo) /
|
||||
|
||||
private ISelect<Sys_SiteMsgRole> QueryInternal(QueryReq<QuerySiteMsgRoleReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
@ -12,8 +12,10 @@ using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
|
||||
/// <inheritdoc cref="ISiteMsgService" />
|
||||
public sealed class SiteMsgService(DefaultRepository<Sys_SiteMsg> rpo, ContextUserInfo contextUserInfo
|
||||
, ISiteMsgFlagService siteMsgFlagService) //
|
||||
public sealed class SiteMsgService(
|
||||
DefaultRepository<Sys_SiteMsg> rpo
|
||||
, ContextUserInfo contextUserInfo
|
||||
, ISiteMsgFlagService siteMsgFlagService) //
|
||||
: RepositoryService<Sys_SiteMsg, ISiteMsgService>(rpo), ISiteMsgService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@ -30,6 +32,13 @@ public sealed class SiteMsgService(DefaultRepository<Sys_SiteMsg> rpo, ContextUs
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgRsp> CreateAsync(CreateSiteMsgReq req)
|
||||
{
|
||||
@ -109,7 +118,7 @@ public sealed class SiteMsgService(DefaultRepository<Sys_SiteMsg> rpo, ContextUs
|
||||
.Count(out var total)
|
||||
.ToListAsync(a => new {
|
||||
a.CreatedTime
|
||||
, a.Creator
|
||||
, a.CreatedUserName
|
||||
, a.Id
|
||||
, a.MsgType
|
||||
, a.Summary
|
||||
@ -275,8 +284,12 @@ public sealed class SiteMsgService(DefaultRepository<Sys_SiteMsg> rpo, ContextUs
|
||||
.WhereIf( //
|
||||
req.Keywords?.Length > 0
|
||||
, a => a.Id == req.Keywords.Int64Try(0) || a.Title.Contains(req.Keywords) ||
|
||||
a.Summary.Contains(req.Keywords))
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
a.Summary.Contains(req.Keywords));
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
@ -300,9 +313,9 @@ public sealed class SiteMsgService(DefaultRepository<Sys_SiteMsg> rpo, ContextUs
|
||||
.WhereDynamicFilter(req.DynamicFilter)
|
||||
.Where((a, _, c, d, e, f) =>
|
||||
(SqlExt.EqualIsNull(f.UserSiteMsgStatus) ||
|
||||
f.UserSiteMsgStatus != UserSiteMsgStatues.Deleted) && (a.MsgType == SiteMsgTypes.Public ||
|
||||
c.DeptId == contextUserInfo.DeptId || roleIds.Contains(d.RoleId) ||
|
||||
e.UserId == contextUserInfo.Id))
|
||||
f.UserSiteMsgStatus != UserSiteMsgStatues.Deleted) &&
|
||||
(a.MsgType == SiteMsgTypes.Public || c.DeptId == contextUserInfo.DeptId ||
|
||||
roleIds.Contains(d.RoleId) || e.UserId == contextUserInfo.Id))
|
||||
.GroupBy((a, _, _, _, _, _) => a.Id);
|
||||
}
|
||||
}
|
@ -26,6 +26,13 @@ public sealed class SiteMsgUserService(DefaultRepository<Sys_SiteMsgUser> rpo) /
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QuerySiteMsgUserReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QuerySiteMsgUserRsp> CreateAsync(CreateSiteMsgUserReq req)
|
||||
{
|
||||
@ -102,9 +109,12 @@ public sealed class SiteMsgUserService(DefaultRepository<Sys_SiteMsgUser> rpo) /
|
||||
|
||||
private ISelect<Sys_SiteMsgUser> QueryInternal(QueryReq<QuerySiteMsgUserReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
@ -27,6 +27,13 @@ public sealed class UserProfileService(DefaultRepository<Sys_UserProfile> rpo) /
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryUserProfileReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserProfileRsp> CreateAsync(CreateUserProfileReq req)
|
||||
{
|
||||
@ -146,18 +153,21 @@ public sealed class UserProfileService(DefaultRepository<Sys_UserProfile> rpo) /
|
||||
QueryReq<QueryUserProfileReq> req)
|
||||
{
|
||||
#pragma warning disable CA1305
|
||||
return Rpo.Orm.Select<Sys_UserProfile, Sys_DicContent, Sys_DicContent, Sys_DicContent, Sys_DicContent>()
|
||||
.LeftJoin((a, b, _, __, ___) =>
|
||||
a.NationArea.ToString() == b.Value && b.CatalogId == Numbers.DIC_CATALOG_ID_GEO_AREA)
|
||||
.LeftJoin((a, _, c, __, ___) =>
|
||||
a.CompanyArea.ToString() == c.Value && c.CatalogId == Numbers.DIC_CATALOG_ID_GEO_AREA)
|
||||
.LeftJoin((a, _, __, d, ___) =>
|
||||
a.HomeArea.ToString() == d.Value && d.CatalogId == Numbers.DIC_CATALOG_ID_GEO_AREA)
|
||||
.LeftJoin((a, _, __, ___, e) => a.EmergencyContactArea.ToString() == e.Value &&
|
||||
e.CatalogId == Numbers.DIC_CATALOG_ID_GEO_AREA)
|
||||
.WhereDynamicFilter(req.DynamicFilter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending)
|
||||
.OrderByDescending((a, _, __, ___, ____) => a.Id);
|
||||
var ret = Rpo.Orm.Select<Sys_UserProfile, Sys_DicContent, Sys_DicContent, Sys_DicContent, Sys_DicContent>()
|
||||
.LeftJoin((a, b, _, __, ___) =>
|
||||
a.NationArea.ToString() == b.Value && b.CatalogId == Numbers.ID_DIC_CATALOG_GEO_AREA)
|
||||
.LeftJoin((a, _, c, __, ___) =>
|
||||
a.CompanyArea.ToString() == c.Value &&
|
||||
c.CatalogId == Numbers.ID_DIC_CATALOG_GEO_AREA)
|
||||
.LeftJoin((a, _, __, d, ___) =>
|
||||
a.HomeArea.ToString() == d.Value && d.CatalogId == Numbers.ID_DIC_CATALOG_GEO_AREA)
|
||||
.LeftJoin((a, _, __, ___, e) => a.EmergencyContactArea.ToString() == e.Value &&
|
||||
e.CatalogId == Numbers.ID_DIC_CATALOG_GEO_AREA)
|
||||
.WhereDynamicFilter(req.DynamicFilter);
|
||||
return req.Order == Orders.Random
|
||||
? ret.OrderByRandom()
|
||||
: ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending)
|
||||
.OrderByDescending((a, _, __, ___, ____) => a.Id);
|
||||
#pragma warning restore CA1305
|
||||
}
|
||||
}
|
@ -13,10 +13,11 @@ using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
|
||||
/// <inheritdoc cref="IUserService" />
|
||||
public sealed class UserService(DefaultRepository<Sys_User> rpo //
|
||||
, IUserProfileService userProfileService //
|
||||
, IVerifyCodeService verifyCodeService //
|
||||
, IEventPublisher eventPublisher) //
|
||||
public sealed class UserService(
|
||||
DefaultRepository<Sys_User> rpo //
|
||||
, IUserProfileService userProfileService //
|
||||
, IVerifyCodeService verifyCodeService //
|
||||
, IEventPublisher eventPublisher) //
|
||||
: RepositoryService<Sys_User, IUserService>(rpo), IUserService
|
||||
{
|
||||
private readonly Expression<Func<Sys_User, Sys_User>> _selectUserFields = a => new Sys_User {
|
||||
@ -63,6 +64,15 @@ public sealed class UserService(DefaultRepository<Sys_User> rpo /
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
#pragma warning disable VSTHRD103
|
||||
return QueryInternal(req).CountAsync();
|
||||
#pragma warning restore VSTHRD103
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserRsp> CreateAsync(CreateUserReq req)
|
||||
{
|
||||
@ -88,20 +98,17 @@ public sealed class UserService(DefaultRepository<Sys_User> rpo /
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var effect = 0;
|
||||
|
||||
// 删除主表
|
||||
effect += await Rpo.DeleteAsync(req.Id).ConfigureAwait(false);
|
||||
var ret = await Rpo.DeleteAsync(req.Id).ConfigureAwait(false);
|
||||
|
||||
// 删除分表
|
||||
effect += await Rpo.Orm.Delete<Sys_UserRole>(new { UserId = req.Id })
|
||||
.ExecuteAffrowsAsync()
|
||||
.ConfigureAwait(false);
|
||||
_ = await Rpo.Orm.Delete<Sys_UserRole>(new { UserId = req.Id }).ExecuteAffrowsAsync().ConfigureAwait(false);
|
||||
|
||||
// 删除档案表
|
||||
effect += await userProfileService.DeleteAsync(req).ConfigureAwait(false);
|
||||
_ = await userProfileService.DeleteAsync(req).ConfigureAwait(false);
|
||||
|
||||
return effect;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -255,7 +262,7 @@ public sealed class UserService(DefaultRepository<Sys_User> rpo /
|
||||
.UpdateColumns(a => a.Avatar)
|
||||
.ExecuteAffrowsAsync()
|
||||
.ConfigureAwait(false) <= 0) {
|
||||
throw new NetAdminUnexpectedException();
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = (await QueryAsync(new QueryReq<QueryUserReq> { Filter = new QueryUserReq { Id = UserToken.Id } })
|
||||
@ -289,7 +296,7 @@ public sealed class UserService(DefaultRepository<Sys_User> rpo /
|
||||
.UpdateColumns(a => a.Email)
|
||||
.ExecuteAffrowsAsync()
|
||||
.ConfigureAwait(false) <= 0) {
|
||||
throw new NetAdminUnexpectedException();
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = (await QueryAsync(new QueryReq<QueryUserReq> { Filter = new QueryUserReq { Id = UserToken.Id } })
|
||||
@ -341,7 +348,7 @@ public sealed class UserService(DefaultRepository<Sys_User> rpo /
|
||||
.UpdateColumns(a => a.Mobile)
|
||||
.ExecuteAffrowsAsync()
|
||||
.ConfigureAwait(false) <= 0) {
|
||||
throw new NetAdminUnexpectedException();
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = (await QueryAsync(new QueryReq<QueryUserReq> { Filter = new QueryUserReq { Id = UserToken.Id } })
|
||||
@ -370,7 +377,7 @@ public sealed class UserService(DefaultRepository<Sys_User> rpo /
|
||||
.UpdateColumns(a => a.Password)
|
||||
.ExecuteAffrowsAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret <= 0 ? throw new NetAdminUnexpectedException() : (uint)ret;
|
||||
return (uint)ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -478,9 +485,12 @@ public sealed class UserService(DefaultRepository<Sys_User> rpo /
|
||||
|
||||
private ISelect<Sys_User> QueryInternal(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
@ -511,8 +521,12 @@ public sealed class UserService(DefaultRepository<Sys_User> rpo /
|
||||
req.Keywords?.Length > 0
|
||||
, a => a.Id == req.Keywords.Int64Try(0) || a.UserName.Contains(req.Keywords) ||
|
||||
a.Mobile.Contains(req.Keywords) || a.Email.Contains(req.Keywords) ||
|
||||
a.Summary.Contains(req.Keywords))
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
a.Summary.Contains(req.Keywords));
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.CreatedTime), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.CreatedTime);
|
||||
|
@ -30,6 +30,13 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryVerifyCodeReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryVerifyCodeRsp> CreateAsync(CreateVerifyCodeReq req)
|
||||
{
|
||||
@ -180,9 +187,12 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
||||
|
||||
private ISelect<Sys_VerifyCode> QueryInternal(QueryReq<QueryVerifyCodeReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
@ -26,6 +26,13 @@ public sealed class ExampleService(DefaultRepository<Tpl_Example> rpo) //
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryExampleReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryExampleRsp> CreateAsync(CreateExampleReq req)
|
||||
{
|
||||
@ -102,9 +109,12 @@ public sealed class ExampleService(DefaultRepository<Tpl_Example> rpo) //
|
||||
|
||||
private ISelect<Tpl_Example> QueryInternal(QueryReq<QueryExampleReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
if (req.Order == Orders.Random) {
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
@ -16,6 +16,12 @@ public sealed class ApiCache(IDistributedCache cache, IApiService service) //
|
||||
return Service.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
return Service.CountAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryApiRsp> CreateAsync(CreateApiReq req)
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ public sealed class CacheCache(IDistributedCache cache, ICacheService service) /
|
||||
{
|
||||
#if !DEBUG
|
||||
return GetOrCreateAsync( //
|
||||
GetCacheKey(string.Empty), Service.CacheStatisticsAsync, TimeSpan.FromMinutes(1));
|
||||
GetCacheKey(string.Empty), Service.CacheStatisticsAsync, TimeSpan.FromSeconds(Numbers.CACHE_SECS_DEFAULT));
|
||||
#else
|
||||
return Service.CacheStatisticsAsync();
|
||||
#endif
|
||||
|
@ -14,7 +14,7 @@ public sealed class CaptchaCache(IDistributedCache cache, ICaptchaService servic
|
||||
{
|
||||
var captchaRsp = await Service.GetCaptchaImageAsync().ConfigureAwait(false);
|
||||
await CreateAsync(GetCacheKey(captchaRsp.Id, nameof(CaptchaCache)), captchaRsp.SawOffsetX
|
||||
, TimeSpan.FromMinutes(1))
|
||||
, TimeSpan.FromSeconds(Numbers.SECS_CACHE_DEFAULT))
|
||||
.ConfigureAwait(false);
|
||||
return captchaRsp;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user