mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-04-23 14:42:51 +08:00
refactor: ♻️ 业务代码项目文件名与框架代码项目文件名区分 (#196)
Co-authored-by: tk <fiyne1a@dingtalk.com>
This commit is contained in:
parent
d1503a859b
commit
e6ce5afd99
4
.github/workflows/nightly-build.yml
vendored
4
.github/workflows/nightly-build.yml
vendored
@ -37,8 +37,8 @@ jobs:
|
|||||||
path: ~/.nuget/packages
|
path: ~/.nuget/packages
|
||||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
|
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
|
||||||
restore-keys: ${{ runner.os }}-nuget
|
restore-keys: ${{ runner.os }}-nuget
|
||||||
- working-directory: ./src/backend/NetAdmin.AdmServer.Host
|
- working-directory: ./src/backend/YourSolution.AdmServer.Host
|
||||||
run: dotnet publish NetAdmin.AdmServer.Host.csproj -c Release
|
run: dotnet publish YourSolution.AdmServer.Host.csproj -c Release
|
||||||
- run: docker build -t nsnail/netadmin:nightly .
|
- run: docker build -t nsnail/netadmin:nightly .
|
||||||
- uses: docker/login-action@v3
|
- uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -37,8 +37,8 @@ jobs:
|
|||||||
path: ~/.nuget/packages
|
path: ~/.nuget/packages
|
||||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
|
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
|
||||||
restore-keys: ${{ runner.os }}-nuget
|
restore-keys: ${{ runner.os }}-nuget
|
||||||
- working-directory: ./src/backend/NetAdmin.AdmServer.Host
|
- working-directory: ./src/backend/YourSolution.AdmServer.Host
|
||||||
run: dotnet publish NetAdmin.AdmServer.Host.csproj -c Release
|
run: dotnet publish YourSolution.AdmServer.Host.csproj -c Release
|
||||||
- uses: actions/create-release@v1
|
- uses: actions/create-release@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
@ -32,6 +32,6 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="../GlobalUsings.cs" Link="GlobalUsings.cs" />
|
<Compile Include="$(SolutionDir)/src/backend/GlobalUsings.cs" Link="GlobalUsings.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -3,5 +3,5 @@ WORKDIR /app
|
|||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
RUN apt update
|
RUN apt update
|
||||||
RUN apt install -y redis
|
RUN apt install -y redis
|
||||||
COPY ./dist/backend/NetAdmin.AdmServer.Host/bin/Release/net9.0/publish .
|
COPY ./dist/backend/YourSolution.AdmServer.Host/bin/Release/net9.0/publish .
|
||||||
ENTRYPOINT redis-server --daemonize yes && dotnet NetAdmin.AdmServer.Host.dll -is
|
ENTRYPOINT redis-server --daemonize yes && dotnet YourSolution.AdmServer.Host.dll -is
|
32
NetAdmin.sln
32
NetAdmin.sln
@ -70,29 +70,29 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{8E4C93BA
|
|||||||
stylecop.analyzers.ruleset = build/stylecop.analyzers.ruleset
|
stylecop.analyzers.ruleset = build/stylecop.analyzers.ruleset
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Infrastructure", "src\backend\NetAdmin.Infrastructure\NetAdmin.Infrastructure.csproj", "{1E62C322-EE42-4699-A6F1-791C53EFA62D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Infrastructure", "src\backend\NetAdmin\NetAdmin.Infrastructure\NetAdmin.Infrastructure.csproj", "{1E62C322-EE42-4699-A6F1-791C53EFA62D}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.AdmServer.Application", "src\backend\NetAdmin.AdmServer.Application\NetAdmin.AdmServer.Application.csproj", "{E38B2EB4-D7A5-4777-9236-3B348919DF23}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourSolution.AdmServer.Application", "src\backend\YourSolution.AdmServer.Application\YourSolution.AdmServer.Application.csproj", "{E38B2EB4-D7A5-4777-9236-3B348919DF23}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.AdmServer.Host", "src\backend\NetAdmin.AdmServer.Host\NetAdmin.AdmServer.Host.csproj", "{CE895E44-EEC3-4ECE-A56A-8A82E7D863E3}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourSolution.AdmServer.Host", "src\backend\YourSolution.AdmServer.Host\YourSolution.AdmServer.Host.csproj", "{CE895E44-EEC3-4ECE-A56A-8A82E7D863E3}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03.hosted-servers", "03.hosted-servers", "{12AE5B4B-CB1A-498E-83B8-04E201E31D86}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03.hosted-servers", "03.hosted-servers", "{12AE5B4B-CB1A-498E-83B8-04E201E31D86}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Domain", "src\backend\NetAdmin.Domain\NetAdmin.Domain.csproj", "{58509C57-09FA-4E3C-BC07-78E786A2A326}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Domain", "src\backend\NetAdmin\NetAdmin.Domain\NetAdmin.Domain.csproj", "{58509C57-09FA-4E3C-BC07-78E786A2A326}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Application", "src\backend\NetAdmin.Application\NetAdmin.Application.csproj", "{70C54E1B-2083-4196-AB68-34CAF0075D82}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Application", "src\backend\NetAdmin\NetAdmin.Application\NetAdmin.Application.csproj", "{70C54E1B-2083-4196-AB68-34CAF0075D82}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Host", "src\backend\NetAdmin.Host\NetAdmin.Host.csproj", "{91839A15-D08F-4848-A301-F793412BC688}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Host", "src\backend\NetAdmin\NetAdmin.Host\NetAdmin.Host.csproj", "{91839A15-D08F-4848-A301-F793412BC688}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Cache", "src\backend\NetAdmin.Cache\NetAdmin.Cache.csproj", "{91452C22-4B57-4F16-9AF6-42C7BF830504}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Cache", "src\backend\NetAdmin\NetAdmin.Cache\NetAdmin.Cache.csproj", "{91452C22-4B57-4F16-9AF6-42C7BF830504}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.AdmServer.Cache", "src\backend\NetAdmin.AdmServer.Cache\NetAdmin.AdmServer.Cache.csproj", "{7CB632D3-3635-4F8D-AFE7-F496D37D422B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourSolution.AdmServer.Cache", "src\backend\YourSolution.AdmServer.Cache\YourSolution.AdmServer.Cache.csproj", "{7CB632D3-3635-4F8D-AFE7-F496D37D422B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.SysComponent.Host", "src\backend\NetAdmin.SysComponent.Host\NetAdmin.SysComponent.Host.csproj", "{C2CC1596-3BEE-43EA-A9BE-4EDE5716296C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.SysComponent.Host", "src\backend\NetAdmin\NetAdmin.SysComponent.Host\NetAdmin.SysComponent.Host.csproj", "{C2CC1596-3BEE-43EA-A9BE-4EDE5716296C}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.SysComponent.Cache", "src\backend\NetAdmin.SysComponent.Cache\NetAdmin.SysComponent.Cache.csproj", "{19872A4C-3C9A-4C62-A33B-74F5B8D6F77C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.SysComponent.Cache", "src\backend\NetAdmin\NetAdmin.SysComponent.Cache\NetAdmin.SysComponent.Cache.csproj", "{19872A4C-3C9A-4C62-A33B-74F5B8D6F77C}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.SysComponent.Application", "src\backend\NetAdmin.SysComponent.Application\NetAdmin.SysComponent.Application.csproj", "{34650E82-D257-46DA-BD6B-DE307113347B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.SysComponent.Application", "src\backend\NetAdmin\NetAdmin.SysComponent.Application\NetAdmin.SysComponent.Application.csproj", "{34650E82-D257-46DA-BD6B-DE307113347B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02.components", "02.components", "{3F23258D-8299-4992-9F51-2EE9B52CF9D2}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02.components", "02.components", "{3F23258D-8299-4992-9F51-2EE9B52CF9D2}"
|
||||||
EndProject
|
EndProject
|
||||||
@ -104,20 +104,20 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "05.tools", "05.tools", "{79
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "src\backend\UnitTests\UnitTests.csproj", "{C7F27698-DA05-4ACD-B0D7-4791B3972002}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "src\backend\UnitTests\UnitTests.csproj", "{C7F27698-DA05-4ACD-B0D7-4791B3972002}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Tests", "src\backend\NetAdmin.Tests\NetAdmin.Tests.csproj", "{00604162-C444-478B-B773-3AB23C856CA7}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Tests", "src\backend\NetAdmin\NetAdmin.Tests\NetAdmin.Tests.csproj", "{00604162-C444-478B-B773-3AB23C856CA7}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{E80A1018-C354-4A26-9029-8847BB9DA864}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{E80A1018-C354-4A26-9029-8847BB9DA864}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
README.md = docker/README.md
|
README.md = docker/README.md
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.SysComponent.Domain", "src\backend\NetAdmin.SysComponent.Domain\NetAdmin.SysComponent.Domain.csproj", "{51D6E603-0749-4A11-A78C-9E5BB127E03A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.SysComponent.Domain", "src\backend\NetAdmin\NetAdmin.SysComponent.Domain\NetAdmin.SysComponent.Domain.csproj", "{51D6E603-0749-4A11-A78C-9E5BB127E03A}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.AdmServer.Domain", "src\backend\NetAdmin.AdmServer.Domain\NetAdmin.AdmServer.Domain.csproj", "{932520DF-D312-415A-A128-1117F8221D68}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourSolution.AdmServer.Domain", "src\backend\YourSolution.AdmServer.Domain\YourSolution.AdmServer.Domain.csproj", "{932520DF-D312-415A-A128-1117F8221D68}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.AdmServer.Infrastructure", "src\backend\NetAdmin.AdmServer.Infrastructure\NetAdmin.AdmServer.Infrastructure.csproj", "{C3DE6F6A-D1FC-4B8E-9033-980FBEBBD2BA}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourSolution.AdmServer.Infrastructure", "src\backend\YourSolution.AdmServer.Infrastructure\YourSolution.AdmServer.Infrastructure.csproj", "{C3DE6F6A-D1FC-4B8E-9033-980FBEBBD2BA}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.SysComponent.Infrastructure", "src\backend\NetAdmin.SysComponent.Infrastructure\NetAdmin.SysComponent.Infrastructure.csproj", "{48EE6FC4-B64A-40D3-B889-36837E067880}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.SysComponent.Infrastructure", "src\backend\NetAdmin\NetAdmin.SysComponent.Infrastructure\NetAdmin.SysComponent.Infrastructure.csproj", "{48EE6FC4-B64A-40D3-B889-36837E067880}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -34,7 +34,7 @@ redis-cli # 连接测试
|
|||||||
# 下载 redis for linux/mac:https://redis.io/download
|
# 下载 redis for linux/mac:https://redis.io/download
|
||||||
|
|
||||||
# 4. 运行后端 WebApi
|
# 4. 运行后端 WebApi
|
||||||
dotnet run --project ./src/backend/NetAdmin.AdmServer.Host/NetAdmin.AdmServer.Host.csproj --urls http://[::]:5010 -is
|
dotnet run --project ./src/backend/YourSolution.AdmServer.Host/YourSolution.AdmServer.Host.csproj --urls http://[::]:5010 -is
|
||||||
# -i 插入种子数据
|
# -i 插入种子数据
|
||||||
# -s 同步数据库结构
|
# -s 同步数据库结构
|
||||||
# 浏览器访问 http://localhost:5010 ,将看到Swagger(Knife4jUI)界面
|
# 浏览器访问 http://localhost:5010 ,将看到Swagger(Knife4jUI)界面
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cz-git": "^1.10.1",
|
"cz-git": "^1.11.0",
|
||||||
"commitizen": "^4.3.1",
|
"commitizen": "^4.3.1",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"standard-version": "^9.5.0"
|
"standard-version": "^9.5.0"
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<Import Project="$(SolutionDir)/build/code.quality.props"/>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="../NetAdmin.AdmServer.Application/NetAdmin.AdmServer.Application.csproj"/>
|
|
||||||
<ProjectReference Include="../NetAdmin.SysComponent.Cache/NetAdmin.SysComponent.Cache.csproj"/>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -1,19 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<Import Project="$(SolutionDir)/build/code.quality.props"/>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="../NetAdmin.SysComponent.Infrastructure/NetAdmin.SysComponent.Infrastructure.csproj"/>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="$(SolutionDir)/assets/res/NetAdmin.AdmServer.Statements.ln">
|
|
||||||
<Link>Languages/NetAdmin.AdmServer.Statements.ln</Link>
|
|
||||||
</None>
|
|
||||||
<None Include="$(SolutionDir)/assets/res/NetAdmin.AdmServer.Fields.ln">
|
|
||||||
<Link>Languages/NetAdmin.AdmServer.Fields.ln</Link>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="*.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -1,31 +0,0 @@
|
|||||||
namespace NetAdmin.Application.Extensions;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 工作单元管理器扩展方法
|
|
||||||
/// </summary>
|
|
||||||
public static class UnitOfWorkManagerExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 事务操作
|
|
||||||
/// </summary>
|
|
||||||
public static async Task AtomicOperateAsync(this UnitOfWorkManager me, Func<Task> handle)
|
|
||||||
{
|
|
||||||
var logger = LogHelper.Get<UnitOfWorkManager>();
|
|
||||||
using var unitOfWork = me.Begin();
|
|
||||||
var hashCode = unitOfWork.GetHashCode();
|
|
||||||
try {
|
|
||||||
#if DEBUG
|
|
||||||
logger?.Debug($"{Ln.开始事务}: {hashCode}");
|
|
||||||
#endif
|
|
||||||
await handle().ConfigureAwait(false);
|
|
||||||
unitOfWork.Commit();
|
|
||||||
logger?.Info($"{Ln.事务已提交}: {hashCode}");
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
logger?.Warn(ex);
|
|
||||||
unitOfWork.Rollback();
|
|
||||||
logger?.Warn($"{Ln.事务已回滚}: {hashCode}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
using NetAdmin.Domain;
|
|
||||||
using NetAdmin.Domain.Dto.Dependency;
|
|
||||||
|
|
||||||
namespace NetAdmin.Application.Modules;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 增删改查模块接口
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TCreateReq">创建请求类型</typeparam>
|
|
||||||
/// <typeparam name="TCreateRsp">创建响应类型</typeparam>
|
|
||||||
/// <typeparam name="TQueryReq">查询请求类型</typeparam>
|
|
||||||
/// <typeparam name="TQueryRsp">查询响应类型</typeparam>
|
|
||||||
/// <typeparam name="TDelReq">删除请求类型</typeparam>
|
|
||||||
public interface ICrudModule<in TCreateReq, TCreateRsp, TQueryReq, TQueryRsp, TDelReq>
|
|
||||||
where TCreateReq : DataAbstraction, new()
|
|
||||||
where TCreateRsp : DataAbstraction
|
|
||||||
where TQueryReq : DataAbstraction, new()
|
|
||||||
where TQueryRsp : DataAbstraction
|
|
||||||
where TDelReq : DataAbstraction, new()
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 批量删除实体
|
|
||||||
/// </summary>
|
|
||||||
Task<int> BulkDeleteAsync(BulkReq<TDelReq> req);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 实体计数
|
|
||||||
/// </summary>
|
|
||||||
Task<long> CountAsync(QueryReq<TQueryReq> req);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建实体
|
|
||||||
/// </summary>
|
|
||||||
Task<TCreateRsp> CreateAsync(TCreateReq req);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除实体
|
|
||||||
/// </summary>
|
|
||||||
Task<int> DeleteAsync(TDelReq req);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 判断实体是否存在
|
|
||||||
/// </summary>
|
|
||||||
Task<bool> ExistAsync(QueryReq<TQueryReq> req);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 导出实体
|
|
||||||
/// </summary>
|
|
||||||
Task<IActionResult> ExportAsync(QueryReq<TQueryReq> req);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取单个实体
|
|
||||||
/// </summary>
|
|
||||||
Task<TQueryRsp> GetAsync(TQueryReq req);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 分页查询实体
|
|
||||||
/// </summary>
|
|
||||||
Task<PagedQueryRsp<TQueryRsp>> PagedQueryAsync(PagedQueryReq<TQueryReq> req);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查询实体
|
|
||||||
/// </summary>
|
|
||||||
Task<IEnumerable<TQueryRsp>> QueryAsync(QueryReq<TQueryReq> req);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
using NetAdmin.Domain.Dto.Dependency;
|
|
||||||
using NetAdmin.Domain.Dto.Tpl.Example;
|
|
||||||
|
|
||||||
namespace NetAdmin.Application.Modules.Tpl;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 示例模块
|
|
||||||
/// </summary>
|
|
||||||
public interface IExampleModule : ICrudModule<CreateExampleReq, QueryExampleRsp // 创建类型
|
|
||||||
, QueryExampleReq, QueryExampleRsp // 查询类型
|
|
||||||
, DelReq // 删除类型
|
|
||||||
>;
|
|
@ -1,6 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<Import Project="$(SolutionDir)/build/code.quality.props"/>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="../NetAdmin.Domain/NetAdmin.Domain.csproj"/>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -1,18 +0,0 @@
|
|||||||
using NetAdmin.Domain.Contexts;
|
|
||||||
using NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
|
|
||||||
namespace NetAdmin.Application.Repositories;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 基础仓储
|
|
||||||
/// </summary>
|
|
||||||
public sealed class BasicRepository<TEntity, TPrimary>(IFreeSql fSql, UnitOfWorkManager uowManger, ContextUserToken userToken)
|
|
||||||
: DefaultRepository<TEntity, TPrimary>(fSql, uowManger)
|
|
||||||
where TEntity : EntityBase<TPrimary> //
|
|
||||||
where TPrimary : IEquatable<TPrimary>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 当前上下文关联的用户令牌
|
|
||||||
/// </summary>
|
|
||||||
public ContextUserToken UserToken => userToken;
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
using NetAdmin.Domain.Contexts;
|
|
||||||
|
|
||||||
namespace NetAdmin.Application.Services;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 服务接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IService
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 服务编号
|
|
||||||
/// </summary>
|
|
||||||
Guid ServiceId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 上下文用户令牌
|
|
||||||
/// </summary>
|
|
||||||
ContextUserToken UserToken { get; set; }
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
using NetAdmin.Application.Repositories;
|
|
||||||
using NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
using StackExchange.Redis;
|
|
||||||
|
|
||||||
namespace NetAdmin.Application.Services;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Redis Service Base
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Initializes a new instance of the <see cref="RedisService{TEntity, TPrimary, TLogger}" /> class.
|
|
||||||
/// Redis Service Base
|
|
||||||
/// </remarks>
|
|
||||||
public abstract class RedisService<TEntity, TPrimary, TLogger>(BasicRepository<TEntity, TPrimary> rpo)
|
|
||||||
: RepositoryService<TEntity, TPrimary, TLogger>(rpo)
|
|
||||||
where TEntity : EntityBase<TPrimary> //
|
|
||||||
where TPrimary : IEquatable<TPrimary>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Redis Database
|
|
||||||
/// </summary>
|
|
||||||
protected IDatabase RedisDatabase { get; } //
|
|
||||||
= App.GetService<IConnectionMultiplexer>()
|
|
||||||
.GetDatabase(App.GetOptions<RedisOptions>().Instances.First(x => x.Name == Chars.FLG_REDIS_INSTANCE_DATA_CACHE).Database);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取锁
|
|
||||||
/// </summary>
|
|
||||||
protected Task<RedisLocker> GetLockerAsync(string lockerName)
|
|
||||||
{
|
|
||||||
return RedisLocker.GetLockerAsync(RedisDatabase, lockerName, TimeSpan.FromSeconds(Numbers.SECS_REDIS_LOCK_EXPIRY)
|
|
||||||
, Numbers.MAX_LIMIT_RETRY_CNT_REDIS_LOCK, TimeSpan.FromSeconds(Numbers.SECS_REDIS_LOCK_RETRY_DELAY));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取锁(仅获取一次)
|
|
||||||
/// </summary>
|
|
||||||
protected Task<RedisLocker> GetLockerOnceAsync(string lockerName)
|
|
||||||
{
|
|
||||||
return RedisLocker.GetLockerAsync(RedisDatabase, lockerName, TimeSpan.FromSeconds(Numbers.SECS_REDIS_LOCK_EXPIRY), 1
|
|
||||||
, TimeSpan.FromSeconds(Numbers.SECS_REDIS_LOCK_RETRY_DELAY));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,159 +0,0 @@
|
|||||||
using CsvHelper;
|
|
||||||
using Microsoft.Net.Http.Headers;
|
|
||||||
using NetAdmin.Application.Repositories;
|
|
||||||
using NetAdmin.Domain;
|
|
||||||
using NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
using NetAdmin.Domain.Dto.Dependency;
|
|
||||||
|
|
||||||
namespace NetAdmin.Application.Services;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 仓储服务基类
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TEntity">实体类型</typeparam>
|
|
||||||
/// <typeparam name="TPrimary">主键类型</typeparam>
|
|
||||||
/// <typeparam name="TLogger">日志类型</typeparam>
|
|
||||||
public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicRepository<TEntity, TPrimary> rpo) : ServiceBase<TLogger>
|
|
||||||
where TEntity : EntityBase<TPrimary> //
|
|
||||||
where TPrimary : IEquatable<TPrimary>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 默认仓储
|
|
||||||
/// </summary>
|
|
||||||
protected BasicRepository<TEntity, TPrimary> Rpo => rpo;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 启用级联保存
|
|
||||||
/// </summary>
|
|
||||||
protected bool EnableCascadeSave {
|
|
||||||
get => Rpo.DbContextOptions.EnableCascadeSave;
|
|
||||||
set => Rpo.DbContextOptions.EnableCascadeSave = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 导出实体
|
|
||||||
/// </summary>
|
|
||||||
protected static async Task<IActionResult> ExportAsync<TQuery, TExport>( //
|
|
||||||
Func<QueryReq<TQuery>, ISelectGrouping<TEntity, TEntity>> selector, QueryReq<TQuery> query, string fileName
|
|
||||||
, Expression<Func<ISelectGroupingAggregate<TEntity, TEntity>, object>> listExp = null)
|
|
||||||
where TQuery : DataAbstraction, new()
|
|
||||||
{
|
|
||||||
var list = await selector(query).Take(Numbers.MAX_LIMIT_EXPORT).ToListAsync(listExp).ConfigureAwait(false);
|
|
||||||
return await GetExportFileStreamAsync<TExport>(fileName, list).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 导出实体
|
|
||||||
/// </summary>
|
|
||||||
protected static async Task<IActionResult> ExportAsync<TQuery, TExport>( //
|
|
||||||
Func<QueryReq<TQuery>, ISelect<TEntity>> selector, QueryReq<TQuery> query, string fileName, Expression<Func<TEntity, object>> listExp = null)
|
|
||||||
where TQuery : DataAbstraction, new()
|
|
||||||
{
|
|
||||||
var select = selector(query)
|
|
||||||
#if DBTYPE_SQLSERVER
|
|
||||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
|
||||||
#endif
|
|
||||||
.Take(Numbers.MAX_LIMIT_EXPORT);
|
|
||||||
|
|
||||||
object list = listExp == null ? await select.ToListAsync().ConfigureAwait(false) : await select.ToListAsync(listExp).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return await GetExportFileStreamAsync<TExport>(fileName, list).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 更新实体
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newValue">新的值</param>
|
|
||||||
/// <param name="includeFields">包含的属性</param>
|
|
||||||
/// <param name="excludeFields">排除的属性</param>
|
|
||||||
/// <param name="whereExp">查询表达式</param>
|
|
||||||
/// <param name="whereSql">查询sql</param>
|
|
||||||
/// <param name="ignoreVersion">是否忽略版本锁</param>
|
|
||||||
/// <returns>更新行数</returns>
|
|
||||||
protected Task<int> UpdateAsync( //
|
|
||||||
TEntity newValue //
|
|
||||||
, IEnumerable<string> includeFields //
|
|
||||||
, string[] excludeFields = null //
|
|
||||||
, Expression<Func<TEntity, bool>> whereExp = null //
|
|
||||||
, string whereSql = null //
|
|
||||||
, bool ignoreVersion = false)
|
|
||||||
{
|
|
||||||
// 默认匹配主键
|
|
||||||
whereExp ??= a => a.Id.Equals(newValue.Id);
|
|
||||||
var update = BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql);
|
|
||||||
return update.ExecuteAffrowsAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DBTYPE_SQLSERVER
|
|
||||||
/// <summary>
|
|
||||||
/// 更新实体
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newValue">新的值</param>
|
|
||||||
/// <param name="includeFields">包含的属性</param>
|
|
||||||
/// <param name="excludeFields">排除的属性</param>
|
|
||||||
/// <param name="whereExp">查询表达式</param>
|
|
||||||
/// <param name="whereSql">查询sql</param>
|
|
||||||
/// <param name="ignoreVersion">是否忽略版本锁</param>
|
|
||||||
/// <returns>更新后的实体列表</returns>
|
|
||||||
protected Task<List<TEntity>> UpdateReturnListAsync( //
|
|
||||||
TEntity newValue //
|
|
||||||
, IEnumerable<string> includeFields //
|
|
||||||
, string[] excludeFields = null //
|
|
||||||
, Expression<Func<TEntity, bool>> whereExp = null //
|
|
||||||
, string whereSql = null //
|
|
||||||
, bool ignoreVersion = false)
|
|
||||||
{
|
|
||||||
// 默认匹配主键
|
|
||||||
whereExp ??= a => a.Id.Equals(newValue.Id);
|
|
||||||
return BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql).ExecuteUpdatedAsync();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private static async Task<IActionResult> GetExportFileStreamAsync<TExport>(string fileName, object list)
|
|
||||||
{
|
|
||||||
var listTyped = list.Adapt<List<TExport>>();
|
|
||||||
var stream = new MemoryStream();
|
|
||||||
var writer = new StreamWriter(stream);
|
|
||||||
var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
|
|
||||||
csv.WriteHeader<TExport>();
|
|
||||||
await csv.NextRecordAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
foreach (var item in listTyped) {
|
|
||||||
csv.WriteRecord(item);
|
|
||||||
await csv.NextRecordAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
await csv.FlushAsync().ConfigureAwait(false);
|
|
||||||
_ = stream.Seek(0, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
App.HttpContext.Response.Headers.ContentDisposition
|
|
||||||
= new ContentDispositionHeaderValue(Chars.FLG_HTTP_HEADER_VALUE_ATTACHMENT) {
|
|
||||||
FileNameStar
|
|
||||||
= $"{fileName}_{DateTime.Now:yyyy.MM.dd-HH.mm.ss}.csv"
|
|
||||||
}.ToString();
|
|
||||||
|
|
||||||
return new FileStreamResult(stream, Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_OCTET_STREAM);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IUpdate<TEntity> BuildUpdate( //
|
|
||||||
TEntity entity //
|
|
||||||
, IEnumerable<string> includeFields //
|
|
||||||
, string[] excludeFields = null //
|
|
||||||
, bool ignoreVersion = false)
|
|
||||||
{
|
|
||||||
var updateExp = includeFields == null
|
|
||||||
? Rpo.UpdateDiy.SetSource(entity)
|
|
||||||
: Rpo.UpdateDiy.SetDto(includeFields!.ToDictionary(
|
|
||||||
x => x, x => typeof(TEntity).GetProperty(x, BindingFlags.Public | BindingFlags.Instance)!.GetValue(entity)));
|
|
||||||
if (excludeFields != null) {
|
|
||||||
updateExp = updateExp.IgnoreColumns(excludeFields);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ignoreVersion && entity is IFieldVersion ver) {
|
|
||||||
updateExp = updateExp.Where($"{nameof(IFieldVersion.Version)} = @version", new { version = ver.Version });
|
|
||||||
}
|
|
||||||
|
|
||||||
return updateExp;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
using NetAdmin.Domain.Contexts;
|
|
||||||
|
|
||||||
namespace NetAdmin.Application.Services;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public abstract class ServiceBase<TLogger> : ServiceBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ServiceBase{TLogger}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
protected ServiceBase() //
|
|
||||||
{
|
|
||||||
Logger = App.GetService<ILogger<TLogger>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 日志记录器
|
|
||||||
/// </summary>
|
|
||||||
protected ILogger<TLogger> Logger { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 服务基类
|
|
||||||
/// </summary>
|
|
||||||
public abstract class ServiceBase : IScoped, IService
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ServiceBase" /> class.
|
|
||||||
/// </summary>
|
|
||||||
protected ServiceBase()
|
|
||||||
{
|
|
||||||
UserToken = App.GetService<ContextUserToken>();
|
|
||||||
ServiceId = Guid.NewGuid();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Guid ServiceId { get; init; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public ContextUserToken UserToken { get; set; }
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
using NetAdmin.Application.Modules.Tpl;
|
|
||||||
|
|
||||||
namespace NetAdmin.Application.Services.Tpl.Dependency;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 示例服务
|
|
||||||
/// </summary>
|
|
||||||
public interface IExampleService : IService, IExampleModule;
|
|
@ -1,128 +0,0 @@
|
|||||||
using NetAdmin.Application.Repositories;
|
|
||||||
using NetAdmin.Application.Services.Tpl.Dependency;
|
|
||||||
using NetAdmin.Domain.DbMaps.Tpl;
|
|
||||||
using NetAdmin.Domain.Dto.Dependency;
|
|
||||||
using NetAdmin.Domain.Dto.Tpl.Example;
|
|
||||||
|
|
||||||
namespace NetAdmin.Application.Services.Tpl;
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IExampleService" />
|
|
||||||
public sealed class ExampleService(BasicRepository<Tpl_Example, long> rpo) //
|
|
||||||
: RepositoryService<Tpl_Example, long, IExampleService>(rpo), IExampleService
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
|
||||||
{
|
|
||||||
req.ThrowIfInvalid();
|
|
||||||
var ret = 0;
|
|
||||||
|
|
||||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
|
||||||
foreach (var item in req.Items) {
|
|
||||||
ret += await DeleteAsync(item).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<long> CountAsync(QueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
req.ThrowIfInvalid();
|
|
||||||
return QueryInternal(req)
|
|
||||||
#if DBTYPE_SQLSERVER
|
|
||||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
|
||||||
#endif
|
|
||||||
.CountAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public async Task<QueryExampleRsp> CreateAsync(CreateExampleReq req)
|
|
||||||
{
|
|
||||||
req.ThrowIfInvalid();
|
|
||||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
|
||||||
return ret.Adapt<QueryExampleRsp>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<int> DeleteAsync(DelReq req)
|
|
||||||
{
|
|
||||||
req.ThrowIfInvalid();
|
|
||||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<bool> ExistAsync(QueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
req.ThrowIfInvalid();
|
|
||||||
return QueryInternal(req)
|
|
||||||
#if DBTYPE_SQLSERVER
|
|
||||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
|
||||||
#endif
|
|
||||||
.AnyAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<IActionResult> ExportAsync(QueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
req.ThrowIfInvalid();
|
|
||||||
return ExportAsync<QueryExampleReq, QueryExampleRsp>(QueryInternal, req, Ln.示例导出);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public async Task<QueryExampleRsp> GetAsync(QueryExampleReq req)
|
|
||||||
{
|
|
||||||
req.ThrowIfInvalid();
|
|
||||||
var ret = await QueryInternal(new QueryReq<QueryExampleReq> { Filter = req, Order = Orders.None }).ToOneAsync().ConfigureAwait(false);
|
|
||||||
return ret.Adapt<QueryExampleRsp>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public async Task<PagedQueryRsp<QueryExampleRsp>> PagedQueryAsync(PagedQueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
req.ThrowIfInvalid();
|
|
||||||
var list = await QueryInternal(req)
|
|
||||||
.Page(req.Page, req.PageSize)
|
|
||||||
#if DBTYPE_SQLSERVER
|
|
||||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
|
||||||
#endif
|
|
||||||
.Count(out var total)
|
|
||||||
.ToListAsync()
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
return new PagedQueryRsp<QueryExampleRsp>(req.Page, req.PageSize, total, list.Adapt<IEnumerable<QueryExampleRsp>>());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public async Task<IEnumerable<QueryExampleRsp>> QueryAsync(QueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
req.ThrowIfInvalid();
|
|
||||||
var ret = await QueryInternal(req)
|
|
||||||
#if DBTYPE_SQLSERVER
|
|
||||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
|
||||||
#endif
|
|
||||||
.Take(req.Count)
|
|
||||||
.ToListAsync()
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
return ret.Adapt<IEnumerable<QueryExampleRsp>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ISelect<Tpl_Example> QueryInternal(QueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
|
||||||
|
|
||||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
|
||||||
switch (req.Order) {
|
|
||||||
case Orders.None:
|
|
||||||
return ret;
|
|
||||||
case 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
using NetAdmin.Application.Services;
|
|
||||||
|
|
||||||
namespace NetAdmin.Cache;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 缓存基类
|
|
||||||
/// </summary>
|
|
||||||
public abstract class CacheBase<TCacheContainer, TService>(TCacheContainer cache, TService service) : ICache<TCacheContainer, TService>
|
|
||||||
where TService : IService
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public TCacheContainer Cache => cache;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public TService Service => service;
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
using System.Runtime.CompilerServices;
|
|
||||||
using NetAdmin.Application.Services;
|
|
||||||
|
|
||||||
namespace NetAdmin.Cache;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 分布式缓存
|
|
||||||
/// </summary>
|
|
||||||
public abstract class DistributedCache<TService>(IDistributedCache cache, TService service) : CacheBase<IDistributedCache, TService>(cache, service)
|
|
||||||
where TService : IService
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建缓存
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key">缓存键</param>
|
|
||||||
/// <param name="createObj">创建对象</param>
|
|
||||||
/// <param name="absLifeTime">绝对过期时间</param>
|
|
||||||
/// <param name="slideLifeTime">滑动过期时间</param>
|
|
||||||
/// <typeparam name="T">缓存对象类型</typeparam>
|
|
||||||
/// <returns>缓存对象</returns>
|
|
||||||
protected Task CreateAsync<T>(string key, T createObj, TimeSpan? absLifeTime = null, TimeSpan? slideLifeTime = null)
|
|
||||||
{
|
|
||||||
var cacheWrite = createObj.ToJson();
|
|
||||||
|
|
||||||
var options = new DistributedCacheEntryOptions();
|
|
||||||
if (absLifeTime != null) {
|
|
||||||
_ = options.SetAbsoluteExpiration(absLifeTime.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slideLifeTime != null) {
|
|
||||||
_ = options.SetSlidingExpiration(slideLifeTime.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Cache.SetAsync(key, cacheWrite.Hex(), options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取缓存
|
|
||||||
/// </summary>
|
|
||||||
protected async Task<T> GetAsync<T>(string key)
|
|
||||||
{
|
|
||||||
var cacheRead = await Cache.GetStringAsync(key).ConfigureAwait(false);
|
|
||||||
try {
|
|
||||||
return cacheRead != null ? cacheRead.ToObject<T>() : default;
|
|
||||||
}
|
|
||||||
catch (JsonException) {
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取缓存键
|
|
||||||
/// </summary>
|
|
||||||
protected string GetCacheKey(string id = "0", [CallerMemberName] string memberName = null)
|
|
||||||
{
|
|
||||||
return $"{GetType().FullName}.{memberName}.{id}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或创建缓存
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key">缓存键</param>
|
|
||||||
/// <param name="createProc">创建函数</param>
|
|
||||||
/// <param name="absLifeTime">绝对过期时间</param>
|
|
||||||
/// <param name="slideLifeTime">滑动过期时间</param>
|
|
||||||
/// <typeparam name="T">缓存对象类型</typeparam>
|
|
||||||
/// <returns>缓存对象</returns>
|
|
||||||
protected async Task<T> GetOrCreateAsync<T>(string key, Func<Task<T>> createProc, TimeSpan? absLifeTime = null, TimeSpan? slideLifeTime = null)
|
|
||||||
{
|
|
||||||
var cacheRead = await GetAsync<T>(key).ConfigureAwait(false);
|
|
||||||
if (cacheRead is not null && App.HttpContext?.Request.Headers.CacheControl.FirstOrDefault() != Chars.FLG_HTTP_HEADER_VALUE_NO_CACHE) {
|
|
||||||
return cacheRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
var obj = await createProc.Invoke().ConfigureAwait(false);
|
|
||||||
|
|
||||||
var cacheWrite = obj?.ToJson();
|
|
||||||
if (cacheWrite == null) {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
await CreateAsync(key, obj, absLifeTime, slideLifeTime).ConfigureAwait(false);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除缓存
|
|
||||||
/// </summary>
|
|
||||||
protected Task RemoveAsync(string key)
|
|
||||||
{
|
|
||||||
return Cache.RemoveAsync(key);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
using NetAdmin.Application.Services;
|
|
||||||
|
|
||||||
namespace NetAdmin.Cache;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 缓存接口
|
|
||||||
/// </summary>
|
|
||||||
public interface ICache<out TCacheLoad, out TService>
|
|
||||||
where TService : IService
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 缓存对象
|
|
||||||
/// </summary>
|
|
||||||
TCacheLoad Cache { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 关联的服务
|
|
||||||
/// </summary>
|
|
||||||
public TService Service { get; }
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
using NetAdmin.Application.Services;
|
|
||||||
|
|
||||||
namespace NetAdmin.Cache;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 内存缓存
|
|
||||||
/// </summary>
|
|
||||||
public abstract class MemoryCache<TService>(IMemoryCache cache, TService service) : CacheBase<IMemoryCache, TService>(cache, service)
|
|
||||||
where TService : IService;
|
|
@ -1,6 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<Import Project="$(SolutionDir)/build/code.quality.props"/>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="../NetAdmin.Application/NetAdmin.Application.csproj"/>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -1,9 +0,0 @@
|
|||||||
using NetAdmin.Application.Modules.Tpl;
|
|
||||||
using NetAdmin.Application.Services.Tpl.Dependency;
|
|
||||||
|
|
||||||
namespace NetAdmin.Cache.Tpl.Dependency;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 示例缓存
|
|
||||||
/// </summary>
|
|
||||||
public interface IExampleCache : ICache<IDistributedCache, IExampleService>, IExampleModule;
|
|
@ -1,65 +0,0 @@
|
|||||||
using NetAdmin.Application.Services.Tpl.Dependency;
|
|
||||||
using NetAdmin.Cache.Tpl.Dependency;
|
|
||||||
using NetAdmin.Domain.Dto.Dependency;
|
|
||||||
using NetAdmin.Domain.Dto.Tpl.Example;
|
|
||||||
|
|
||||||
namespace NetAdmin.Cache.Tpl;
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IExampleCache" />
|
|
||||||
public sealed class ExampleCache(IDistributedCache cache, IExampleService service)
|
|
||||||
: DistributedCache<IExampleService>(cache, service), IScoped, IExampleCache
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
|
||||||
{
|
|
||||||
return Service.BulkDeleteAsync(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<long> CountAsync(QueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
return Service.CountAsync(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<QueryExampleRsp> CreateAsync(CreateExampleReq req)
|
|
||||||
{
|
|
||||||
return Service.CreateAsync(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<int> DeleteAsync(DelReq req)
|
|
||||||
{
|
|
||||||
return Service.DeleteAsync(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<bool> ExistAsync(QueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
return Service.ExistAsync(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<IActionResult> ExportAsync(QueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
return Service.ExportAsync(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<QueryExampleRsp> GetAsync(QueryExampleReq req)
|
|
||||||
{
|
|
||||||
return Service.GetAsync(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<PagedQueryRsp<QueryExampleRsp>> PagedQueryAsync(PagedQueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
return Service.PagedQueryAsync(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<IEnumerable<QueryExampleRsp>> QueryAsync(QueryReq<QueryExampleReq> req)
|
|
||||||
{
|
|
||||||
return Service.QueryAsync(req);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 危险字段标记
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Property)]
|
|
||||||
public sealed class DangerFieldAttribute : Attribute;
|
|
@ -1,23 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 支付宝验证器(手机或邮箱)
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class AlipayAttribute : ValidationAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="AlipayAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public AlipayAttribute()
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln.支付宝账号);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool IsValid(object value)
|
|
||||||
{
|
|
||||||
return new MobileAttribute().IsValid(value) || new EmailAddressAttribute().IsValid(value);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 证件号码验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class CertificateAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="CertificateAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public CertificateAttribute() //
|
|
||||||
: base(Chars.RGX_CERTIFICATE)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln.无效证件号码);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 中文姓名验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class ChineseNameAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ChineseNameAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public ChineseNameAttribute() //
|
|
||||||
: base(Chars.RGXL_CHINESE_NAME)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln.中文姓名);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 时间表达式验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class CronAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="CronAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public CronAttribute() //
|
|
||||||
: base(Chars.RGXL_CRON)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln.时间表达式);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 邮箱验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class EmailAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="EmailAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public EmailAttribute() //
|
|
||||||
: base(Chars.RGXL_EMAIL)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln.电子邮箱);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 邀请码验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class InviteCodeAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="InviteCodeAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public InviteCodeAttribute() //
|
|
||||||
: base(Chars.RGX_INVITE_CODE)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln.邀请码不正确);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// JSON文本验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class JsonStringAttribute : ValidationAttribute
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
|
|
||||||
{
|
|
||||||
return (value as string).IsJsonString() ? ValidationResult.Success : new ValidationResult(Ln.非JSON字符串, [validationContext.MemberName]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 手机号码验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class MobileAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="MobileAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public MobileAttribute() //
|
|
||||||
: base(Chars.RGX_MOBILE)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln.手机号码不正确);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 密码验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class PasswordAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="PasswordAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public PasswordAttribute() //
|
|
||||||
: base(Chars.RGX_PASSWORD)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln._8位以上数字字母组合);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 交易密码验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class PayPasswordAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="PayPasswordAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public PayPasswordAttribute() //
|
|
||||||
: base(Chars.RGX_PAY_PASSWORD)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln._6位数字);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 端口号验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class PortAttribute : RangeAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="PortAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public PortAttribute() //
|
|
||||||
: base(1, ushort.MaxValue)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln.无效端口号);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 正则表达式验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
#pragma warning disable DesignedForInheritance
|
|
||||||
public class RegexAttribute : RegularExpressionAttribute
|
|
||||||
#pragma warning restore DesignedForInheritance
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="RegexAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
protected RegexAttribute(string pattern) //
|
|
||||||
: base(pattern) { }
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 固定电话验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class TelephoneAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="TelephoneAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public TelephoneAttribute() //
|
|
||||||
: base(Chars.RGX_TELEPHONE)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln.区号电话号码分机号);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 用户名验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class UserNameAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="UserNameAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public UserNameAttribute() //
|
|
||||||
: base(Chars.RGX_USERNAME)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool IsValid(object value)
|
|
||||||
{
|
|
||||||
if (!base.IsValid(value)) {
|
|
||||||
ErrorMessageResourceName = nameof(Ln.用户名长度4位以上);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!new MobileAttribute().IsValid(value)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 不能是手机号码
|
|
||||||
ErrorMessageResourceName = nameof(Ln.用户名不能是手机号码);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 验证码验证器
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
|
||||||
public sealed class VerifyCodeAttribute : RegexAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="VerifyCodeAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public VerifyCodeAttribute() //
|
|
||||||
: base(Chars.RGX_VERIFY_CODE)
|
|
||||||
{
|
|
||||||
ErrorMessageResourceName = nameof(Ln.验证码不正确);
|
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标记一个枚举的状态指示
|
|
||||||
/// </summary>
|
|
||||||
/// <inheritdoc />
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Enum)]
|
|
||||||
public sealed class IndicatorAttribute(string indicate) : Attribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 状态指示
|
|
||||||
/// </summary>
|
|
||||||
public string Indicate { get; } = indicate;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Attributes;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标记一个字段启用服务器时间
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Property)]
|
|
||||||
public sealed class ServerTimeAttribute : Attribute;
|
|
@ -1,9 +0,0 @@
|
|||||||
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
|
|
||||||
|
|
||||||
namespace NetAdmin.Domain.Attributes;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标记一个字段启用雪花编号生成
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Property)]
|
|
||||||
public sealed class SnowflakeAttribute : Attribute;
|
|
@ -1,58 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Contexts;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 上下文用户凭据
|
|
||||||
/// </summary>
|
|
||||||
public sealed record ContextUserToken : DataAbstraction
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 部门编号
|
|
||||||
/// </summary>
|
|
||||||
/// ReSharper disable once MemberCanBePrivate.Global
|
|
||||||
public long DeptId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 用户编号
|
|
||||||
/// </summary>
|
|
||||||
/// ReSharper disable once MemberCanBePrivate.Global
|
|
||||||
public long Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 做授权验证的Token,全局唯一,可以随时重置(强制下线)
|
|
||||||
/// </summary>
|
|
||||||
/// ReSharper disable once MemberCanBePrivate.Global
|
|
||||||
public Guid Token { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 用户名
|
|
||||||
/// </summary>
|
|
||||||
/// ReSharper disable once MemberCanBePrivate.Global
|
|
||||||
public string UserName { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从HttpContext 创建上下文用户
|
|
||||||
/// </summary>
|
|
||||||
public static ContextUserToken Create()
|
|
||||||
{
|
|
||||||
var claim = App.User?.FindFirst(nameof(ContextUserToken));
|
|
||||||
return claim?.Value.ToObject<ContextUserToken>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从 QueryUserRsp 创建上下文用户
|
|
||||||
/// </summary>
|
|
||||||
public static ContextUserToken Create(long id, Guid token, string userName, long deptId)
|
|
||||||
{
|
|
||||||
return new ContextUserToken { Id = id, Token = token, UserName = userName, DeptId = deptId };
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从 Json Web Token 创建上下文用户
|
|
||||||
/// </summary>
|
|
||||||
public static ContextUserToken Create(string jwt)
|
|
||||||
{
|
|
||||||
var claim = JWTEncryption.ReadJwtToken(jwt.TrimPrefix($"{Chars.FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA} "))
|
|
||||||
?.Claims.FirstOrDefault(x => x.Type == nameof(ContextUserToken));
|
|
||||||
return claim?.Value.ToObject<ContextUserToken>();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
namespace NetAdmin.Domain;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 数据基类
|
|
||||||
/// </summary>
|
|
||||||
public abstract record DataAbstraction
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 如果数据校验失败,抛出异常
|
|
||||||
/// </summary>
|
|
||||||
/// <exception cref="NetAdminValidateException">NetAdminValidateException</exception>
|
|
||||||
public void ThrowIfInvalid()
|
|
||||||
{
|
|
||||||
var validationResult = this.TryValidate();
|
|
||||||
if (!validationResult.IsValid) {
|
|
||||||
throw new NetAdminValidateException(validationResult.ValidationResults.ToDictionary( //
|
|
||||||
x => x.MemberNames.First() //
|
|
||||||
, x => new[] { x.ErrorMessage }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return this.ToJson();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 截断所有字符串属性 以符合[MaxLength(x)]特性
|
|
||||||
/// </summary>
|
|
||||||
public void TruncateStrings()
|
|
||||||
{
|
|
||||||
foreach (var property in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType == typeof(string))) {
|
|
||||||
var maxLen = property.GetCustomAttribute<MaxLengthAttribute>(true)?.Length;
|
|
||||||
if (maxLen is null or 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var value = property.GetValue(this);
|
|
||||||
if (value is not string s || s.Length < maxLen) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = s.Sub(0, maxLen.Value);
|
|
||||||
property.SetValue(this, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 数据库实体基类
|
|
||||||
/// </summary>
|
|
||||||
public abstract record EntityBase<T> : DataAbstraction
|
|
||||||
where T : IEquatable<T>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
public virtual T Id { get; init; }
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者客户端IP字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldCreatedClientIp
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者客户端IP
|
|
||||||
/// </summary>
|
|
||||||
int? CreatedClientIp { get; init; }
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者客户端用户代理字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldCreatedClientUserAgent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者客户端用户代理
|
|
||||||
/// </summary>
|
|
||||||
string CreatedUserAgent { get; init; }
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建时间字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldCreatedTime
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建时间
|
|
||||||
/// </summary>
|
|
||||||
DateTime CreatedTime { get; init; }
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建用户字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldCreatedUser
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者编号
|
|
||||||
/// </summary>
|
|
||||||
long? CreatedUserId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者用户名
|
|
||||||
/// </summary>
|
|
||||||
string CreatedUserName { get; init; }
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 启用字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldEnabled
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 是否启用
|
|
||||||
/// </summary>
|
|
||||||
bool Enabled { get; init; }
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改客户端IP字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldModifiedClientIp
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 客户端IP
|
|
||||||
/// </summary>
|
|
||||||
int ModifiedClientIp { get; init; }
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改客户端用户代理字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldModifiedClientUserAgent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 客户端用户代理
|
|
||||||
/// </summary>
|
|
||||||
string ModifiedUserAgent { get; init; }
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改时间字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldModifiedTime
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 修改时间
|
|
||||||
/// </summary>
|
|
||||||
DateTime? ModifiedTime { get; init; }
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改用户字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldModifiedUser
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 修改者编号
|
|
||||||
/// </summary>
|
|
||||||
long? ModifiedUserId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改者用户名
|
|
||||||
/// </summary>
|
|
||||||
string ModifiedUserName { get; init; }
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 拥有者字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldOwner
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 拥有者部门编号
|
|
||||||
/// </summary>
|
|
||||||
long? OwnerDeptId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 拥有者用户编号
|
|
||||||
/// </summary>
|
|
||||||
long? OwnerId { get; init; }
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 排序字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldSort
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 排序值,越大越前
|
|
||||||
/// </summary>
|
|
||||||
long Sort { get; init; }
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 备注字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldSummary
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 备注
|
|
||||||
/// </summary>
|
|
||||||
string Summary { get; init; }
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 版本字段接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IFieldVersion
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 数据版本
|
|
||||||
/// </summary>
|
|
||||||
long Version { get; init; }
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public abstract record ImmutableEntity : ImmutableEntity<long>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[Snowflake]
|
|
||||||
public override long Id { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 不可变实体
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">主键类型</typeparam>
|
|
||||||
public abstract record ImmutableEntity<T> : LiteImmutableEntity<T>, IFieldCreatedUser
|
|
||||||
where T : IEquatable<T>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者编号
|
|
||||||
/// </summary>
|
|
||||||
[Column(CanUpdate = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public long? CreatedUserId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者用户名
|
|
||||||
/// </summary>
|
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanUpdate = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public virtual string CreatedUserName { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
public override T Id { get; init; }
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public abstract record LiteImmutableEntity : LiteImmutableEntity<long>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[Snowflake]
|
|
||||||
public override long Id { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 轻型不可变实体
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">主键类型</typeparam>
|
|
||||||
public abstract record LiteImmutableEntity<T> : EntityBase<T>, IFieldCreatedTime
|
|
||||||
where T : IEquatable<T>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建时间
|
|
||||||
/// </summary>
|
|
||||||
[Column(ServerTime = DateTimeKind.Local, CanUpdate = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public virtual DateTime CreatedTime { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public override T Id { get; init; }
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public abstract record LiteMutableEntity : LiteMutableEntity<long>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[Snowflake]
|
|
||||||
public override long Id { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 轻型可变实体
|
|
||||||
/// </summary>
|
|
||||||
public abstract record LiteMutableEntity<T> : LiteImmutableEntity<T>, IFieldModifiedTime
|
|
||||||
where T : IEquatable<T>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
public override T Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改时间
|
|
||||||
/// </summary>
|
|
||||||
[Column(ServerTime = DateTimeKind.Local, CanInsert = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public virtual DateTime? ModifiedTime { get; init; }
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public abstract record LiteVersionEntity : LiteVersionEntity<long>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[Snowflake]
|
|
||||||
public override long Id { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 乐观锁轻型可变实体
|
|
||||||
/// </summary>
|
|
||||||
public abstract record LiteVersionEntity<T> : LiteMutableEntity<T>, IFieldVersion
|
|
||||||
where T : IEquatable<T>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[Snowflake]
|
|
||||||
public override T Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 数据版本
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsVersion = true, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public virtual long Version { get; init; }
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public abstract record MutableEntity : MutableEntity<long>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[Snowflake]
|
|
||||||
public override long Id { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 可变实体
|
|
||||||
/// </summary>
|
|
||||||
public abstract record MutableEntity<T> : LiteMutableEntity<T>, IFieldCreatedUser, IFieldModifiedUser
|
|
||||||
where T : IEquatable<T>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者编号
|
|
||||||
/// </summary>
|
|
||||||
[Column(CanUpdate = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public virtual long? CreatedUserId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者用户名
|
|
||||||
/// </summary>
|
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanUpdate = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public virtual string CreatedUserName { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
public override T Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改者编号
|
|
||||||
/// </summary>
|
|
||||||
[Column(CanInsert = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public long? ModifiedUserId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改者用户名
|
|
||||||
/// </summary>
|
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanInsert = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public string ModifiedUserName { get; init; }
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public abstract record SimpleEntity : SimpleEntity<long>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[Snowflake]
|
|
||||||
public override long Id { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 简单实体
|
|
||||||
/// </summary>
|
|
||||||
public abstract record SimpleEntity<T> : EntityBase<T>
|
|
||||||
where T : IEquatable<T>;
|
|
@ -1,59 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public abstract record VersionEntity : VersionEntity<long>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[Snowflake]
|
|
||||||
public override long Id { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 乐观锁可变实体
|
|
||||||
/// </summary>
|
|
||||||
public abstract record VersionEntity<T> : LiteVersionEntity<T>, IFieldModifiedUser, IFieldCreatedUser
|
|
||||||
where T : IEquatable<T>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者编号
|
|
||||||
/// </summary>
|
|
||||||
[Column(CanUpdate = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public virtual long? CreatedUserId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建者用户名
|
|
||||||
/// </summary>
|
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanUpdate = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public virtual string CreatedUserName { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一编码
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
public override T Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改者编号
|
|
||||||
/// </summary>
|
|
||||||
[Column(CanInsert = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public virtual long? ModifiedUserId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改者用户名
|
|
||||||
/// </summary>
|
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanInsert = false, Position = -1)]
|
|
||||||
[CsvIgnore]
|
|
||||||
[JsonIgnore]
|
|
||||||
public virtual string ModifiedUserName { get; init; }
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.DbMaps.Tpl;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 示例表
|
|
||||||
/// </summary>
|
|
||||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Tpl_Example))]
|
|
||||||
public record Tpl_Example : VersionEntity;
|
|
@ -1,16 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Dto.Dependency;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 批量请求
|
|
||||||
/// </summary>
|
|
||||||
public sealed record BulkReq<T> : DataAbstraction
|
|
||||||
where T : DataAbstraction, new()
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 请求对象
|
|
||||||
/// </summary>
|
|
||||||
[MaxLength(Numbers.MAX_LIMIT_BULK_REQ)]
|
|
||||||
[MinLength(1)]
|
|
||||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.请求对象不能为空))]
|
|
||||||
public IEnumerable<T> Items { get; init; }
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Dto.Dependency;
|
|
||||||
|
|
||||||
/// <inheritdoc cref="DelReq{T}" />
|
|
||||||
public sealed record DelReq : DelReq<long>;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求:通过编号删除
|
|
||||||
/// </summary>
|
|
||||||
public record DelReq<T> : EntityBase<T>
|
|
||||||
where T : IEquatable<T>
|
|
||||||
{
|
|
||||||
/// <inheritdoc cref="EntityBase{T}.Id" />
|
|
||||||
public override T Id { get; init; }
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Dto.Dependency;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 信息:分页
|
|
||||||
/// </summary>
|
|
||||||
public interface IPagedInfo
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 当前页码
|
|
||||||
/// </summary>
|
|
||||||
int Page { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 页容量
|
|
||||||
/// </summary>
|
|
||||||
int PageSize { get; init; }
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Dto.Dependency;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 空请求
|
|
||||||
/// </summary>
|
|
||||||
public sealed record NopReq : DataAbstraction;
|
|
@ -1,16 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Dto.Dependency;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求:分页查询
|
|
||||||
/// </summary>
|
|
||||||
public sealed record PagedQueryReq<T> : QueryReq<T>, IPagedInfo
|
|
||||||
where T : DataAbstraction, new()
|
|
||||||
{
|
|
||||||
/// <inheritdoc cref="IPagedInfo.Page" />
|
|
||||||
[Range(1, Numbers.MAX_LIMIT_QUERY_PAGE_NO)]
|
|
||||||
public int Page { get; init; } = 1;
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IPagedInfo.PageSize" />
|
|
||||||
[Range(1, Numbers.MAX_LIMIT_QUERY_PAGE_SIZE)]
|
|
||||||
public int PageSize { get; init; } = Numbers.DEF_PAGE_SIZE_QUERY;
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Dto.Dependency;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 响应:分页查询
|
|
||||||
/// </summary>
|
|
||||||
public sealed record PagedQueryRsp<T>(int Page, int PageSize, long Total, IEnumerable<T> Rows) : IPagedInfo
|
|
||||||
where T : DataAbstraction
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 数据行
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<T> Rows { get; } = Rows;
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IPagedInfo.Page" />
|
|
||||||
public int Page { get; init; } = Page;
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IPagedInfo.PageSize" />
|
|
||||||
public int PageSize { get; init; } = PageSize;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 数据总条
|
|
||||||
/// </summary>
|
|
||||||
public long Total { get; init; } = Total;
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Dto.Dependency;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求:查询
|
|
||||||
/// </summary>
|
|
||||||
public record QueryReq<T> : DataAbstraction
|
|
||||||
where T : DataAbstraction, new()
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 取前n条
|
|
||||||
/// </summary>
|
|
||||||
[Range(1, Numbers.MAX_LIMIT_QUERY)]
|
|
||||||
public int Count { get; init; } = Numbers.MAX_LIMIT_QUERY;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 动态查询条件
|
|
||||||
/// </summary>
|
|
||||||
public DynamicFilterInfo DynamicFilter { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查询条件
|
|
||||||
/// </summary>
|
|
||||||
public T Filter { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查询关键字
|
|
||||||
/// </summary>
|
|
||||||
public string Keywords { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 排序方式
|
|
||||||
/// </summary>
|
|
||||||
public Orders? Order { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 排序字段
|
|
||||||
/// </summary>
|
|
||||||
public string Prop { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 所需字段
|
|
||||||
/// </summary>
|
|
||||||
public string[] RequiredFields { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 列表表达式
|
|
||||||
/// </summary>
|
|
||||||
public Expression<Func<TEntity, TEntity>> GetToListExp<TEntity>()
|
|
||||||
{
|
|
||||||
if (RequiredFields.NullOrEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var expParameter = Expression.Parameter(typeof(TEntity), "a");
|
|
||||||
var bindings = new List<MemberBinding>();
|
|
||||||
|
|
||||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
|
||||||
foreach (var field in RequiredFields) {
|
|
||||||
var prop = typeof(TEntity).GetProperty(field);
|
|
||||||
if (prop == null || prop.GetCustomAttribute<DangerFieldAttribute>() != null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var propExp = Expression.Property(expParameter, prop);
|
|
||||||
var binding = Expression.Bind(prop, propExp);
|
|
||||||
bindings.Add(binding);
|
|
||||||
}
|
|
||||||
|
|
||||||
var expBody = Expression.MemberInit(Expression.New(typeof(TEntity)), bindings);
|
|
||||||
return Expression.Lambda<Func<TEntity, TEntity>>(expBody, expParameter);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using NetAdmin.Domain.Enums;
|
|
||||||
|
|
||||||
namespace NetAdmin.Domain.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 动态过滤条件生成器
|
|
||||||
/// </summary>
|
|
||||||
public sealed record DfBuilder
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 构建生成器
|
|
||||||
/// </summary>
|
|
||||||
public static DynamicFilterInfo New(DynamicFilterLogics logic)
|
|
||||||
{
|
|
||||||
return new DynamicFilterInfo { Logic = logic, Filters = [] };
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,125 +0,0 @@
|
|||||||
using NetAdmin.Domain.Enums;
|
|
||||||
|
|
||||||
namespace NetAdmin.Domain.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 动态过滤条件
|
|
||||||
/// </summary>
|
|
||||||
public sealed record DynamicFilterInfo : DataAbstraction
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 字段名
|
|
||||||
/// </summary>
|
|
||||||
public string Field { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 子过滤条件
|
|
||||||
/// </summary>
|
|
||||||
public List<DynamicFilterInfo> Filters { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 子过滤条件逻辑关系
|
|
||||||
/// </summary>
|
|
||||||
public DynamicFilterLogics Logic { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 操作符
|
|
||||||
/// </summary>
|
|
||||||
public DynamicFilterOperators Operator { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 值
|
|
||||||
/// </summary>
|
|
||||||
public object Value { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 隐式转换为 FreeSql 的 DynamicFilterInfo 对象
|
|
||||||
/// </summary>
|
|
||||||
public static implicit operator FreeSql.Internal.Model.DynamicFilterInfo(DynamicFilterInfo d)
|
|
||||||
{
|
|
||||||
var ret = d.Adapt<FreeSql.Internal.Model.DynamicFilterInfo>();
|
|
||||||
ProcessDynamicFilter(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加子过滤条件
|
|
||||||
/// </summary>
|
|
||||||
public DynamicFilterInfo Add(DynamicFilterInfo df)
|
|
||||||
{
|
|
||||||
if (Filters == null) {
|
|
||||||
return this with { Filters = [df] };
|
|
||||||
}
|
|
||||||
|
|
||||||
Filters.Add(df);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加过滤条件
|
|
||||||
/// </summary>
|
|
||||||
public DynamicFilterInfo Add(string field, DynamicFilterOperators opt, object val)
|
|
||||||
{
|
|
||||||
return Add(new DynamicFilterInfo { Field = field, Operator = opt, Value = val });
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加过滤条件
|
|
||||||
/// </summary>
|
|
||||||
public DynamicFilterInfo AddIf(bool condition, string field, DynamicFilterOperators opt, object val)
|
|
||||||
{
|
|
||||||
return !condition ? this : Add(field, opt, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加过滤条件
|
|
||||||
/// </summary>
|
|
||||||
public DynamicFilterInfo AddIf(bool condition, DynamicFilterInfo df)
|
|
||||||
{
|
|
||||||
return !condition ? this : Add(df);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ParseDateExp(FreeSql.Internal.Model.DynamicFilterInfo d)
|
|
||||||
{
|
|
||||||
var values = ((JsonElement)d.Value).Deserialize<string[]>();
|
|
||||||
if (!DateTime.TryParse(values[0], CultureInfo.InvariantCulture, out _)) {
|
|
||||||
var result = values[0]
|
|
||||||
.ExecuteCSharpCodeAsync<DateTime>([typeof(DateTime).Assembly], nameof(System))
|
|
||||||
.ConfigureAwait(false)
|
|
||||||
.GetAwaiter()
|
|
||||||
.GetResult();
|
|
||||||
values[0] = $"{result:yyyy-MM-dd HH:mm:ss}";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DateTime.TryParse(values[1], CultureInfo.InvariantCulture, out _)) {
|
|
||||||
var result = values[1]
|
|
||||||
.ExecuteCSharpCodeAsync<DateTime>([typeof(DateTime).Assembly], nameof(System))
|
|
||||||
.ConfigureAwait(false)
|
|
||||||
.GetAwaiter()
|
|
||||||
.GetResult();
|
|
||||||
values[1] = $"{result:yyyy-MM-dd HH:mm:ss}";
|
|
||||||
}
|
|
||||||
|
|
||||||
d.Value = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ProcessDynamicFilter(FreeSql.Internal.Model.DynamicFilterInfo d)
|
|
||||||
{
|
|
||||||
if (d?.Filters != null) {
|
|
||||||
foreach (var filterInfo in d.Filters) {
|
|
||||||
ProcessDynamicFilter(filterInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new[] { nameof(IFieldCreatedClientIp.CreatedClientIp), nameof(IFieldModifiedClientIp.ModifiedClientIp) }.Contains(
|
|
||||||
d?.Field, StringComparer.OrdinalIgnoreCase)) {
|
|
||||||
var val = d!.Value?.ToString();
|
|
||||||
if (val?.IsIpV4() == true) {
|
|
||||||
d.Value = val.IpV4ToInt32();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (d?.Operator == DynamicFilterOperator.DateRange) {
|
|
||||||
ParseDateExp(d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 信息:RESTful 风格结果集
|
|
||||||
/// </summary>
|
|
||||||
public record RestfulInfo<T> : DataAbstraction
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 代码
|
|
||||||
/// </summary>
|
|
||||||
/// <example>succeed</example>
|
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
|
||||||
public ErrorCodes Code { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 数据
|
|
||||||
/// </summary>
|
|
||||||
public T Data { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 字符串:"消息内容",或数组:[{"参数名1":"消息内容1"},{"参数名2":"消息内容2"}]
|
|
||||||
/// </summary>
|
|
||||||
/// <example>请求成功</example>
|
|
||||||
public object Msg { get; init; }
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
using NetAdmin.Domain.DbMaps.Tpl;
|
|
||||||
|
|
||||||
namespace NetAdmin.Domain.Dto.Tpl.Example;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求:创建示例
|
|
||||||
/// </summary>
|
|
||||||
public record CreateExampleReq : Tpl_Example;
|
|
@ -1,13 +0,0 @@
|
|||||||
using NetAdmin.Domain.DbMaps.Tpl;
|
|
||||||
|
|
||||||
namespace NetAdmin.Domain.Dto.Tpl.Example;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求:查询示例
|
|
||||||
/// </summary>
|
|
||||||
public sealed record QueryExampleReq : Tpl_Example
|
|
||||||
{
|
|
||||||
/// <inheritdoc cref="EntityBase{T}.Id" />
|
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
|
||||||
public override long Id { get; init; }
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using NetAdmin.Domain.DbMaps.Tpl;
|
|
||||||
|
|
||||||
namespace NetAdmin.Domain.Dto.Tpl.Example;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 响应:查询示例
|
|
||||||
/// </summary>
|
|
||||||
public sealed record QueryExampleRsp : Tpl_Example
|
|
||||||
{
|
|
||||||
/// <inheritdoc cref="EntityBase{T}.Id" />
|
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
|
||||||
public override long Id { get; init; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
|
||||||
public override long Version { get; init; }
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Enums;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 动态查询条件逻辑运算符
|
|
||||||
/// </summary>
|
|
||||||
[Export]
|
|
||||||
public enum DynamicFilterLogics
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 并且
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.并且))]
|
|
||||||
And = 0
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 或者
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.或者))]
|
|
||||||
Or = 1
|
|
||||||
}
|
|
@ -1,158 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Enums;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 动态查询条件操作符
|
|
||||||
/// </summary>
|
|
||||||
[Export]
|
|
||||||
public enum DynamicFilterOperators
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 包含
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.包含))]
|
|
||||||
Contains = 0
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 以什么开始
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.以什么开始))]
|
|
||||||
StartsWith = 1
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 以什么结束
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.以什么结束))]
|
|
||||||
EndsWith = 2
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 不包含
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.不包含))]
|
|
||||||
NotContains = 3
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 不以什么开始
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.不以什么开始))]
|
|
||||||
NotStartsWith = 4
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 不以什么结束
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.不以什么结束))]
|
|
||||||
NotEndsWith = 5
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 等于
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.等于))]
|
|
||||||
Equal = 6
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 等于
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.等于))]
|
|
||||||
Equals = 7
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 等于
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.等于))]
|
|
||||||
Eq = 8
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 不等于
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.不等于))]
|
|
||||||
NotEqual = 9
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 大于
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.大于))]
|
|
||||||
GreaterThan = 10
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 大于等于
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.大于等于))]
|
|
||||||
GreaterThanOrEqual = 11
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 小于
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.小于))]
|
|
||||||
LessThan = 12
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 小于等于
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.小于等于))]
|
|
||||||
LessThanOrEqual = 13
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 范围
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.范围))]
|
|
||||||
Range = 14
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 日期范围
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.日期范围))]
|
|
||||||
DateRange = 15
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 为其中之一
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.为其中之一))]
|
|
||||||
Any = 16
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 不为其中之一
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.不为其中之一))]
|
|
||||||
NotAny = 17
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 自定义
|
|
||||||
/// </summary>
|
|
||||||
[ResourceDescription<Ln>(nameof(Ln.自定义))]
|
|
||||||
Custom = 18
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Enums;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// HTTP 请求方法
|
|
||||||
/// </summary>
|
|
||||||
[Export]
|
|
||||||
public enum HttpMethods
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Connect
|
|
||||||
/// </summary>
|
|
||||||
Connect = 1
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Delete
|
|
||||||
/// </summary>
|
|
||||||
Delete = 2
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get
|
|
||||||
/// </summary>
|
|
||||||
Get = 3
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Head
|
|
||||||
/// </summary>
|
|
||||||
Head = 4
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Options
|
|
||||||
/// </summary>
|
|
||||||
Options = 5
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Patch
|
|
||||||
/// </summary>
|
|
||||||
Patch = 6
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Post
|
|
||||||
/// </summary>
|
|
||||||
Post = 7
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Put
|
|
||||||
/// </summary>
|
|
||||||
Put = 8
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Trace
|
|
||||||
/// </summary>
|
|
||||||
Trace = 9
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Events;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 泛型事件源接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IEventSourceGeneric<out T> : IEventSource
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 事件承载(携带)数据
|
|
||||||
/// </summary>
|
|
||||||
T Data { get; }
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Events;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 种子数据插入完毕事件
|
|
||||||
/// </summary>
|
|
||||||
public sealed record SeedDataInsertedEvent : DataAbstraction, IEventSource
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="SeedDataInsertedEvent" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public SeedDataInsertedEvent(int insertedCount, bool isConsumOnce = false)
|
|
||||||
{
|
|
||||||
IsConsumOnce = isConsumOnce;
|
|
||||||
InsertedCount = insertedCount;
|
|
||||||
CreatedTime = DateTime.Now;
|
|
||||||
EventId = nameof(SeedDataInsertedEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public DateTime CreatedTime { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public string EventId { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public bool IsConsumOnce { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public CancellationToken CancellationToken { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 插入数量
|
|
||||||
/// </summary>
|
|
||||||
public int InsertedCount { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public object Payload { get; init; }
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Events;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sql命令执行后事件
|
|
||||||
/// </summary>
|
|
||||||
public sealed record SqlCommandAfterEvent : SqlCommandBeforeEvent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="SqlCommandAfterEvent" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public SqlCommandAfterEvent(CommandAfterEventArgs e) //
|
|
||||||
: base(e)
|
|
||||||
{
|
|
||||||
ElapsedMilliseconds = (long)((double)e.ElapsedTicks / Stopwatch.Frequency * 1_000);
|
|
||||||
EventId = nameof(SqlCommandAfterEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 耗时(单位:毫秒)
|
|
||||||
/// </summary>
|
|
||||||
/// de
|
|
||||||
private long ElapsedMilliseconds { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.InvariantCulture, "SQL-{0}: {2} ms {1}", Id, Sql, ElapsedMilliseconds);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Events;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sql命令执行前事件
|
|
||||||
/// </summary>
|
|
||||||
public record SqlCommandBeforeEvent : SqlCommandEvent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="SqlCommandBeforeEvent" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public SqlCommandBeforeEvent(CommandBeforeEventArgs e)
|
|
||||||
{
|
|
||||||
Identifier = e.Identifier;
|
|
||||||
Sql = e.Command.ParameterFormat().RemoveWrapped();
|
|
||||||
EventId = nameof(SqlCommandBeforeEvent);
|
|
||||||
CreatedTime = DateTime.Now;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.InvariantCulture, "SQL-{0}: Executing...", Id);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Events;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sql命令事件
|
|
||||||
/// </summary>
|
|
||||||
public abstract record SqlCommandEvent : DataAbstraction, IEventSource
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="SqlCommandEvent" /> class.
|
|
||||||
/// </summary>
|
|
||||||
protected SqlCommandEvent(bool isConsumOnce = false)
|
|
||||||
{
|
|
||||||
IsConsumOnce = isConsumOnce;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public bool IsConsumOnce { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public CancellationToken CancellationToken { get; init; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public DateTime CreatedTime { get; protected init; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public string EventId { get; protected init; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public object Payload { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标识符缩写
|
|
||||||
/// </summary>
|
|
||||||
protected string Id => Identifier.ToString()[..8].ToUpperInvariant();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标识符,可将 CommandBefore 与 CommandAfter 进行匹配
|
|
||||||
/// </summary>
|
|
||||||
protected Guid Identifier { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 关联的Sql语句
|
|
||||||
/// </summary>
|
|
||||||
protected string Sql { get; init; }
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Events;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 同步数据库结构之后事件
|
|
||||||
/// </summary>
|
|
||||||
public sealed record SyncStructureAfterEvent : SyncStructureBeforeEvent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="SyncStructureAfterEvent" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public SyncStructureAfterEvent(SyncStructureBeforeEventArgs e) //
|
|
||||||
: base(e)
|
|
||||||
{
|
|
||||||
EventId = nameof(SyncStructureAfterEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.InvariantCulture, "{0}: {1}: {2}", Id, Ln.数据库结构同步完成, string.Join(',', EntityTypes.Select(x => x.Name)));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Events;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 同步数据库结构之前事件
|
|
||||||
/// </summary>
|
|
||||||
public record SyncStructureBeforeEvent : SqlCommandEvent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="SyncStructureBeforeEvent" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public SyncStructureBeforeEvent(SyncStructureBeforeEventArgs e)
|
|
||||||
{
|
|
||||||
Identifier = e.Identifier;
|
|
||||||
EventId = nameof(SyncStructureBeforeEvent);
|
|
||||||
CreatedTime = DateTime.Now;
|
|
||||||
EntityTypes = e.EntityTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 实体类型
|
|
||||||
/// </summary>
|
|
||||||
protected Type[] EntityTypes { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.InvariantCulture, "{0}: {1}", Id, Ln.数据库同步开始);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<Import Project="$(SolutionDir)/build/code.quality.props"/>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="../NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj"/>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="CronExpressionDescriptor" Version="2.36.0"/>
|
|
||||||
<PackageReference Include="Cronos" Version="0.8.4"/>
|
|
||||||
<PackageReference Include="CsvHelper.NS" Version="33.0.2-ns2"/>
|
|
||||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14"/>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -1,5 +0,0 @@
|
|||||||
global using NetAdmin.Domain.Attributes;
|
|
||||||
global using NetAdmin.Domain.DbMaps.Dependency;
|
|
||||||
global using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
|
||||||
global using CsvIgnore = CsvHelper.Configuration.Attributes.IgnoreAttribute;
|
|
||||||
global using DynamicFilterOperators = NetAdmin.Domain.Enums.DynamicFilterOperators;
|
|
@ -1,7 +0,0 @@
|
|||||||
namespace NetAdmin.Host.Attributes;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标记一个Action,其响应的json结果会被删除值为null的节点
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
|
||||||
public sealed class RemoveNullNodeAttribute : Attribute;
|
|
@ -1,41 +0,0 @@
|
|||||||
namespace NetAdmin.Host.Attributes;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标记一个Action启用事务
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
|
||||||
public sealed class TransactionAttribute : Attribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="TransactionAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public TransactionAttribute() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="TransactionAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public TransactionAttribute(Propagation propagation) //
|
|
||||||
: this(null, propagation) { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="TransactionAttribute" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public TransactionAttribute(IsolationLevel isolationLevel, Propagation propagation) //
|
|
||||||
: this(new IsolationLevel?(isolationLevel), propagation) { }
|
|
||||||
|
|
||||||
private TransactionAttribute(IsolationLevel? isolationLevel, Propagation propagation)
|
|
||||||
{
|
|
||||||
IsolationLevel = isolationLevel;
|
|
||||||
Propagation = propagation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 事务隔离级别
|
|
||||||
/// </summary>
|
|
||||||
public IsolationLevel? IsolationLevel { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 事务传播方式
|
|
||||||
/// </summary>
|
|
||||||
public Propagation Propagation { get; } = Propagation.Required;
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Host.BackgroundRunning;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 轮询工作接口
|
|
||||||
/// </summary>
|
|
||||||
public interface IPollingWork
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 启动工作
|
|
||||||
/// </summary>
|
|
||||||
ValueTask StartAsync(CancellationToken cancelToken);
|
|
||||||
}
|
|
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