Compare commits

...

39 Commits
v2.3.1 ... main

Author SHA1 Message Date
tk
220b19d152 refactor: ♻️ 框架代码同步 2025-04-16 16:00:58 +08:00
tk
7d0fcd4906 refactor: ♻️ 框架代码同步
[skip ci]
2025-04-16 15:54:10 +08:00
tk
9b6e053721 fix: 🐛 初次访问时前端js错误 2025-04-07 16:38:47 +08:00
snail1519
eef6661c92 fix: flowchart显示问题 2025-04-02 11:11:12 +08:00
tk
7a7bf0e578 build: 📦 build err 2025-03-26 15:49:32 +08:00
tk
d4956c94e0 chore: 🔨 界面优化
[skip ci]
2025-03-26 15:39:23 +08:00
tk
20f09c8ea1 build: 📦 dotnet sdk 升级至 9.0.202 2025-03-24 11:28:20 +08:00
tk
e0a4a40314 refactor: ♻️ 文件上传功能调整 2025-03-19 16:31:17 +08:00
tk
6fed7ec752 chore: 🔨 事件发布器接口通道数量
[skip ci]
2025-03-06 09:38:53 +08:00
tk
4afda0fbde perf: nuget update
[skip ci]
2025-02-27 14:32:16 +08:00
tk
a3b4608919 build: 📦 新的解决方案文件格式 slnx 支持来了 2025-02-19 10:54:46 +08:00
tk
9155db4d9d perf: package update
[skip ci]
2025-02-13 16:24:33 +08:00
tk
72cc3c42fd chore: 🔨 npm update 2025-01-14 15:31:33 +08:00
tk
f50dfc8f19 refactor: ♻️ 计划作业模块 2025-01-07 15:41:18 +08:00
tk
e82a172598 perf: 事件总线精简优化 2025-01-03 17:27:01 +08:00
tk
c9e570f11d perf: nuget update
[skip ci]
2025-01-03 09:04:35 +08:00
tk
278e10d8fc fix: 🐛 build error
BREAKING CHANGE: [skip ci]
2024-12-31 16:01:42 +08:00
tk
ddac448087 perf: 子模块更新 2024-12-31 15:56:55 +08:00
nsnail
a2de0bcbd1 chore: 🔨 补充语言文件 2024-12-27 22:14:06 +08:00
tk
13a4896828 perf: 子模块更新 2024-12-27 15:02:12 +08:00
tk
6580516e81 perf: nuget update 2024-12-27 11:35:32 +08:00
tk
d827d56e49 perf: nuget update 2024-12-26 18:59:16 +08:00
tk
b0a4f46af3 chore: 🔨 框架代码同步 2024-12-26 16:01:37 +08:00
tk
7b8f1b0fcd perf: nuget update 2024-12-24 18:12:26 +08:00
tk
52e7f93cc2 fix: 🐛 scTable dataChanged 2024-12-23 11:52:34 +08:00
tk
81ac00d1f1 style: 💄 code format 2024-12-23 11:16:11 +08:00
tk
9c81ce6f9f fix: 🐛 前端警告 2024-12-23 10:59:51 +08:00
tk
ac4bb50b66 fix: 🐛 档案管理空列表loading状态 2024-12-23 10:34:15 +08:00
tk
377c28c570 fix: 🐛 样式问题 2024-12-20 18:47:56 +08:00
tk
4d45a72243 chore: 🔨 表格行双击查看
[skip ci]
2024-12-20 10:35:11 +08:00
tk
f3651f1432 perf: 精简全局组件 2024-12-19 17:41:11 +08:00
tk
ce697588f5 refactor: ♻️ 异常请求输出追踪标识 2024-12-19 10:10:39 +08:00
nsnail
93fe9e41b7 docs: Update README.md
[skip ci]
2024-12-18 16:42:57 +08:00
nsnail
5815ca8594 doc: Update README.md
[skip ci]
2024-12-18 16:28:02 +08:00
nsnail
44e21423cc doc: Update README.md 2024-12-18 16:26:23 +08:00
tk
f7c91252cd chore: 🔨 用户列表左侧部门树形菜单 2024-12-18 15:24:47 +08:00
tk
ef17a8bd79 chore: 🔨 时间选择器调整
[skip ci]
2024-12-18 14:00:30 +08:00
tk
e5e1d6f50f refactor: ♻️ 框架代码同步 2024-12-16 11:40:11 +08:00
tk
7c47c09838 chore(release): 2.3.1 2024-12-13 16:15:52 +08:00
311 changed files with 2710 additions and 2608 deletions

View File

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
node-version: [ 22.x ] node-version: [ 23.x ]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:

View File

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
node-version: [ 22.x ] node-version: [ 23.x ]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:

View File

@ -2,6 +2,33 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [2.3.1](https://github.com/nsnail/NetAdmin/compare/v2.1.0...v2.3.1) (2024-12-13)
### Features
* ✨ 菜单复制 ([#214](https://github.com/nsnail/NetAdmin/issues/214)) ([81d9b0b](https://github.com/nsnail/NetAdmin/commit/81d9b0b3bb280661ceffa61aa6e9d612fb7ec52c))
* ✨ 分组统计功能 ([0b036e9](https://github.com/nsnail/NetAdmin/commit/0b036e9d67ffdf7a07c772606009f02744e6a3c3))
* ✨ 框架代码同步 ([098cfc1](https://github.com/nsnail/NetAdmin/commit/098cfc135e781a0cf172cd1289e5e871c7a76419))
* ✨ 框架代码同步 ([7256626](https://github.com/nsnail/NetAdmin/commit/725662693b7b47f6fae4c1917dd8d80220c7640a))
* ✨ 文档管理 ([#221](https://github.com/nsnail/NetAdmin/issues/221)) ([7ed3040](https://github.com/nsnail/NetAdmin/commit/7ed30406c9f721a12f0b756ec8884a1882242b93))
* ✨ select-filter badge icon ([#217](https://github.com/nsnail/NetAdmin/issues/217)) ([4d857f1](https://github.com/nsnail/NetAdmin/commit/4d857f1861b1256980e7cc59e2ab6a5f7d966da2))
### Bug Fixes
* 🐛 按钮文字提示 ([#227](https://github.com/nsnail/NetAdmin/issues/227)) ([c88c8d2](https://github.com/nsnail/NetAdmin/commit/c88c8d293d44f2707f3b5232e6a40a141af9981c))
* 🐛 导出界面报错 ([#213](https://github.com/nsnail/NetAdmin/issues/213)) ([ef2f0de](https://github.com/nsnail/NetAdmin/commit/ef2f0de095e314f34bec21c0a2ccdb51423a163b))
* 🐛 导出文件的responseType ([#205](https://github.com/nsnail/NetAdmin/issues/205)) ([841a419](https://github.com/nsnail/NetAdmin/commit/841a4195e77aa96e3c6c72626c1add3f71a310aa))
* 🐛 个性主题色冲突 ([4e4a1d0](https://github.com/nsnail/NetAdmin/commit/4e4a1d0dff7f3698e9a9cfcf46368260cfd70cbd))
* 🐛 请求日志批量插入,漏写了登录日志 ([#210](https://github.com/nsnail/NetAdmin/issues/210)) ([6c71c74](https://github.com/nsnail/NetAdmin/commit/6c71c74a27617c7d0530a5f6eaff650ecfd4eaec))
* 🐛 修复一些样式问题 ([442a69f](https://github.com/nsnail/NetAdmin/commit/442a69f90de179539f78c01d967572f83bd2eff8))
* 🐛 用户选择器报错 ([#220](https://github.com/nsnail/NetAdmin/issues/220)) ([71bfdaa](https://github.com/nsnail/NetAdmin/commit/71bfdaafa8176cf686b03244ee758de058080a71))
* 🐛 editUser ([ef2a0c3](https://github.com/nsnail/NetAdmin/commit/ef2a0c3280532ac24889279e4780a1b1a2561a6b))
* 🐛 idd ([#208](https://github.com/nsnail/NetAdmin/issues/208)) ([4e9f605](https://github.com/nsnail/NetAdmin/commit/4e9f605ea2cc6fe394068cfea5638e51920b9096))
* 🐛 version 条件重复指定 ([01058ba](https://github.com/nsnail/NetAdmin/commit/01058ba7288bcc645f66de2f78e1d659d55333cf))
* 🐛 version lock ([4eecc0b](https://github.com/nsnail/NetAdmin/commit/4eecc0b4ce09f620f83109949e4c2b67b7f8ba90))
## [2.3.0](https://github.com/nsnail/NetAdmin/compare/v2.1.0...v2.3.0) (2024-12-12) ## [2.3.0](https://github.com/nsnail/NetAdmin/compare/v2.1.0...v2.3.0) (2024-12-12)

View File

@ -4,7 +4,7 @@
<DefineConstants>DBTYPE_SQLITE</DefineConstants> <DefineConstants>DBTYPE_SQLITE</DefineConstants>
<SolutionDir>$(MSBuildThisFileDirectory)</SolutionDir> <SolutionDir>$(MSBuildThisFileDirectory)</SolutionDir>
</PropertyGroup> </PropertyGroup>
<Import Project="$(SolutionDir)/build/minver.targets" /> <Import Project="$(SolutionDir)/build/minver.targets"/>
<PropertyGroup> <PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Authors>nsnail</Authors> <Authors>nsnail</Authors>
@ -18,7 +18,7 @@
<LangVersion>preview</LangVersion> <LangVersion>preview</LangVersion>
<MinVerDefaultPreReleaseIdentifiers>beta</MinVerDefaultPreReleaseIdentifiers> <MinVerDefaultPreReleaseIdentifiers>beta</MinVerDefaultPreReleaseIdentifiers>
<MinVerTagPrefix>v</MinVerTagPrefix> <MinVerTagPrefix>v</MinVerTagPrefix>
<NoWarn>CA1707;IDE0005;IDE0008;IDE0010;IDE0028;IDE0055;IDE0160;IDE0300;IDE0305;RCS1141;RCS1142;RCS1181;S101;S1121;S1135;S125;S2094;S3604;S4663;S6561;SYSLIB1045;SA1010</NoWarn> <NoWarn>CA1707;IDE0005;IDE0008;IDE0010;IDE0028;IDE0055;IDE0072;IDE0160;IDE0300;IDE0305;RCS1141;RCS1142;RCS1181;S101;S1121;S1135;S125;S2094;S3604;S4663;S6561;SA1010;SYSLIB1045</NoWarn>
<Product>NetAdmin</Product> <Product>NetAdmin</Product>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/nsnail/NetAdmin.git</RepositoryUrl> <RepositoryUrl>https://github.com/nsnail/NetAdmin.git</RepositoryUrl>
@ -26,12 +26,12 @@
<Title>$(AssemblyName)</Title> <Title>$(AssemblyName)</Title>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MinVer" Version="6.0.0"> <PackageReference Include="MinVer" Version="6.1.0-beta.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="$(SolutionDir)/src/backend/GlobalUsings.cs" Link="GlobalUsings.cs" /> <Compile Include="$(SolutionDir)/src/backend/GlobalUsings.cs" Link="GlobalUsings.cs"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base FROM mcr.microsoft.com/dotnet/aspnet:9.0.4 AS base
WORKDIR /app WORKDIR /app
EXPOSE 8080 EXPOSE 8080
RUN apt update RUN apt update

View File

@ -1,249 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".drone", ".drone", "{3E408077-E73E-45CE-A53A-EF5F9DAE4B46}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{BB5BB244-E7D2-4368-8C18-C1C0ED1E12D1}"
ProjectSection(SolutionItems) = preProject
README.md = .drone/workflows/README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{1129FE25-466B-4F4F-85FC-3752664245E1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{3C6F049E-3EE8-4D66-9AFF-E8A369032487}"
ProjectSection(SolutionItems) = preProject
nightly-build.yml = .github/workflows/nightly-build.yml
README.md = .github/workflows/README.md
release.yml = .github/workflows/release.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{8E4C93BA-9493-4892-80C4-5E174C504829}"
ProjectSection(SolutionItems) = preProject
code.quality.props = build/code.quality.props
copy.pkg.xml.comment.files.targets = build/copy.pkg.xml.comment.files.targets
minver.targets = build/minver.targets
prebuild.targets = build/prebuild.targets
stylecop.analyzers.ruleset = build/stylecop.analyzers.ruleset
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{E80A1018-C354-4A26-9029-8847BB9DA864}"
ProjectSection(SolutionItems) = preProject
README.md = docker/README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{5198A03D-0CAC-4828-A807-34A693F73859}"
ProjectSection(SolutionItems) = preProject
.commitlintrc.js = .commitlintrc.js
.editorconfig = .editorconfig
.gitattributes = .gitattributes
.gitignore = .gitignore
.gitmodules = .gitmodules
CHANGELOG.md = CHANGELOG.md
Directory.Build.props = Directory.Build.props
Dockerfile = Dockerfile
dotnet-tools.json = dotnet-tools.json
global.json = global.json
LICENSE = LICENSE
NetAdmin.sln.DotSettings = NetAdmin.sln.DotSettings
nuget.config = nuget.config
package.json = package.json
README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{BB0B25C9-0901-4923-913F-00F9A6B352A5}"
ProjectSection(SolutionItems) = preProject
1.git.pull.request.ps1 = scripts/1.git.pull.request.ps1
2.git.release.ps1 = scripts/2.git.release.ps1
3.git.recreate.branch.ps1 = scripts/3.git.recreate.branch.ps1
4.git.del.obsolete.tags.ps1 = scripts/4.git.del.obsolete.tags.ps1
5.git.update.submodule.ps1 = scripts/5.git.update.submodule.ps1
clean.ln.csx = scripts/clean.ln.csx
code.clean.csx = scripts/code.clean.csx
code.clean.ps1 = scripts/code.clean.ps1
find.unused.ln.csx = scripts/find.unused.ln.csx
gen.cs.tt = scripts/gen.cs.tt
gen.id.linq = scripts/gen.id.linq
gen.ln.cmd = scripts/gen.ln.cmd
gen.resx.tt = scripts/gen.resx.tt
image.optimize.csx = scripts/image.optimize.csx
install.as.tpl.ps1 = scripts/install.as.tpl.ps1
rename.csx = scripts/rename.csx
resharper.full.ps1 = scripts/resharper.full.ps1
switch.nuget.or.project.csx = scripts/switch.nuget.or.project.csx
sync.sln.files.csx = scripts/sync.sln.files.csx
wait.server.stop.sh = scripts/wait.server.stop.sh
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C84EB5A0-37AD-4B17-A51E-E36888C4441E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "backend", "backend", "{4DAF9366-855F-46BB-AE4C-660C92FA0697}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Infrastructure", "src\backend\NetAdmin\NetAdmin.Infrastructure\NetAdmin.Infrastructure.csproj", "{1E62C322-EE42-4699-A6F1-791C53EFA62D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourSolution.AdmServer.Application", "src\backend\YourSolution.AdmServer.Application\YourSolution.AdmServer.Application.csproj", "{E38B2EB4-D7A5-4777-9236-3B348919DF23}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourSolution.AdmServer.Host", "src\backend\YourSolution.AdmServer.Host\YourSolution.AdmServer.Host.csproj", "{CE895E44-EEC3-4ECE-A56A-8A82E7D863E3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03.hosted-servers", "03.hosted-servers", "{12AE5B4B-CB1A-498E-83B8-04E201E31D86}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Domain", "src\backend\NetAdmin\NetAdmin.Domain\NetAdmin.Domain.csproj", "{58509C57-09FA-4E3C-BC07-78E786A2A326}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Application", "src\backend\NetAdmin\NetAdmin.Application\NetAdmin.Application.csproj", "{70C54E1B-2083-4196-AB68-34CAF0075D82}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Host", "src\backend\NetAdmin\NetAdmin.Host\NetAdmin.Host.csproj", "{91839A15-D08F-4848-A301-F793412BC688}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Cache", "src\backend\NetAdmin\NetAdmin.Cache\NetAdmin.Cache.csproj", "{91452C22-4B57-4F16-9AF6-42C7BF830504}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourSolution.AdmServer.Cache", "src\backend\YourSolution.AdmServer.Cache\YourSolution.AdmServer.Cache.csproj", "{7CB632D3-3635-4F8D-AFE7-F496D37D422B}"
EndProject
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
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
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
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02.components", "02.components", "{3F23258D-8299-4992-9F51-2EE9B52CF9D2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01.frameworks", "01.frameworks", "{D9C3EF66-2757-473D-A26B-54FD08DA203F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "04.tests", "04.tests", "{89260294-80FC-49F1-8D73-AECD39AFF2B7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "05.tools", "05.tools", "{79409163-5006-405D-AC96-406FA0AD77B7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "src\backend\UnitTests\UnitTests.csproj", "{C7F27698-DA05-4ACD-B0D7-4791B3972002}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetAdmin.Tests", "src\backend\NetAdmin\NetAdmin.Tests\NetAdmin.Tests.csproj", "{00604162-C444-478B-B773-3AB23C856CA7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourSolution.AdmServer.Domain", "src\backend\YourSolution.AdmServer.Domain\YourSolution.AdmServer.Domain.csproj", "{932520DF-D312-415A-A128-1117F8221D68}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourSolution.AdmServer.Infrastructure", "src\backend\YourSolution.AdmServer.Infrastructure\YourSolution.AdmServer.Infrastructure.csproj", "{C3DE6F6A-D1FC-4B8E-9033-980FBEBBD2BA}"
EndProject
##Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gurion", "refs\Gurion\src\Gurion\Gurion.csproj", "{CCD098FE-4F95-4FA4-8CC0-9A6DE921FBAE}"#refs
##EndProject#refs
##Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql", "refs\NetAdmin.FreeSql\src\FreeSql\FreeSql.csproj", "{3C65DA42-877D-46FF-B754-C12214302A29}"#refs
##EndProject#refs
##Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql.Provider.Sqlite", "refs\NetAdmin.FreeSql\src\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj", "{CF5EFA63-4631-4A64-B4F3-98A7DD532F68}"#refs
##EndProject#refs
##Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql.DbContext", "refs\NetAdmin.FreeSql\src\FreeSql.DbContext\FreeSql.DbContext.csproj", "{FE03DF27-EC56-48DB-81B0-F99947259A7C}"#refs
##EndProject#refs
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1E62C322-EE42-4699-A6F1-791C53EFA62D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E62C322-EE42-4699-A6F1-791C53EFA62D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E62C322-EE42-4699-A6F1-791C53EFA62D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E62C322-EE42-4699-A6F1-791C53EFA62D}.Release|Any CPU.Build.0 = Release|Any CPU
{E38B2EB4-D7A5-4777-9236-3B348919DF23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E38B2EB4-D7A5-4777-9236-3B348919DF23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E38B2EB4-D7A5-4777-9236-3B348919DF23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E38B2EB4-D7A5-4777-9236-3B348919DF23}.Release|Any CPU.Build.0 = Release|Any CPU
{CE895E44-EEC3-4ECE-A56A-8A82E7D863E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CE895E44-EEC3-4ECE-A56A-8A82E7D863E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CE895E44-EEC3-4ECE-A56A-8A82E7D863E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CE895E44-EEC3-4ECE-A56A-8A82E7D863E3}.Release|Any CPU.Build.0 = Release|Any CPU
{58509C57-09FA-4E3C-BC07-78E786A2A326}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58509C57-09FA-4E3C-BC07-78E786A2A326}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58509C57-09FA-4E3C-BC07-78E786A2A326}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58509C57-09FA-4E3C-BC07-78E786A2A326}.Release|Any CPU.Build.0 = Release|Any CPU
{70C54E1B-2083-4196-AB68-34CAF0075D82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70C54E1B-2083-4196-AB68-34CAF0075D82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70C54E1B-2083-4196-AB68-34CAF0075D82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70C54E1B-2083-4196-AB68-34CAF0075D82}.Release|Any CPU.Build.0 = Release|Any CPU
{91839A15-D08F-4848-A301-F793412BC688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{91839A15-D08F-4848-A301-F793412BC688}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91839A15-D08F-4848-A301-F793412BC688}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91839A15-D08F-4848-A301-F793412BC688}.Release|Any CPU.Build.0 = Release|Any CPU
{91452C22-4B57-4F16-9AF6-42C7BF830504}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{91452C22-4B57-4F16-9AF6-42C7BF830504}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91452C22-4B57-4F16-9AF6-42C7BF830504}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91452C22-4B57-4F16-9AF6-42C7BF830504}.Release|Any CPU.Build.0 = Release|Any CPU
{7CB632D3-3635-4F8D-AFE7-F496D37D422B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CB632D3-3635-4F8D-AFE7-F496D37D422B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CB632D3-3635-4F8D-AFE7-F496D37D422B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CB632D3-3635-4F8D-AFE7-F496D37D422B}.Release|Any CPU.Build.0 = Release|Any CPU
{C2CC1596-3BEE-43EA-A9BE-4EDE5716296C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2CC1596-3BEE-43EA-A9BE-4EDE5716296C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2CC1596-3BEE-43EA-A9BE-4EDE5716296C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2CC1596-3BEE-43EA-A9BE-4EDE5716296C}.Release|Any CPU.Build.0 = Release|Any CPU
{19872A4C-3C9A-4C62-A33B-74F5B8D6F77C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19872A4C-3C9A-4C62-A33B-74F5B8D6F77C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19872A4C-3C9A-4C62-A33B-74F5B8D6F77C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19872A4C-3C9A-4C62-A33B-74F5B8D6F77C}.Release|Any CPU.Build.0 = Release|Any CPU
{34650E82-D257-46DA-BD6B-DE307113347B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{34650E82-D257-46DA-BD6B-DE307113347B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{34650E82-D257-46DA-BD6B-DE307113347B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{34650E82-D257-46DA-BD6B-DE307113347B}.Release|Any CPU.Build.0 = Release|Any CPU
{C7F27698-DA05-4ACD-B0D7-4791B3972002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C7F27698-DA05-4ACD-B0D7-4791B3972002}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C7F27698-DA05-4ACD-B0D7-4791B3972002}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C7F27698-DA05-4ACD-B0D7-4791B3972002}.Release|Any CPU.Build.0 = Release|Any CPU
{00604162-C444-478B-B773-3AB23C856CA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{00604162-C444-478B-B773-3AB23C856CA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00604162-C444-478B-B773-3AB23C856CA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00604162-C444-478B-B773-3AB23C856CA7}.Release|Any CPU.Build.0 = Release|Any CPU
{932520DF-D312-415A-A128-1117F8221D68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{932520DF-D312-415A-A128-1117F8221D68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{932520DF-D312-415A-A128-1117F8221D68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{932520DF-D312-415A-A128-1117F8221D68}.Release|Any CPU.Build.0 = Release|Any CPU
{C3DE6F6A-D1FC-4B8E-9033-980FBEBBD2BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3DE6F6A-D1FC-4B8E-9033-980FBEBBD2BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3DE6F6A-D1FC-4B8E-9033-980FBEBBD2BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3DE6F6A-D1FC-4B8E-9033-980FBEBBD2BA}.Release|Any CPU.Build.0 = Release|Any CPU
##{CCD098FE-4F95-4FA4-8CC0-9A6DE921FBAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
##{CCD098FE-4F95-4FA4-8CC0-9A6DE921FBAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
##{CCD098FE-4F95-4FA4-8CC0-9A6DE921FBAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
##{CCD098FE-4F95-4FA4-8CC0-9A6DE921FBAE}.Release|Any CPU.Build.0 = Release|Any CPU
##{3C65DA42-877D-46FF-B754-C12214302A29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
##{3C65DA42-877D-46FF-B754-C12214302A29}.Debug|Any CPU.Build.0 = Debug|Any CPU
##{3C65DA42-877D-46FF-B754-C12214302A29}.Release|Any CPU.ActiveCfg = Release|Any CPU
##{3C65DA42-877D-46FF-B754-C12214302A29}.Release|Any CPU.Build.0 = Release|Any CPU
##{CF5EFA63-4631-4A64-B4F3-98A7DD532F68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
##{CF5EFA63-4631-4A64-B4F3-98A7DD532F68}.Debug|Any CPU.Build.0 = Debug|Any CPU
##{CF5EFA63-4631-4A64-B4F3-98A7DD532F68}.Release|Any CPU.ActiveCfg = Release|Any CPU
##{CF5EFA63-4631-4A64-B4F3-98A7DD532F68}.Release|Any CPU.Build.0 = Release|Any CPU
##{FE03DF27-EC56-48DB-81B0-F99947259A7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
##{FE03DF27-EC56-48DB-81B0-F99947259A7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
##{FE03DF27-EC56-48DB-81B0-F99947259A7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
##{FE03DF27-EC56-48DB-81B0-F99947259A7C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4DAF9366-855F-46BB-AE4C-660C92FA0697} = {C84EB5A0-37AD-4B17-A51E-E36888C4441E}
{12AE5B4B-CB1A-498E-83B8-04E201E31D86} = {4DAF9366-855F-46BB-AE4C-660C92FA0697}
{3F23258D-8299-4992-9F51-2EE9B52CF9D2} = {4DAF9366-855F-46BB-AE4C-660C92FA0697}
{D9C3EF66-2757-473D-A26B-54FD08DA203F} = {4DAF9366-855F-46BB-AE4C-660C92FA0697}
{70C54E1B-2083-4196-AB68-34CAF0075D82} = {D9C3EF66-2757-473D-A26B-54FD08DA203F}
{91452C22-4B57-4F16-9AF6-42C7BF830504} = {D9C3EF66-2757-473D-A26B-54FD08DA203F}
{58509C57-09FA-4E3C-BC07-78E786A2A326} = {D9C3EF66-2757-473D-A26B-54FD08DA203F}
{91839A15-D08F-4848-A301-F793412BC688} = {D9C3EF66-2757-473D-A26B-54FD08DA203F}
{1E62C322-EE42-4699-A6F1-791C53EFA62D} = {D9C3EF66-2757-473D-A26B-54FD08DA203F}
{E38B2EB4-D7A5-4777-9236-3B348919DF23} = {12AE5B4B-CB1A-498E-83B8-04E201E31D86}
{7CB632D3-3635-4F8D-AFE7-F496D37D422B} = {12AE5B4B-CB1A-498E-83B8-04E201E31D86}
{CE895E44-EEC3-4ECE-A56A-8A82E7D863E3} = {12AE5B4B-CB1A-498E-83B8-04E201E31D86}
{89260294-80FC-49F1-8D73-AECD39AFF2B7} = {4DAF9366-855F-46BB-AE4C-660C92FA0697}
{C7F27698-DA05-4ACD-B0D7-4791B3972002} = {89260294-80FC-49F1-8D73-AECD39AFF2B7}
{00604162-C444-478B-B773-3AB23C856CA7} = {D9C3EF66-2757-473D-A26B-54FD08DA203F}
{34650E82-D257-46DA-BD6B-DE307113347B} = {3F23258D-8299-4992-9F51-2EE9B52CF9D2}
{19872A4C-3C9A-4C62-A33B-74F5B8D6F77C} = {3F23258D-8299-4992-9F51-2EE9B52CF9D2}
{C2CC1596-3BEE-43EA-A9BE-4EDE5716296C} = {3F23258D-8299-4992-9F51-2EE9B52CF9D2}
{79409163-5006-405D-AC96-406FA0AD77B7} = {4DAF9366-855F-46BB-AE4C-660C92FA0697}
{932520DF-D312-415A-A128-1117F8221D68} = {12AE5B4B-CB1A-498E-83B8-04E201E31D86}
{C3DE6F6A-D1FC-4B8E-9033-980FBEBBD2BA} = {12AE5B4B-CB1A-498E-83B8-04E201E31D86}
{3C6F049E-3EE8-4D66-9AFF-E8A369032487} = {1129FE25-466B-4F4F-85FC-3752664245E1}
{BB5BB244-E7D2-4368-8C18-C1C0ED1E12D1} = {3E408077-E73E-45CE-A53A-EF5F9DAE4B46}
EndGlobalSection
EndGlobal

93
NetAdmin.slnx Normal file
View File

@ -0,0 +1,93 @@
<Solution>
<Folder Name="/.drone/"/>
<Folder Name="/.drone/workflows/">
<File Path=".drone/workflows/README.md"/>
</Folder>
<Folder Name="/.github/"/>
<Folder Name="/.github/workflows/">
<File Path=".github/workflows/nightly-build.yml"/>
<File Path=".github/workflows/README.md"/>
<File Path=".github/workflows/release.yml"/>
</Folder>
<Folder Name="/build/">
<File Path="build/code.quality.props"/>
<File Path="build/copy.pkg.xml.comment.files.targets"/>
<File Path="build/minver.targets"/>
<File Path="build/prebuild.targets"/>
<File Path="build/stylecop.analyzers.ruleset"/>
</Folder>
<Folder Name="/docker/">
<File Path="docker/README.md"/>
</Folder>
<Folder Name="/meta/">
<File Path=".commitlintrc.js"/>
<File Path=".editorconfig"/>
<File Path=".gitattributes"/>
<File Path=".gitignore"/>
<File Path=".gitmodules"/>
<File Path="CHANGELOG.md"/>
<File Path="Directory.Build.props"/>
<File Path="Dockerfile"/>
<File Path="dotnet-tools.json"/>
<File Path="global.json"/>
<File Path="LICENSE"/>
<File Path="NetAdmin.slnx.DotSettings"/>
<File Path="nuget.config"/>
<File Path="package.json"/>
<File Path="README.md"/>
</Folder>
<Folder Name="/scripts/">
<File Path="scripts/1.git.pull.request.ps1"/>
<File Path="scripts/2.git.release.ps1"/>
<File Path="scripts/3.git.recreate.branch.ps1"/>
<File Path="scripts/4.git.del.obsolete.tags.ps1"/>
<File Path="scripts/5.git.update.submodule.ps1"/>
<File Path="scripts/clean.ln.csx"/>
<File Path="scripts/code.clean.csx"/>
<File Path="scripts/code.clean.ps1"/>
<File Path="scripts/find.unused.ln.csx"/>
<File Path="scripts/gen.cs.tt"/>
<File Path="scripts/gen.id.linq"/>
<File Path="scripts/gen.ln.cmd"/>
<File Path="scripts/gen.resx.tt"/>
<File Path="scripts/git.config.cmd"/>
<File Path="scripts/image.optimize.csx"/>
<File Path="scripts/install.as.tpl.ps1"/>
<File Path="scripts/rename.csx"/>
<File Path="scripts/resharper.full.ps1"/>
<File Path="scripts/switch.nuget.or.project.csx"/>
<File Path="scripts/sync.slnx.files.csx"/>
<File Path="scripts/wait.server.stop.sh"/>
</Folder>
<Folder Name="/src/"/>
<Folder Name="/src/backend/"/>
<Folder Name="/src/backend/01.frameworks/">
<!--<Project Type="Refs" Path="refs/Gurion/src/Gurion/Gurion.csproj"/>-->
<!--<Project Type="Refs" Path="refs/NetAdmin.FreeSql/src/FreeSql.DbContext/FreeSql.DbContext.csproj"/>-->
<!--<Project Type="Refs" Path="refs/NetAdmin.FreeSql/src/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj"/>-->
<!--<Project Type="Refs" Path="refs/NetAdmin.FreeSql/src/FreeSql/FreeSql.csproj"/>-->
<Project Path="src/backend/NetAdmin/NetAdmin.Application/NetAdmin.Application.csproj"/>
<Project Path="src/backend/NetAdmin/NetAdmin.Cache/NetAdmin.Cache.csproj"/>
<Project Path="src/backend/NetAdmin/NetAdmin.Domain/NetAdmin.Domain.csproj"/>
<Project Path="src/backend/NetAdmin/NetAdmin.Host/NetAdmin.Host.csproj"/>
<Project Path="src/backend/NetAdmin/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj"/>
<Project Path="src/backend/NetAdmin/NetAdmin.Tests/NetAdmin.Tests.csproj"/>
</Folder>
<Folder Name="/src/backend/02.components/">
<Project Path="src/backend/NetAdmin/NetAdmin.SysComponent.Application/NetAdmin.SysComponent.Application.csproj"/>
<Project Path="src/backend/NetAdmin/NetAdmin.SysComponent.Cache/NetAdmin.SysComponent.Cache.csproj"/>
<Project Path="src/backend/NetAdmin/NetAdmin.SysComponent.Host/NetAdmin.SysComponent.Host.csproj"/>
</Folder>
<Folder Name="/src/backend/03.hosted-servers/">
<Project Path="src/backend/YourSolution.AdmServer.Application/YourSolution.AdmServer.Application.csproj"/>
<Project Path="src/backend/YourSolution.AdmServer.Cache/YourSolution.AdmServer.Cache.csproj"/>
<Project Path="src/backend/YourSolution.AdmServer.Domain/YourSolution.AdmServer.Domain.csproj"/>
<Project Path="src/backend/YourSolution.AdmServer.Host/YourSolution.AdmServer.Host.csproj"/>
<Project Path="src/backend/YourSolution.AdmServer.Infrastructure/YourSolution.AdmServer.Infrastructure.csproj"/>
</Folder>
<Folder Name="/src/backend/04.tests/">
<Project Path="src/backend/UnitTests/UnitTests.csproj"/>
</Folder>
<Folder Name="/src/backend/05.tools/">
</Folder>
</Solution>

View File

@ -12,6 +12,7 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantPatternParentheses/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantPatternParentheses/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestBaseTypeForParameter/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestBaseTypeForParameter/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestBaseTypeForParameterInConstructor/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestBaseTypeForParameterInConstructor/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TooWideLocalVariableScope/@EntryIndexedValue">HINT</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TooWideLocalVariableScope/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
@ -325,6 +326,7 @@
&lt;/Patterns&gt;</s:String> &lt;/Patterns&gt;</s:String>
<!-- Environment--> <!-- Environment-->
<s:Boolean x:Key="/Default/Environment/Editor/UseCamelHumps/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>

View File

@ -14,22 +14,23 @@ https://na.tools92.top
```shell ```shell
docker run -p 8080:8080 nsnail/netadmin docker run -p 8080:8080 nsnail/netadmin
# 需魔法上网 # 墙内用户请自备梯子
``` ```
## 构建步骤 ## 构建步骤
所涉软件均推荐下载zip/tar版本解压即用一键删除不会污染系统环境
```shell ```shell
# 1. 检查 dotnet sdk 版本 >=9.0.0 # 1. 检查 dotnet sdk 版本 >=9.0.0
dotnet --list-sdks dotnet --list-sdks
# 下载 dotnethttps://dotnet.microsoft.com/zh-cn/download/dotnet # 下载 dotnethttps://dotnet.microsoft.com/zh-cn/download/dotnet
# 2. 克隆代码仓库 # 2. 克隆代码仓库
git clone https://github.com/nsnail/NetAdmin.git && cd ./NetAdmin git clone --depth 1 https://github.com/nsnail/NetAdmin.git && cd ./NetAdmin
# 3. 确认本机 redis 处于运行状态 # 3. 确认本机 redis 处于运行状态
redis-server # 启动服务器 redis-server # 启动服务器
redis-cli # 连接测试 redis-cli ping # 连接测试
# 下载 redis for windowshttps://github.com/redis-windows/redis-windows/releases # 下载 redis for windowshttps://github.com/redis-windows/redis-windows/releases
# 下载 redis for linux/machttps://redis.io/download # 下载 redis for linux/machttps://redis.io/download
@ -40,7 +41,7 @@ dotnet run --project ./src/backend/YourSolution.AdmServer.Host/YourSolution.AdmS
# 5. 检查 nodejs 版本 >=20 # 5. 检查 nodejs 版本 >=20
node -v node -v
# 下载 nodejshttps://nodejs.org/en/download # 下载 nodejshttps://nodejs.org/zh-cn/download
# 6. 安装 npm 依赖包 # 6. 安装 npm 依赖包
cd ./src/frontend/admin && npm install cd ./src/frontend/admin && npm install
@ -69,19 +70,19 @@ npm run dev
```mermaid ```mermaid
flowchart TD flowchart TD
sys-host["NetAdmin.SysComponent.Host\n系统组件:主机层"] sys-host["NetAdmin.SysComponent.Host<br>系统组件:主机层"]
sys-cache["NetAdmin.SysComponent.Cache\n系统组件:缓存层"] sys-cache["NetAdmin.SysComponent.Cache<br>系统组件:缓存层"]
sys-app["NetAdmin.SysComponent.Application\n系统组件:应用层"] sys-app["NetAdmin.SysComponent.Application<br>系统组件:应用层"]
host["<b>NetAdmin.Host</b>\n框架主机层\n.Net自托管主机程序\n输入输出格式化\n数据校验、鉴权\n...所有HTTP管道过滤器中间件"] host["<b>NetAdmin.Host</b><br>框架:主机层<br>.Net自托管主机程序<br>(输入输出格式化)<br>(数据校验、鉴权)<br>...所有HTTP管道过滤器中间件"]
cache["<b>NetAdmin.Cache</b>\n框架缓存层\n基于Redis或MemoryCache的缓存策略实现"] cache["<b>NetAdmin.Cache</b><br>框架:缓存层<br>基于Redis或MemoryCache的缓存策略实现"]
app["<b>NetAdmin.Application</b>\n框架业务应用层\n内部服务增删改查\n外部服务增删改查\n...所有业务用例的计算与组合逻辑的模块化)"] app["<b>NetAdmin.Application</b><br>框架:业务应用层<br>(内部服务增删改查)<br>(外部服务增删改查)<br>...所有业务用例的计算与组合逻辑的模块化)"]
domain["<b>NetAdmin.Domain</b>\n框架数据实体层\n数据库关系实体映射\nDTO数据传输对象\n...所有数据模型的抽象与封装)"] domain["<b>NetAdmin.Domain</b><br>框架:数据实体层<br>(数据库关系实体映射)<br>DTO数据传输对象<br>...所有数据模型的抽象与封装)"]
infra["<b>NetAdmin.Infrastructure</b>\n框架基础设施层\n第三方组件和Nuget包引用\n公共构建和程序运行配置\n公共常量枚举异常定义\n全球化化和多语言\n...所有公共Utility工具"] infra["<b>NetAdmin.Infrastructure</b><br>框架:基础设施层<br>第三方组件和Nuget包引用<br>(公共构建和程序运行配置)<br>(公共常量枚举异常定义)<br>(全球化化和多语言)<br>...所有公共Utility工具"]
biz-host["YourSolution.XXX.Host\n业务实例:主机层"] biz-host["YourSolution.XXX.Host<br>业务实例:主机层"]
biz-cache["YourSolution.XXX.Cache\n业务实例:缓存层"] biz-cache["YourSolution.XXX.Cache<br>业务实例:缓存层"]
biz-app["YourSolution.XXX.Application\n业务实例:应用层"] biz-app["YourSolution.XXX.Application<br>业务实例:应用层"]
biz-domain["YourSolution.XXX.Domain\n业务实例:数据实体层"] biz-domain["YourSolution.XXX.Domain<br>业务实例:数据实体层"]
biz-infra["YourSolution.XXX.Infrastructure\n业务实例:基础设施层"] biz-infra["YourSolution.XXX.Infrastructure<br>业务实例:基础设施层"]
biz-host-->biz-cache-->biz-app-->biz-domain-->biz-infra biz-host-->biz-cache-->biz-app-->biz-domain-->biz-infra
sys-host-->sys-cache-->sys-app-->domain-->infra sys-host-->sys-cache-->sys-app-->domain-->infra
host-->cache-->app-->domain-->infra host-->cache-->app-->domain-->infra

View File

@ -128,8 +128,8 @@
请求方式 请求方式
请求日志导出 请求日志导出
调试 调试
踪标识 踪标识
身份证 身份证
运行 运行
通知 通知

View File

@ -42,5 +42,21 @@
{ {
"ApiId": "api/sys/user/set.session.user.app.config", "ApiId": "api/sys/user/set.session.user.app.config",
"RoleId": 371729946431493, "RoleId": 371729946431493,
},
{
"ApiId": "api/sys/login.log/paged.query",
"RoleId": 371729946431493,
},
{
"ApiId": "api/sys/login.log/get",
"RoleId": 371729946431493,
},
{
"ApiId": "api/sys/login.log/count.by",
"RoleId": 371729946431493,
},
{
"ApiId": "api/sys/login.log/export",
"RoleId": 371729946431493,
} }
] ]

View File

@ -15,15 +15,15 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.12.19"> <PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.2-alpha">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="4.12.9"> <PackageReference Include="Roslynator.Analyzers" Version="4.13.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.3.0.106239"> <PackageReference Include="SonarAnalyzer.CSharp" Version="10.8.0.113526">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>

View File

@ -1,9 +1,9 @@
{ {
"version": "2.3.0", "version": "2.3.1",
"devDependencies": { "devDependencies": {
"cz-git": "^1.11.0", "cz-git": "^1.11.1",
"commitizen": "^4.3.1", "commitizen": "^4.3.1",
"prettier": "^3.4.2", "prettier": "^3.5.3",
"standard-version": "^9.5.0" "standard-version": "^9.5.0"
}, },
"config": { "config": {

@ -1 +1 @@
Subproject commit 89586fd0c666cb907cb24690498c3211e578483f Subproject commit b16b1a35559281a9f53d6914f1195a204c9b4185

@ -1 +1 @@
Subproject commit c851ae3da25abd26364b0965d6d6affc76abee9f Subproject commit 15717df4499d284ec77c624a281c199a29280a4e

@ -1 +1 @@
Subproject commit 890b229683208dd42db2d34cd29f0349e6c913cc Subproject commit 322cbc32df1363755d4b0588923ee7324676c3b6

View File

@ -1,3 +1,5 @@
#!/usr/bin/env pwsh
$branch = $( git branch --show-current ) $branch = $( git branch --show-current )
git add ../ git add ../
$skipFormat = Read-Host "输入 n 跳过代码整理" $skipFormat = Read-Host "输入 n 跳过代码整理"

View File

@ -1,3 +1,5 @@
#!/usr/bin/env pwsh
cd .. cd ..
$types = @{ $types = @{
'1' = @('major', '主版本') '1' = @('major', '主版本')

View File

@ -1,3 +1,5 @@
#!/usr/bin/env pwsh
$branch = $( git branch --show-current ) $branch = $( git branch --show-current )
git checkout main git checkout main
git pull git pull

View File

@ -1,2 +1,4 @@
#!/usr/bin/env pwsh
git push origin :refs/tags/$(git tag -l "*-*") git push origin :refs/tags/$(git tag -l "*-*")
git tag -d $(git tag -l "*-*") git tag -d $(git tag -l "*-*")

View File

@ -1,3 +1,5 @@
#!/usr/bin/env pwsh
git submodule update --progress --init --recursive --force --remote -- "../refs/Gurion" git submodule update --progress --init --recursive --force --remote -- "../refs/Gurion"
git submodule update --progress --init --recursive --force --remote -- "../refs/NetAdmin.FreeSql" git submodule update --progress --init --recursive --force --remote -- "../refs/NetAdmin.FreeSql"
git submodule update --progress --init --recursive --force --remote -- "../refs/ns-ext" git submodule update --progress --init --recursive --force --remote -- "../refs/ns-ext"

View File

@ -18,7 +18,7 @@ using System.Net.Http.Json;
{ {
CreateNoWindow = true, CreateNoWindow = true,
FileName = "dotnet", FileName = "dotnet",
Arguments = $"jb cleanupcode --include=\"{files}\" --no-build ../NetAdmin.sln", Arguments = $"jb cleanupcode --include=\"{files}\" --no-build ../NetAdmin.slnx",
UseShellExecute = false, UseShellExecute = false,
RedirectStandardOutput = true RedirectStandardOutput = true
} }

View File

@ -1,5 +1,7 @@
#!/usr/bin/env pwsh
npm --prefix ../src/frontend/admin run prettier npm --prefix ../src/frontend/admin run prettier
jb cleanupcode --no-build --include=$($(git status --porcelain | Where-Object { $_ -match "^\s*[MA]" } | ForEach-Object { $_.TrimStart(" M").TrimStart(" A") }) -join ";") ../NetAdmin.sln jb cleanupcode --no-build --include=$( $( git status --porcelain | Where-Object { $_ -match "^\s*[MA]" } | ForEach-Object { $_.TrimStart(" M").TrimStart(" A") } ) -join ";" ) ../NetAdmin.slnx
dot rbom -w -e refs -e .git -e node_modules ../ dot rbom -w -e refs -e .git -e node_modules ../
dot trim -w -e refs -e .git -e node_modules ../ dot trim -w -e refs -e .git -e node_modules ../
dot tolf -w -e refs -e .git -e node_modules ../ dot tolf -w -e refs -e .git -e node_modules ../

View File

@ -1,2 +1,4 @@
#!/usr/bin/env pwsh
dotnet new uninstall ../ dotnet new uninstall ../
dotnet new --install ../ dotnet new --install ../

View File

@ -1,4 +1,4 @@
#r "nuget: NSExt, 2.3.2" #r "nuget: NSExt, 2.3.5"
using NSExt.Extensions; using NSExt.Extensions;
Console.WriteLine("请输入原始名称NetAdmin"); Console.WriteLine("请输入原始名称NetAdmin");

View File

@ -1 +1,3 @@
jb cleanupcode --no-build ../NetAdmin.sln #!/usr/bin/env pwsh
jb cleanupcode --no-build ../NetAdmin.slnx

View File

@ -5,18 +5,13 @@ while (!new[] { "1", "2" }.Contains(input))
Console.WriteLine("1.nuget 2.project"); Console.WriteLine("1.nuget 2.project");
input = Console.ReadLine(); input = Console.ReadLine();
} }
var slnFile = Directory.GetFiles(@"../", "*.sln").First(); var slnxFile = Directory.GetFiles(@"../", "*.slnx").First();
var csprojFiles = Directory.GetFiles(@"../src", "*.csproj", new EnumerationOptions { RecurseSubdirectories = true }); var csprojFiles = Directory.GetFiles(@"../src", "*.csproj", new EnumerationOptions { RecurseSubdirectories = true });
var slnContent = File.ReadAllText(slnFile); var slnContent = File.ReadAllText(slnxFile);
if (input == "1") if (input == "1")
{ {
slnContent = Regex.Replace(slnContent, "\\nProject\\((.*)#refs", "\n##Project($1#refs"); slnContent = Regex.Replace(slnContent, "<Project Type=\"Refs\"(.*)>", "<!--<Project Type=\"Refs\"$1>-->");
slnContent = Regex.Replace(slnContent, "\\nEndProject#refs", "\n##EndProject#refs");
foreach (Match m in Regex.Matches(slnContent, "\"(\\{[A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12}\\})\"#refs"))
{
slnContent = slnContent.Replace($" {m.Groups[1].Value}.", $" ##{m.Groups[1].Value}.");
}
foreach (var csprojFile in csprojFiles) foreach (var csprojFile in csprojFiles)
{ {
var csprojContent = File.ReadAllText(csprojFile); var csprojContent = File.ReadAllText(csprojFile);
@ -27,7 +22,7 @@ if (input == "1")
} }
else else
{ {
slnContent = Regex.Replace(slnContent, "##", ""); slnContent = Regex.Replace(slnContent, "<!--(.*)-->", "$1");
foreach (var csprojFile in csprojFiles) foreach (var csprojFile in csprojFiles)
{ {
var csprojContent = File.ReadAllText(csprojFile); var csprojContent = File.ReadAllText(csprojFile);
@ -39,4 +34,4 @@ else
Console.WriteLine(slnContent); Console.WriteLine(slnContent);
File.WriteAllText(slnFile, slnContent); File.WriteAllText(slnxFile, slnContent);

View File

@ -1,91 +0,0 @@
using System.Text.RegularExpressions;
var slnFile = Directory.GetFiles(@"../", "*.sln").First();
var content = File.ReadAllText(slnFile);
content = Regex.Replace(
content,
"Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"meta\", \"meta\", \"{5198A03D-0CAC-4828-A807-34A693F73859}\"(?:.|\n)*?EndProject",
$$"""
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{5198A03D-0CAC-4828-A807-34A693F73859}"
ProjectSection(SolutionItems) = preProject
{{string.Join('\n',
Directory.GetFiles(@"../", "*").Where(x => !x.EndsWith(".sln") && !x.EndsWith(".user"))
.Select(x=>$" {Path.GetFileName(x)} = {Path.GetFileName(x)}")
)}}
EndProject
"""
);
content = Regex.Replace(
content,
"Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"docker\", \"docker\", \"{E80A1018-C354-4A26-9029-8847BB9DA864}\"(?:.|\n)*?EndProject",
$$"""
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{E80A1018-C354-4A26-9029-8847BB9DA864}"
ProjectSection(SolutionItems) = preProject
{{string.Join('\n',
Directory.GetFiles(@"../docker", "*")
.Select(x=>$" {Path.GetFileName(x)} = docker/{Path.GetFileName(x)}")
)}}
EndProject
"""
);
content = Regex.Replace(
content,
"Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"workflows\", \"workflows\", \"{3C6F049E-3EE8-4D66-9AFF-E8A369032487}\"(?:.|\n)*?EndProject",
$$"""
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{3C6F049E-3EE8-4D66-9AFF-E8A369032487}"
ProjectSection(SolutionItems) = preProject
{{string.Join('\n',
Directory.GetFiles(@"../.github/workflows", "*")
.Select(x=>$" {Path.GetFileName(x)} = .github/workflows/{Path.GetFileName(x)}")
)}}
EndProject
"""
);
content = Regex.Replace(
content,
"Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"workflows\", \"workflows\", \"{BB5BB244-E7D2-4368-8C18-C1C0ED1E12D1}\"(?:.|\n)*?EndProject",
$$"""
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{BB5BB244-E7D2-4368-8C18-C1C0ED1E12D1}"
ProjectSection(SolutionItems) = preProject
{{string.Join('\n',
Directory.GetFiles(@"../.drone/workflows", "*")
.Select(x=>$" {Path.GetFileName(x)} = .drone/workflows/{Path.GetFileName(x)}")
)}}
EndProject
"""
);
content = Regex.Replace(
content,
"Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"scripts\", \"scripts\", \"{BB0B25C9-0901-4923-913F-00F9A6B352A5}\"(?:.|\n)*?EndProject",
$$"""
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{BB0B25C9-0901-4923-913F-00F9A6B352A5}"
ProjectSection(SolutionItems) = preProject
{{string.Join('\n',
Directory.GetFiles(@"../scripts", "*")
.Select(x=>$" {Path.GetFileName(x)} = scripts/{Path.GetFileName(x)}")
)}}
EndProject
"""
);
content = Regex.Replace(
content,
"Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"build\", \"build\", \"{8E4C93BA-9493-4892-80C4-5E174C504829}\"(?:.|\n)*?EndProject",
$$"""
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{8E4C93BA-9493-4892-80C4-5E174C504829}"
ProjectSection(SolutionItems) = preProject
{{string.Join('\n',
Directory.GetFiles(@"../build", "*")
.Select(x=>$" {Path.GetFileName(x)} = build/{Path.GetFileName(x)}")
)}}
EndProject
"""
);
Console.WriteLine(content);
File.WriteAllText(slnFile, content);

View File

@ -0,0 +1,87 @@
using System.Text.RegularExpressions;
var slnxFile = Directory.GetFiles(@"../", "*.slnx").First();
var content = File.ReadAllText(slnxFile);
content = Regex.Replace(
content,
"<Folder Name=\"/meta/\">(?:.|\n)*?</Folder>",
$$"""
<Folder Name="/meta/">
{{string.Join('\n',
Directory.GetFiles(@"../", "*").Where(x => !x.EndsWith(".slnx") && !x.EndsWith(".user"))
.Select(x=>$" <File Path=\"{Path.GetFileName(x)}\"/>")
)}}
</Folder>
"""
);
content = Regex.Replace(
content,
"<Folder Name=\"/docker/\">(?:.|\n)*?</Folder>",
$$"""
<Folder Name="/docker/">
{{string.Join('\n',
Directory.GetFiles(@"../docker", "*")
.Select(x=>$" <File Path=\"docker/{Path.GetFileName(x)}\"/>")
)}}
</Folder>
"""
);
content = Regex.Replace(
content,
"<Folder Name=\"/.github/workflows/\">(?:.|\n)*?</Folder>",
$$"""
<Folder Name="/.github/workflows/">
{{string.Join('\n',
Directory.GetFiles(@"../.github/workflows", "*")
.Select(x=>$" <File Path=\".github/workflows/{Path.GetFileName(x)}\"/>")
)}}
</Folder>
"""
);
content = Regex.Replace(
content,
"<Folder Name=\"/.drone/workflows/\">(?:.|\n)*?</Folder>",
$$"""
<Folder Name="/.drone/workflows/">
{{string.Join('\n',
Directory.GetFiles(@"../.drone/workflows", "*")
.Select(x=>$" <File Path=\".drone/workflows/{Path.GetFileName(x)}\"/>")
)}}
</Folder>
"""
);
content = Regex.Replace(
content,
"<Folder Name=\"/scripts/\">(?:.|\n)*?</Folder>",
$$"""
<Folder Name="/scripts/">
{{string.Join('\n',
Directory.GetFiles(@"../scripts", "*")
.Select(x=>$" <File Path=\"scripts/{Path.GetFileName(x)}\"/>")
)}}
</Folder>
"""
);
content = Regex.Replace(
content,
"<Folder Name=\"/build/\">(?:.|\n)*?</Folder>",
$$"""
<Folder Name="/build/">
{{string.Join('\n',
Directory.GetFiles(@"../build", "*")
.Select(x=>$" <File Path=\"build/{Path.GetFileName(x)}\"/>")
)}}
</Folder>
"""
);
Console.WriteLine(content);
File.WriteAllText(slnxFile, content);

View File

@ -32,7 +32,6 @@ global using Gurion.DataEncryption;
global using Gurion.DataValidation; global using Gurion.DataValidation;
global using Gurion.DependencyInjection; global using Gurion.DependencyInjection;
global using Gurion.DynamicApiController; global using Gurion.DynamicApiController;
global using Gurion.EventBus;
global using Gurion.SpecificationDocument; global using Gurion.SpecificationDocument;
global using Gurion.UnifyResult; global using Gurion.UnifyResult;
global using Mapster; global using Mapster;
@ -58,6 +57,7 @@ global using NetAdmin.Infrastructure.Configuration.Options.SubNodes.Redis;
global using NetAdmin.Infrastructure.Configuration.Options.SubNodes.Upload; global using NetAdmin.Infrastructure.Configuration.Options.SubNodes.Upload;
global using NetAdmin.Infrastructure.Constant; global using NetAdmin.Infrastructure.Constant;
global using NetAdmin.Infrastructure.Enums; global using NetAdmin.Infrastructure.Enums;
global using NetAdmin.Infrastructure.EventBus;
global using NetAdmin.Infrastructure.Exceptions; global using NetAdmin.Infrastructure.Exceptions;
global using NetAdmin.Infrastructure.Extensions; global using NetAdmin.Infrastructure.Extensions;
global using NetAdmin.Infrastructure.Languages; global using NetAdmin.Infrastructure.Languages;

View File

@ -2,6 +2,7 @@ using CsvHelper;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using NetAdmin.Application.Repositories; using NetAdmin.Application.Repositories;
using NetAdmin.Domain; using NetAdmin.Domain;
using NetAdmin.Domain.Contexts;
using NetAdmin.Domain.DbMaps.Dependency; using NetAdmin.Domain.DbMaps.Dependency;
using NetAdmin.Domain.DbMaps.Dependency.Fields; using NetAdmin.Domain.DbMaps.Dependency.Fields;
using NetAdmin.Domain.Dto.Dependency; using NetAdmin.Domain.Dto.Dependency;
@ -53,9 +54,7 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
{ {
var select = selector(query).WithNoLockNoWait().Take(Numbers.MAX_LIMIT_EXPORT); var select = selector(query).WithNoLockNoWait().Take(Numbers.MAX_LIMIT_EXPORT);
object list = listExp == null object list = listExp == null ? await select.ToListAsync().ConfigureAwait(false) : await select.ToListAsync(listExp).ConfigureAwait(false);
? await select.ToListAsync().ConfigureAwait(false)
: await select.ToListAsync(listExp).ConfigureAwait(false);
return await GetExportFileStreamAsync<TExport>(fileName, list).ConfigureAwait(false); return await GetExportFileStreamAsync<TExport>(fileName, list).ConfigureAwait(false);
} }
@ -81,7 +80,7 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
// 默认匹配主键 // 默认匹配主键
whereExp ??= a => a.Id.Equals(newValue.Id); whereExp ??= a => a.Id.Equals(newValue.Id);
var update = BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql); var update = BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql);
return update.ExecuteAffrowsAsync(); return update.ExecuteEffectsAsync();
} }
#if DBTYPE_SQLSERVER #if DBTYPE_SQLSERVER
@ -135,6 +134,30 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
return new FileStreamResult(stream, Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_OCTET_STREAM); return new FileStreamResult(stream, Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_OCTET_STREAM);
} }
private static Dictionary<string, object> IncludeToDictionary(TEntity entity, List<string> includeFields)
{
var ret = includeFields!.ToDictionary(
x => x, x => typeof(TEntity).GetProperty(x, BindingFlags.Public | BindingFlags.Instance)!.GetValue(entity));
// ReSharper disable once ConvertIfStatementToSwitchStatement
if (entity is IFieldModifiedUser) {
var userInfo = App.GetService<ContextUserInfo>();
if (userInfo == null) {
return ret;
}
ret.Add(nameof(IFieldModifiedUser.ModifiedUserId), userInfo.Id);
ret.Add(nameof(IFieldModifiedUser.ModifiedUserName), userInfo.UserName);
}
// ReSharper disable once SuspiciousTypeConversion.Global
if (entity is IFieldModifiedClientIp) {
ret.Add(nameof(IFieldModifiedClientIp.ModifiedClientIp), App.HttpContext?.GetRealIpAddress()?.MapToIPv4().ToString().IpV4ToInt32());
}
return ret;
}
private IUpdate<TEntity> BuildUpdate(TEntity entity, List<string> includeFields, List<string> excludeFields, bool ignoreVersion) private IUpdate<TEntity> BuildUpdate(TEntity entity, List<string> includeFields, List<string> excludeFields, bool ignoreVersion)
{ {
IUpdate<TEntity> updateExp; IUpdate<TEntity> updateExp;
@ -145,9 +168,7 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
} }
} }
else { else {
updateExp = Rpo.UpdateDiy.SetDto(includeFields!.ToDictionary( updateExp = Rpo.UpdateDiy.SetDto(IncludeToDictionary(entity, includeFields));
x => x
, x => typeof(TEntity).GetProperty(x, BindingFlags.Public | BindingFlags.Instance)!.GetValue(entity)));
if (!ignoreVersion && entity is IFieldVersion ver) { if (!ignoreVersion && entity is IFieldVersion ver) {
updateExp = updateExp.Where($"{nameof(IFieldVersion.Version)} = {ver.Version}"); updateExp = updateExp.Where($"{nameof(IFieldVersion.Version)} = {ver.Version}");
} }

View File

@ -16,5 +16,5 @@ public interface ICache<out TCacheLoad, out TService>
/// <summary> /// <summary>
/// 关联的服务 /// 关联的服务
/// </summary> /// </summary>
public TService Service { get; } TService Service { get; }
} }

View File

@ -1,11 +1,11 @@
namespace NetAdmin.Domain.Attributes; namespace NetAdmin.Domain.Attributes;
/// <summary> /// <summary>
/// 标记一个枚举的状态指示 /// 枚举装饰
/// </summary> /// </summary>
/// <inheritdoc /> /// <inheritdoc />
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Enum)] [AttributeUsage(AttributeTargets.Field | AttributeTargets.Enum)]
public sealed class IndicatorAttribute(string indicate, bool pulse) : Attribute public sealed class EnumDecorationAttribute(string indicate = nameof(Indicates.None), bool pulse = false, int sort = 0) : Attribute
{ {
/// <summary> /// <summary>
/// 状态指示 /// 状态指示
@ -16,4 +16,9 @@ public sealed class IndicatorAttribute(string indicate, bool pulse) : Attribute
/// 脉动 /// 脉动
/// </summary> /// </summary>
public bool Pulse { get; } = pulse; public bool Pulse { get; } = pulse;
/// <summary>
/// 排序值
/// </summary>
public int Sort { get; } = sort;
} }

View File

@ -8,5 +8,5 @@ public interface IFieldModifiedClientIp
/// <summary> /// <summary>
/// 客户端IP /// 客户端IP
/// </summary> /// </summary>
int ModifiedClientIp { get; init; } int? ModifiedClientIp { get; init; }
} }

View File

@ -47,7 +47,7 @@ public abstract record MutableEntity<T> : LiteMutableEntity<T>, IFieldCreatedUse
[Column(CanInsert = false, Position = -1)] [Column(CanInsert = false, Position = -1)]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public long? ModifiedUserId { get; init; } public virtual long? ModifiedUserId { get; init; }
/// <summary> /// <summary>
/// 修改者用户名 /// 修改者用户名
@ -55,5 +55,5 @@ public abstract record MutableEntity<T> : LiteMutableEntity<T>, IFieldCreatedUse
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanInsert = false, Position = -1)] [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanInsert = false, Position = -1)]
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
public string ModifiedUserName { get; init; } public virtual string ModifiedUserName { get; init; }
} }

View File

@ -71,7 +71,7 @@ public record Sys_Api : ImmutableEntity<string>, IFieldSummary
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_RoleApi))] [Navigate(ManyToMany = typeof(Sys_RoleApi))]
public ICollection<Sys_Role> Roles { get; init; } public IReadOnlyCollection<Sys_Role> Roles { get; init; }
/// <summary> /// <summary>
/// 服务描述 /// 服务描述

View File

@ -44,7 +44,7 @@ public record Sys_Dept : VersionEntity, IFieldEnabled, IFieldSummary, IFieldSort
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_RoleDept))] [Navigate(ManyToMany = typeof(Sys_RoleDept))]
public ICollection<Sys_Role> Roles { get; init; } public IReadOnlyCollection<Sys_Role> Roles { get; init; }
/// <summary> /// <summary>
/// 发送给此部门的站内信集合 /// 发送给此部门的站内信集合
@ -52,7 +52,7 @@ public record Sys_Dept : VersionEntity, IFieldEnabled, IFieldSummary, IFieldSort
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_SiteMsgDept))] [Navigate(ManyToMany = typeof(Sys_SiteMsgDept))]
public ICollection<Sys_SiteMsg> SiteMsgs { get; init; } public IReadOnlyCollection<Sys_SiteMsg> SiteMsgs { get; init; }
/// <summary> /// <summary>
/// 排序值,越大越前 /// 排序值,越大越前

View File

@ -29,7 +29,7 @@ public record Sys_DicCatalog : VersionEntity
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(nameof(Sys_DicContent.CatalogId))] [Navigate(nameof(Sys_DicContent.CatalogId))]
public ICollection<Sys_DicContent> Contents { get; init; } public IReadOnlyCollection<Sys_DicContent> Contents { get; init; }
/// <summary> /// <summary>
/// 字典目录名称 /// 字典目录名称

View File

@ -29,7 +29,7 @@ public record Sys_DocCatalog : VersionEntity, IFieldOwner
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(nameof(Sys_DocContent.CatalogId))] [Navigate(nameof(Sys_DocContent.CatalogId))]
public ICollection<Sys_DocContent> Contents { get; init; } public IReadOnlyCollection<Sys_DocContent> Contents { get; init; }
/// <summary> /// <summary>
/// 文档分类名称 /// 文档分类名称

View File

@ -111,7 +111,7 @@ public record Sys_Menu : VersionEntity, IFieldSort
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_RoleMenu))] [Navigate(ManyToMany = typeof(Sys_RoleMenu))]
public ICollection<Sys_Role> Roles { get; init; } public IReadOnlyCollection<Sys_Role> Roles { get; init; }
/// <summary> /// <summary>
/// 排序值,越大越前 /// 排序值,越大越前

View File

@ -100,7 +100,7 @@ public record Sys_RequestLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFi
public virtual long? OwnerId { get; init; } public virtual long? OwnerId { get; init; }
/// <summary> /// <summary>
/// 请求踪标识 /// 请求踪标识
/// </summary> /// </summary>
[Column] [Column]
[CsvIgnore] [CsvIgnore]

View File

@ -16,7 +16,7 @@ public record Sys_Role : VersionEntity, IFieldSort, IFieldEnabled, IFieldSummary
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_RoleApi))] [Navigate(ManyToMany = typeof(Sys_RoleApi))]
public ICollection<Sys_Api> Apis { get; init; } public IReadOnlyCollection<Sys_Api> Apis { get; init; }
/// <summary> /// <summary>
/// 仪表板布局 /// 仪表板布局
@ -40,7 +40,7 @@ public record Sys_Role : VersionEntity, IFieldSort, IFieldEnabled, IFieldSummary
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_RoleDept))] [Navigate(ManyToMany = typeof(Sys_RoleDept))]
public ICollection<Sys_Dept> Depts { get; init; } public IReadOnlyCollection<Sys_Dept> Depts { get; init; }
/// <summary> /// <summary>
/// 是否显示仪表板 /// 是否显示仪表板
@ -72,7 +72,7 @@ public record Sys_Role : VersionEntity, IFieldSort, IFieldEnabled, IFieldSummary
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_RoleMenu))] [Navigate(ManyToMany = typeof(Sys_RoleMenu))]
public ICollection<Sys_Menu> Menus { get; init; } public IReadOnlyCollection<Sys_Menu> Menus { get; init; }
/// <summary> /// <summary>
/// 角色名称 /// 角色名称
@ -88,7 +88,7 @@ public record Sys_Role : VersionEntity, IFieldSort, IFieldEnabled, IFieldSummary
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_SiteMsgRole))] [Navigate(ManyToMany = typeof(Sys_SiteMsgRole))]
public ICollection<Sys_SiteMsg> SiteMsgs { get; init; } public IReadOnlyCollection<Sys_SiteMsg> SiteMsgs { get; init; }
/// <summary> /// <summary>
/// 排序值,越大越前 /// 排序值,越大越前
@ -112,7 +112,7 @@ public record Sys_Role : VersionEntity, IFieldSort, IFieldEnabled, IFieldSummary
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_UserRole))] [Navigate(ManyToMany = typeof(Sys_UserRole))]
public ICollection<Sys_User> Users { get; init; } public IReadOnlyCollection<Sys_User> Users { get; init; }
/// <inheritdoc /> /// <inheritdoc />
public virtual void Register(TypeAdapterConfig config) public virtual void Register(TypeAdapterConfig config)

View File

@ -31,7 +31,7 @@ public record Sys_SiteMsg : VersionEntity, IRegister, IFieldSummary
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_SiteMsgDept))] [Navigate(ManyToMany = typeof(Sys_SiteMsgDept))]
public ICollection<Sys_Dept> Depts { get; init; } public IReadOnlyCollection<Sys_Dept> Depts { get; init; }
/// <summary> /// <summary>
/// 消息-标记映射 /// 消息-标记映射
@ -39,7 +39,7 @@ public record Sys_SiteMsg : VersionEntity, IRegister, IFieldSummary
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(nameof(Sys_SiteMsgFlag.SiteMsgId))] [Navigate(nameof(Sys_SiteMsgFlag.SiteMsgId))]
public ICollection<Sys_SiteMsgFlag> Flags { get; init; } public IReadOnlyCollection<Sys_SiteMsgFlag> Flags { get; init; }
/// <summary> /// <summary>
/// 消息类型 /// 消息类型
@ -54,7 +54,7 @@ public record Sys_SiteMsg : VersionEntity, IRegister, IFieldSummary
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_SiteMsgRole))] [Navigate(ManyToMany = typeof(Sys_SiteMsgRole))]
public ICollection<Sys_Role> Roles { get; init; } public IReadOnlyCollection<Sys_Role> Roles { get; init; }
/// <summary> /// <summary>
/// 消息摘要 /// 消息摘要
@ -78,7 +78,7 @@ public record Sys_SiteMsg : VersionEntity, IRegister, IFieldSummary
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_SiteMsgUser))] [Navigate(ManyToMany = typeof(Sys_SiteMsgUser))]
public ICollection<Sys_User> Users { get; init; } public IReadOnlyCollection<Sys_User> Users { get; init; }
/// <inheritdoc /> /// <inheritdoc />
public void Register(TypeAdapterConfig config) public void Register(TypeAdapterConfig config)

View File

@ -97,7 +97,7 @@ public record Sys_User : VersionEntity, IFieldSummary, IFieldEnabled, IRegister
[CsvIgnore] [CsvIgnore]
[JsonIgnore] [JsonIgnore]
[Navigate(ManyToMany = typeof(Sys_SiteMsgUser))] [Navigate(ManyToMany = typeof(Sys_SiteMsgUser))]
public ICollection<Sys_SiteMsg> SiteMsgs { get; init; } public IReadOnlyCollection<Sys_SiteMsg> SiteMsgs { get; init; }
/// <summary> /// <summary>
/// 备注 /// 备注

View File

@ -22,4 +22,9 @@ public record RestfulInfo<T> : DataAbstraction
/// </summary> /// </summary>
/// <example>请求成功</example> /// <example>请求成功</example>
public object Msg { get; init; } public object Msg { get; init; }
/// <summary>
/// 追踪标识
/// </summary>
public Guid? TraceId { get; set; }
} }

View File

@ -15,11 +15,6 @@ public sealed record CacheStatisticsRsp : DataAbstraction
, new("redis_version:(.+)", RegexOptions.Compiled) // , new("redis_version:(.+)", RegexOptions.Compiled) //
]; ];
/// <summary>
/// Initializes a new instance of the <see cref="CacheStatisticsRsp" /> class.
/// </summary>
public CacheStatisticsRsp() { }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="CacheStatisticsRsp" /> class. /// Initializes a new instance of the <see cref="CacheStatisticsRsp" /> class.
/// </summary> /// </summary>

View File

@ -7,11 +7,6 @@ namespace NetAdmin.Domain.Dto.Sys.Cache;
/// </summary> /// </summary>
public sealed record GetEntryRsp : DataAbstraction public sealed record GetEntryRsp : DataAbstraction
{ {
/// <summary>
/// Initializes a new instance of the <see cref="GetEntryRsp" /> class.
/// </summary>
public GetEntryRsp() { }
/// <summary> /// <summary>
/// 缓存值 /// 缓存值
/// </summary> /// </summary>

View File

@ -0,0 +1,17 @@
namespace NetAdmin.Domain.Dto.Sys.File;
/// <summary>
/// 响应:文件上传
/// </summary>
public record UploadFileRsp : DataAbstraction
{
/// <summary>
/// 文件名
/// </summary>
public string FileName { get; init; }
/// <summary>
/// 可访问的url地址
/// </summary>
public string Url { get; init; }
}

View File

@ -5,7 +5,7 @@ namespace NetAdmin.Domain.Dto.Sys.Job;
/// </summary> /// </summary>
public sealed record EditJobReq : CreateJobReq public sealed record EditJobReq : CreateJobReq
{ {
/// <inheritdoc cref="System.Version" /> /// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Version { get; init; } public override long Version { get; init; }
} }

View File

@ -7,11 +7,6 @@ namespace NetAdmin.Domain.Dto.Sys.Menu;
/// </summary> /// </summary>
public sealed record MetaInfo : DataAbstraction public sealed record MetaInfo : DataAbstraction
{ {
/// <summary>
/// Initializes a new instance of the <see cref="MetaInfo" /> class.
/// </summary>
public MetaInfo() { }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MetaInfo" /> class. /// Initializes a new instance of the <see cref="MetaInfo" /> class.
/// </summary> /// </summary>

View File

@ -76,6 +76,6 @@ public sealed record ExportRequestLogRsp : QueryRequestLogRsp
/// <inheritdoc /> /// <inheritdoc />
[CsvIndex(7)] [CsvIndex(7)]
[CsvIgnore(false)] [CsvIgnore(false)]
[CsvName(nameof(Ln.踪标识))] [CsvName(nameof(Ln.踪标识))]
public override Guid TraceId { get; init; } public override Guid TraceId { get; init; }
} }

View File

@ -14,4 +14,9 @@ public record ExecuteSqlReq : DataAbstraction
/// 超时时间(秒) /// 超时时间(秒)
/// </summary> /// </summary>
public int TimeoutSecs { get; init; } public int TimeoutSecs { get; init; }
/// <summary>
/// 等待结果
/// </summary>
public bool WaitResult { get; init; } = true;
} }

View File

@ -11,7 +11,7 @@ public sealed record SetAvatarReq : Sys_User
[Url(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.网络地址不正确))] [Url(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.网络地址不正确))]
public override string Avatar { get; init; } public override string Avatar { get; init; }
/// <inheritdoc cref="System.Version" /> /// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public override long Version { get; init; } public override long Version { get; init; }
} }

View File

@ -9,7 +9,7 @@ public enum JobStatues
/// <summary> /// <summary>
/// 空闲 /// 空闲
/// </summary> /// </summary>
[Indicator(nameof(Indicates.Success), false)] [EnumDecoration(nameof(Indicates.Success), false)]
[ResourceDescription<Ln>(nameof(Ln.空闲))] [ResourceDescription<Ln>(nameof(Ln.空闲))]
Idle = 1 Idle = 1
@ -18,7 +18,7 @@ public enum JobStatues
/// <summary> /// <summary>
/// 运行 /// 运行
/// </summary> /// </summary>
[Indicator(nameof(Indicates.Warning), true)] [EnumDecoration(nameof(Indicates.Warning), true)]
[ResourceDescription<Ln>(nameof(Ln.运行))] [ResourceDescription<Ln>(nameof(Ln.运行))]
Running = 2 Running = 2
} }

View File

@ -0,0 +1,21 @@
namespace NetAdmin.Domain.Events;
/// <summary>
/// 事件数据
/// </summary>
public abstract record EventData<T> : DataAbstraction, IEventData<T>
{
/// <summary>
/// Initializes a new instance of the <see cref="EventData{T}" /> class.
/// </summary>
protected EventData(T payLoad)
{
PayLoad = payLoad;
}
/// <inheritdoc />
public DateTime CreatedTime { get; init; } = DateTime.Now;
/// <inheritdoc />
public T PayLoad { get; init; }
}

View File

@ -1,12 +0,0 @@
namespace NetAdmin.Domain.Events;
/// <summary>
/// 泛型事件源接口
/// </summary>
public interface IEventSourceGeneric<out T> : IEventSource
{
/// <summary>
/// 事件承载(携带)数据
/// </summary>
T Data { get; }
}

View File

@ -3,36 +3,9 @@ namespace NetAdmin.Domain.Events;
/// <summary> /// <summary>
/// 种子数据插入完毕事件 /// 种子数据插入完毕事件
/// </summary> /// </summary>
public sealed record SeedDataInsertedEvent : DataAbstraction, IEventSource public sealed record SeedDataInsertedEvent : EventData<int>
{ {
/// <summary>
/// Initializes a new instance of the <see cref="SeedDataInsertedEvent" /> class.
/// </summary>
public SeedDataInsertedEvent(int insertedCount, bool isConsumeOnce = false)
{
IsConsumeOnce = isConsumeOnce;
InsertedCount = insertedCount;
CreatedTime = DateTime.Now;
EventId = nameof(SeedDataInsertedEvent);
}
/// <inheritdoc /> /// <inheritdoc />
public DateTime CreatedTime { get; } public SeedDataInsertedEvent(int payLoad) //
: base(payLoad) { }
/// <inheritdoc />
public string EventId { get; }
/// <inheritdoc />
public bool IsConsumeOnce { get; }
/// <inheritdoc />
public CancellationToken CancellationToken { get; init; }
/// <summary>
/// 插入数量
/// </summary>
public int InsertedCount { get; set; }
/// <inheritdoc />
public object Payload { get; init; }
} }

View File

@ -12,7 +12,6 @@ public sealed record SqlCommandAfterEvent : SqlCommandBeforeEvent
: base(e) : base(e)
{ {
ElapsedMilliseconds = (long)((double)e.ElapsedTicks / Stopwatch.Frequency * 1_000); ElapsedMilliseconds = (long)((double)e.ElapsedTicks / Stopwatch.Frequency * 1_000);
EventId = nameof(SqlCommandAfterEvent);
} }
/// <summary> /// <summary>
@ -24,6 +23,6 @@ public sealed record SqlCommandAfterEvent : SqlCommandBeforeEvent
/// <inheritdoc /> /// <inheritdoc />
public override string ToString() public override string ToString()
{ {
return string.Format(CultureInfo.InvariantCulture, "SQL-{0}: {2} ms {1}", Id, Sql, ElapsedMilliseconds); return string.Format(CultureInfo.InvariantCulture, "SQL-{0}: {2} ms {1}", Id, PayLoad, ElapsedMilliseconds);
} }
} }

View File

@ -8,13 +8,8 @@ public record SqlCommandBeforeEvent : SqlCommandEvent
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SqlCommandBeforeEvent" /> class. /// Initializes a new instance of the <see cref="SqlCommandBeforeEvent" /> class.
/// </summary> /// </summary>
public SqlCommandBeforeEvent(CommandBeforeEventArgs e) public SqlCommandBeforeEvent(CommandBeforeEventArgs e) //
{ : base(e.Command.ParameterFormat().RemoveWrapped(), e.Identifier) { }
Identifier = e.Identifier;
Sql = e.Command.ParameterFormat().RemoveWrapped();
EventId = nameof(SqlCommandBeforeEvent);
CreatedTime = DateTime.Now;
}
/// <inheritdoc /> /// <inheritdoc />
public override string ToString() public override string ToString()

View File

@ -3,31 +3,17 @@ namespace NetAdmin.Domain.Events;
/// <summary> /// <summary>
/// Sql命令事件 /// Sql命令事件
/// </summary> /// </summary>
public abstract record SqlCommandEvent : DataAbstraction, IEventSource public abstract record SqlCommandEvent : EventData<string>
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SqlCommandEvent" /> class. /// Initializes a new instance of the <see cref="SqlCommandEvent" /> class.
/// </summary> /// </summary>
protected SqlCommandEvent(bool isConsumeOnce = false) protected SqlCommandEvent(string payLoad, Guid identifier) //
: base(payLoad)
{ {
IsConsumeOnce = isConsumeOnce; Identifier = identifier;
} }
/// <inheritdoc />
public bool IsConsumeOnce { 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>
/// 标识符缩写 /// 标识符缩写
/// </summary> /// </summary>
@ -37,9 +23,4 @@ public abstract record SqlCommandEvent : DataAbstraction, IEventSource
/// 标识符,可将 CommandBefore 与 CommandAfter 进行匹配 /// 标识符,可将 CommandBefore 与 CommandAfter 进行匹配
/// </summary> /// </summary>
protected Guid Identifier { get; init; } protected Guid Identifier { get; init; }
/// <summary>
/// 关联的Sql语句
/// </summary>
protected string Sql { get; init; }
} }

View File

@ -9,10 +9,7 @@ public sealed record SyncStructureAfterEvent : SyncStructureBeforeEvent
/// Initializes a new instance of the <see cref="SyncStructureAfterEvent" /> class. /// Initializes a new instance of the <see cref="SyncStructureAfterEvent" /> class.
/// </summary> /// </summary>
public SyncStructureAfterEvent(SyncStructureBeforeEventArgs e) // public SyncStructureAfterEvent(SyncStructureBeforeEventArgs e) //
: base(e) : base(e) { }
{
EventId = nameof(SyncStructureAfterEvent);
}
/// <inheritdoc /> /// <inheritdoc />
public override string ToString() public override string ToString()

View File

@ -8,11 +8,9 @@ public record SyncStructureBeforeEvent : SqlCommandEvent
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SyncStructureBeforeEvent" /> class. /// Initializes a new instance of the <see cref="SyncStructureBeforeEvent" /> class.
/// </summary> /// </summary>
public SyncStructureBeforeEvent(SyncStructureBeforeEventArgs e) public SyncStructureBeforeEvent(SyncStructureBeforeEventArgs e) //
: base(null, e.Identifier)
{ {
Identifier = e.Identifier;
EventId = nameof(SyncStructureBeforeEvent);
CreatedTime = DateTime.Now;
EntityTypes = e.EntityTypes; EntityTypes = e.EntityTypes;
} }

View File

@ -5,36 +5,9 @@ namespace NetAdmin.Domain.Events.Sys;
/// <summary> /// <summary>
/// 请求日志事件 /// 请求日志事件
/// </summary> /// </summary>
public sealed record RequestLogEvent : DataAbstraction, IEventSourceGeneric<CreateRequestLogReq> public sealed record RequestLogEvent : EventData<CreateRequestLogReq>
{ {
/// <summary>
/// Initializes a new instance of the <see cref="RequestLogEvent" /> class.
/// </summary>
public RequestLogEvent(CreateRequestLogReq data, bool isConsumeOnce = false, object payload = default, DateTime createdTime = default
, CancellationToken cancellationToken = default)
{
Data = data;
IsConsumeOnce = isConsumeOnce;
Payload = payload;
CreatedTime = createdTime;
CancellationToken = cancellationToken;
}
/// <inheritdoc /> /// <inheritdoc />
public CancellationToken CancellationToken { get; } public RequestLogEvent(CreateRequestLogReq payLoad) //
: base(payLoad) { }
/// <inheritdoc />
public DateTime CreatedTime { get; }
/// <inheritdoc />
public CreateRequestLogReq Data { get; }
/// <inheritdoc />
public string EventId => nameof(RequestLogEvent);
/// <inheritdoc />
public bool IsConsumeOnce { get; }
/// <inheritdoc />
public object Payload { get; }
} }

View File

@ -5,36 +5,9 @@ namespace NetAdmin.Domain.Events.Sys;
/// <summary> /// <summary>
/// 用户被创建事件 /// 用户被创建事件
/// </summary> /// </summary>
public sealed record UserCreatedEvent : DataAbstraction, IEventSourceGeneric<UserInfoRsp> public sealed record UserCreatedEvent : EventData<UserInfoRsp>
{ {
/// <summary>
/// Initializes a new instance of the <see cref="UserCreatedEvent" /> class.
/// </summary>
public UserCreatedEvent(UserInfoRsp data, DateTime createdTime = default, bool isConsumeOnce = false, object payload = default
, CancellationToken cancellationToken = default)
{
Data = data;
CancellationToken = cancellationToken;
CreatedTime = createdTime;
IsConsumeOnce = isConsumeOnce;
Payload = payload;
}
/// <inheritdoc /> /// <inheritdoc />
public CancellationToken CancellationToken { get; } public UserCreatedEvent(UserInfoRsp payLoad) //
: base(payLoad) { }
/// <inheritdoc />
public DateTime CreatedTime { get; }
/// <inheritdoc />
public UserInfoRsp Data { get; }
/// <inheritdoc />
public string EventId => nameof(UserCreatedEvent);
/// <inheritdoc />
public bool IsConsumeOnce { get; }
/// <inheritdoc />
public object Payload { get; }
} }

View File

@ -5,36 +5,9 @@ namespace NetAdmin.Domain.Events.Sys;
/// <summary> /// <summary>
/// 用户被更新事件 /// 用户被更新事件
/// </summary> /// </summary>
public sealed record UserUpdatedEvent : DataAbstraction, IEventSourceGeneric<UserInfoRsp> public sealed record UserUpdatedEvent : EventData<UserInfoRsp>
{ {
/// <summary>
/// Initializes a new instance of the <see cref="UserUpdatedEvent" /> class.
/// </summary>
public UserUpdatedEvent(UserInfoRsp data, DateTime createdTime = default, bool isConsumeOnce = false, object payload = default
, CancellationToken cancellationToken = default)
{
Data = data;
CancellationToken = cancellationToken;
CreatedTime = createdTime;
IsConsumeOnce = isConsumeOnce;
Payload = payload;
}
/// <inheritdoc /> /// <inheritdoc />
public CancellationToken CancellationToken { get; } public UserUpdatedEvent(UserInfoRsp payLoad) //
: base(payLoad) { }
/// <inheritdoc />
public DateTime CreatedTime { get; }
/// <inheritdoc />
public UserInfoRsp Data { get; }
/// <inheritdoc />
public string EventId => nameof(UserUpdatedEvent);
/// <inheritdoc />
public bool IsConsumeOnce { get; }
/// <inheritdoc />
public object Payload { get; }
} }

View File

@ -5,36 +5,9 @@ namespace NetAdmin.Domain.Events.Sys;
/// <summary> /// <summary>
/// 验证码创建事件 /// 验证码创建事件
/// </summary> /// </summary>
public sealed record VerifyCodeCreatedEvent : DataAbstraction, IEventSourceGeneric<QueryVerifyCodeRsp> public sealed record VerifyCodeCreatedEvent : EventData<QueryVerifyCodeRsp>
{ {
/// <summary>
/// Initializes a new instance of the <see cref="VerifyCodeCreatedEvent" /> class.
/// </summary>
public VerifyCodeCreatedEvent(QueryVerifyCodeRsp data, DateTime createdTime = default, bool isConsumeOnce = false, object payload = default
, CancellationToken cancellationToken = default)
{
Data = data;
CancellationToken = cancellationToken;
CreatedTime = createdTime;
IsConsumeOnce = isConsumeOnce;
Payload = payload;
}
/// <inheritdoc /> /// <inheritdoc />
public CancellationToken CancellationToken { get; } public VerifyCodeCreatedEvent(QueryVerifyCodeRsp payLoad) //
: base(payLoad) { }
/// <inheritdoc />
public DateTime CreatedTime { get; }
/// <inheritdoc />
public QueryVerifyCodeRsp Data { get; }
/// <inheritdoc />
public string EventId => nameof(VerifyCodeCreatedEvent);
/// <inheritdoc />
public bool IsConsumeOnce { get; }
/// <inheritdoc />
public object Payload { get; }
} }

View File

@ -1,3 +1,7 @@
#if DBTYPE_SQLSERVER
using FreeSql.Provider.SqlServer;
#endif
namespace NetAdmin.Domain.Extensions; namespace NetAdmin.Domain.Extensions;
/// <summary> /// <summary>

View File

@ -4,8 +4,8 @@
<ProjectReference Include="../NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj"/> <ProjectReference Include="../NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CronExpressionDescriptor" Version="2.36.0"/> <PackageReference Include="CronExpressionDescriptor" Version="2.40.0"/>
<PackageReference Include="Cronos" Version="0.9.0"/> <PackageReference Include="Cronos" Version="0.10.0"/>
<PackageReference Include="NetAdmin.CsvHelper" Version="1.0.0"/> <PackageReference Include="NetAdmin.CsvHelper" Version="1.0.0"/>
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14"/> <PackageReference Include="Yitter.IdGenerator" Version="1.0.14"/>
</ItemGroup> </ItemGroup>

View File

@ -34,7 +34,6 @@ public sealed class ExampleController(IExampleCache cache) : ControllerBase<IExa
/// <summary> /// <summary>
/// 示例分组计数 /// 示例分组计数
/// </summary> /// </summary>
[NonAction]
public Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryExampleReq> req) public Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryExampleReq> req)
{ {
return Cache.CountByAsync(req); return Cache.CountByAsync(req);

View File

@ -133,7 +133,11 @@ public static class ServiceCollectionExtensions
/// </summary> /// </summary>
public static IServiceCollection AddEventBus(this IServiceCollection me) public static IServiceCollection AddEventBus(this IServiceCollection me)
{ {
return me.AddEventBus(builder => builder.AddSubscribers(App.Assemblies.ToArray())); foreach (var type in App.EffectiveTypes.Where(x => typeof(IEventSubscriber).IsAssignableFrom(x) && x.IsClass && !x.IsAbstract)) {
_ = me.AddSingleton(type);
}
return me.AddSingleton<IEventPublisher>(new DefaultEventPublisher());
} }
/// <summary> /// <summary>

View File

@ -35,7 +35,7 @@ public abstract class ApiResultHandler<T>
var result = RestfulResult(errorCode, metadata.Data var result = RestfulResult(errorCode, metadata.Data
, naException is NetAdminValidateException vEx , naException is NetAdminValidateException vEx
? vEx.ValidateResults ? vEx.ValidateResults
: naException?.Message ?? errorCode.ResDesc<ErrorCodes>()); : naException?.Message ?? errorCode.ResDesc<ErrorCodes>(), context.HttpContext.GetTraceId());
SetErrorCodeToHeader(context.HttpContext, errorCode); SetErrorCodeToHeader(context.HttpContext, errorCode);
@ -95,9 +95,9 @@ public abstract class ApiResultHandler<T>
/// <summary> /// <summary>
/// 返回 RESTful 风格结果集 /// 返回 RESTful 风格结果集
/// </summary> /// </summary>
private static T RestfulResult(ErrorCodes errorCode, object data = default, object message = default) private static T RestfulResult(ErrorCodes errorCode, object data = null, object message = null, Guid? traceId = null)
{ {
return new T { Code = errorCode, Data = data, Msg = message }; return new T { Code = errorCode, Data = data, Msg = message, TraceId = traceId };
} }
/// <summary> /// <summary>

View File

@ -0,0 +1,16 @@
namespace NetAdmin.Host.Middlewares;
/// <summary>
/// 输出环境信息到 http header
/// </summary>
public sealed class EnvironmentInfoMiddleware(RequestDelegate next)
{
/// <summary>
/// 主函数
/// </summary>
public Task InvokeAsync(HttpContext context)
{
context.Response.Headers.Append("X-Node", Environment.MachineName);
return next(context);
}
}

View File

@ -27,9 +27,11 @@ public sealed class SafetyShopHostMiddleware(RequestDelegate next)
public static void OnStopping() public static void OnStopping()
{ {
Stop(); Stop();
#if !DEBUG
while (Interlocked.Read(ref _connections) > 0) { while (Interlocked.Read(ref _connections) > 0) {
Thread.Sleep(10); Thread.Sleep(10);
} }
#endif
} }
/// <summary> /// <summary>

View File

@ -10,55 +10,50 @@ public sealed class SqlProfiler(ILogger<SqlProfiler> logger) : IEventSubscriber
/// <summary> /// <summary>
/// Sql命令执行后 /// Sql命令执行后
/// </summary> /// </summary>
[EventSubscribe(nameof(SqlCommandAfterEvent))] [EventSubscribe]
public Task CommandAfterAsync(EventHandlerExecutingContext context) public Task CommandAfterAsync(SqlCommandAfterEvent @event)
{ {
var source = context.Source as SqlCommandAfterEvent; logger.Info(@event);
logger.Info(source);
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <summary> /// <summary>
/// Sql命令执行前 /// Sql命令执行前
/// </summary> /// </summary>
[EventSubscribe(nameof(SqlCommandBeforeEvent))] [EventSubscribe]
public Task CommandBeforeAsync(EventHandlerExecutingContext context) public Task CommandBeforeAsync(SqlCommandBeforeEvent @event)
{ {
var source = context.Source as SqlCommandBeforeEvent; logger.Debug(@event);
logger.Debug(source);
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <summary> /// <summary>
/// 种子数据插入完毕 /// 种子数据插入完毕
/// </summary> /// </summary>
[EventSubscribe(nameof(SeedDataInsertedEvent))] [EventSubscribe]
public Task SeedDataInsertedEventAsync(EventHandlerExecutingContext context) public Task SeedDataInsertedEventAsync(SeedDataInsertedEvent @event)
{ {
var source = context.Source as SeedDataInsertedEvent; logger.Info(@event);
logger.Info(source);
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <summary> /// <summary>
/// 同步数据库结构之后 /// 同步数据库结构之后
/// </summary> /// </summary>
[EventSubscribe(nameof(SyncStructureAfterEvent))] [EventSubscribe]
public Task SyncStructureAfterAsync(EventHandlerExecutingContext context) public Task SyncStructureAfterAsync(SyncStructureAfterEvent @event)
{ {
var source = context.Source as SyncStructureAfterEvent; logger.Info(@event);
logger.Info(source);
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <summary> /// <summary>
/// 同步数据库结构之前 /// 同步数据库结构之前
/// </summary> /// </summary>
[EventSubscribe(nameof(SyncStructureBeforeEvent))] [EventSubscribe]
public Task SyncStructureBeforeAsync(EventHandlerExecutingContext context) public Task SyncStructureBeforeAsync(SyncStructureBeforeEvent @event)
{ {
var source = context.Source as SyncStructureBeforeEvent; logger.Info(@event);
logger.Info(source);
return Task.CompletedTask; return Task.CompletedTask;
} }
} }

View File

@ -38,4 +38,11 @@ public enum Indicates
/// 危险 /// 危险
/// </summary> /// </summary>
Danger = 5 Danger = 5
,
/// <summary>
/// 无
/// </summary>
None = 6
} }

View File

@ -7,10 +7,10 @@ namespace NetAdmin.Infrastructure.Enums;
public enum LogLevels public enum LogLevels
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[Display(Name = "[gray]TCE[/]", ShortName = "TCE")] [Display(Name = "[gray]TCE[/]", ShortName = "TCE")]
[ResourceDescription<Ln>(nameof(Ln.踪))] [ResourceDescription<Ln>(nameof(Ln.踪))]
Trace = 0 Trace = 0
, ,

View File

@ -0,0 +1,39 @@
using System.Threading.Channels;
namespace NetAdmin.Infrastructure.EventBus;
/// <summary>
/// 事件发布器默认实现
/// </summary>
public sealed class DefaultEventPublisher : IEventPublisher
{
private readonly Channel<object> _eventChannel;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultEventPublisher" /> class.
/// </summary>
public DefaultEventPublisher()
{
_eventChannel = Channel.CreateUnbounded<object>();
_ = new TaskFactory<Task>().StartNew( //
async state => {
var subscribers = (List<MethodInfo>)state;
await Parallel.ForEachAsync(_eventChannel.Reader.ReadAllAsync(), (msg, __) => {
_ = Parallel.ForEach( //
subscribers.Where(x => x.GetParameters().FirstOrDefault()?.ParameterType == msg.GetType())
, (x, _) => x.Invoke(App.GetService(x.DeclaringType), [msg]));
return ValueTask.CompletedTask;
})
.ConfigureAwait(false);
}, App.EffectiveTypes.Where(x => typeof(IEventSubscriber).IsAssignableFrom(x) && x.IsClass && !x.IsAbstract).SelectMany(x => x.GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(y => y.IsDefined(typeof(EventSubscribeAttribute)))).ToList());
}
/// <inheritdoc />
public int ChannelCount => _eventChannel.Reader.Count;
/// <inheritdoc />
public async Task PublishAsync<T>(IEventData<T> eventData)
{
await _eventChannel.Writer.WriteAsync(eventData).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,7 @@
namespace NetAdmin.Infrastructure.EventBus;
/// <summary>
/// 事件处理程序特性
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public sealed class EventSubscribeAttribute : Attribute;

View File

@ -0,0 +1,17 @@
namespace NetAdmin.Infrastructure.EventBus;
/// <summary>
/// 事件数据接口
/// </summary>
public interface IEventData<T>
{
/// <summary>
/// 事件发生时间
/// </summary>
DateTime CreatedTime { get; init; }
/// <summary>
/// 负载
/// </summary>
T PayLoad { get; init; }
}

View File

@ -0,0 +1,17 @@
namespace NetAdmin.Infrastructure.EventBus;
/// <summary>
/// 事件发布器接口
/// </summary>
public interface IEventPublisher
{
/// <summary>
/// 通道数量
/// </summary>
int ChannelCount { get; }
/// <summary>
/// 发布一条消息
/// </summary>
Task PublishAsync<T>(IEventData<T> eventData);
}

View File

@ -0,0 +1,6 @@
namespace NetAdmin.Infrastructure.EventBus;
/// <summary>
/// 事件订阅器接口
/// </summary>
public interface IEventSubscriber;

View File

@ -24,7 +24,7 @@ public static class HttpContextExtensions
} }
/// <summary> /// <summary>
/// 获取踪标识 /// 获取踪标识
/// </summary> /// </summary>
public static Guid GetTraceId(this HttpContext me) public static Guid GetTraceId(this HttpContext me)
{ {

View File

@ -46,33 +46,12 @@ public static class GlobalStatic
/// <exception cref="NotImplementedException">NotImplementedException</exception> /// <exception cref="NotImplementedException">NotImplementedException</exception>
public static string SqlRandomSorting => public static string SqlRandomSorting =>
App.GetOptions<DatabaseOptions>().DbType switch { App.GetOptions<DatabaseOptions>().DbType switch {
DataType.MySql => "RAND()" DataType.MySql => "RAND()"
, DataType.SqlServer => "NEWID()" , DataType.SqlServer => "NEWID()"
, DataType.PostgreSQL => "RANDOM()" , DataType.PostgreSQL => "RANDOM()"
, DataType.Oracle => "DBMS_RANDOM.value" , DataType.Oracle => "DBMS_RANDOM.value"
, DataType.Sqlite => "RANDOM()" , DataType.Sqlite => "RANDOM()"
, DataType.OdbcOracle => throw new NotImplementedException() , _ => throw new NotImplementedException()
, DataType.OdbcSqlServer => throw new NotImplementedException()
, DataType.OdbcMySql => throw new NotImplementedException()
, DataType.OdbcPostgreSQL => throw new NotImplementedException()
, DataType.Odbc => throw new NotImplementedException()
, DataType.OdbcDameng => throw new NotImplementedException()
, DataType.MsAccess => throw new NotImplementedException()
, DataType.Dameng => throw new NotImplementedException()
, DataType.OdbcKingbaseES => throw new NotImplementedException()
, DataType.ShenTong => throw new NotImplementedException()
, DataType.KingbaseES => throw new NotImplementedException()
, DataType.Firebird => throw new NotImplementedException()
, DataType.Custom => throw new NotImplementedException()
, DataType.ClickHouse => throw new NotImplementedException()
, DataType.GBase => throw new NotImplementedException()
, DataType.QuestDb => throw new NotImplementedException()
, DataType.Xugu => throw new NotImplementedException()
, DataType.CustomOracle => throw new NotImplementedException()
, DataType.CustomSqlServer => throw new NotImplementedException()
, DataType.CustomMySql => throw new NotImplementedException()
, DataType.CustomPostgreSQL => throw new NotImplementedException()
, _ => throw new NotImplementedException()
}; };
/// <summary> /// <summary>

View File

@ -3,13 +3,13 @@
<Import Project="$(SolutionDir)/build/copy.pkg.xml.comment.files.targets"/> <Import Project="$(SolutionDir)/build/copy.pkg.xml.comment.files.targets"/>
<Import Project="$(SolutionDir)/build/prebuild.targets"/> <Import Project="$(SolutionDir)/build/prebuild.targets"/>
<ItemGroup> <ItemGroup>
<PackageReference Include="NetAdmin.FreeSql.DbContext" Version="1.0.3" Label="refs"/> <PackageReference Include="NetAdmin.FreeSql.DbContext" Version="1.1.3" Label="refs"/>
<PackageReference Include="NetAdmin.FreeSql.Provider.Sqlite" Version="1.0.3" Label="refs"/> <PackageReference Include="NetAdmin.FreeSql.Provider.Sqlite" Version="1.1.3" Label="refs"/>
<PackageReference Include="Gurion" Version="1.2.5" Label="refs"/> <PackageReference Include="Gurion" Version="1.2.13" Label="refs"/>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0"/> <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.4"/>
<PackageReference Include="Minio" Version="6.0.3"/> <PackageReference Include="Minio" Version="6.0.4"/>
<PackageReference Include="NSExt" Version="2.3.2"/> <PackageReference Include="NSExt" Version="2.3.5"/>
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.4"/> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.5"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<!--<ProjectReference Include="$(SolutionDir)/refs/NetAdmin.FreeSql/src/FreeSql.DbContext/FreeSql.DbContext.csproj" Label="refs"/>--> <!--<ProjectReference Include="$(SolutionDir)/refs/NetAdmin.FreeSql/src/FreeSql.DbContext/FreeSql.DbContext.csproj" Label="refs"/>-->

View File

@ -0,0 +1,12 @@
namespace NetAdmin.Infrastructure.Schedule;
/// <summary>
/// 作业处理程序
/// </summary>
public interface IJob
{
/// <summary>
/// 具体处理逻辑
/// </summary>
Task ExecuteAsync(CancellationToken cancelToken);
}

View File

@ -0,0 +1,23 @@
namespace NetAdmin.Infrastructure.Schedule;
/// <summary>
/// 作业配置
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class JobConfigAttribute : Attribute
{
/// <summary>
/// 上一次执行时间
/// </summary>
public DateTime? LastExecutionTime { get; set; }
/// <summary>
/// 启动时运行
/// </summary>
public bool RunOnStart { get; init; }
/// <summary>
/// 触发器表达式
/// </summary>
public string TriggerCron { get; init; }
}

View File

@ -37,12 +37,12 @@ public static class CaptchaImageHelper
await using var tranStream = resAsm.GetManifestResourceStream($"{tempPath}._{templateIndex}.transparent.png"); await using var tranStream = resAsm.GetManifestResourceStream($"{tempPath}._{templateIndex}.transparent.png");
// 底图 // 底图
using var backgroundImage = await Image.LoadAsync<Rgba32>(bgStream).ConfigureAwait(false); using var backgroundImage = await Image.LoadAsync<Rgba32>(bgStream!).ConfigureAwait(false);
using var darkTemplateImage = await Image.LoadAsync<Rgba32>(darkStream).ConfigureAwait(false); using var darkTemplateImage = await Image.LoadAsync<Rgba32>(darkStream!).ConfigureAwait(false);
// 透明模板图 // 透明模板图
using var transparentTemplateImage = await Image.LoadAsync<Rgba32>(tranStream).ConfigureAwait(false); using var transparentTemplateImage = await Image.LoadAsync<Rgba32>(tranStream!).ConfigureAwait(false);
// 调整模板图大小 // 调整模板图大小
darkTemplateImage.Mutate(x => x.Resize(sliderSize)); darkTemplateImage.Mutate(x => x.Resize(sliderSize));

View File

@ -58,7 +58,7 @@ public sealed class FreeSqlBuilder(DatabaseOptions databaseOptions)
{ {
return typeof(IBaseRepository<>).MakeGenericType(entityType) return typeof(IBaseRepository<>).MakeGenericType(entityType)
.GetMethod( // .GetMethod( //
nameof(IBaseRepository<dynamic>.Insert) // nameof(IBaseRepository<>.Insert) //
, BindingFlags.Public | BindingFlags.Instance // , BindingFlags.Public | BindingFlags.Instance //
, null // , null //
, CallingConventions.Any // , CallingConventions.Any //
@ -119,7 +119,7 @@ public sealed class FreeSqlBuilder(DatabaseOptions databaseOptions)
// 如果表存在数据,跳过 // 如果表存在数据,跳过
var select = typeof(IFreeSql).GetMethod(nameof(freeSql.Select), 1, Type.EmptyTypes)?.MakeGenericMethod(entityType).Invoke(freeSql, null); var select = typeof(IFreeSql).GetMethod(nameof(freeSql.Select), 1, Type.EmptyTypes)?.MakeGenericMethod(entityType).Invoke(freeSql, null);
if (select?.GetType().GetMethod(nameof(ISelect<dynamic>.Any), 0, Type.EmptyTypes)?.Invoke(select, null) as bool? ?? true) { if (select?.GetType().GetMethod(nameof(ISelect<>.Any), 0, Type.EmptyTypes)?.Invoke(select, null) as bool? ?? true) {
continue; continue;
} }

View File

@ -15,8 +15,8 @@ public sealed class MinioHelper(IOptions<UploadOptions> uploadOptions) : IScoped
/// <param name="fileStream">文件流</param> /// <param name="fileStream">文件流</param>
/// <param name="contentType">文件类型</param> /// <param name="contentType">文件类型</param>
/// <param name="fileSize">文件大小</param> /// <param name="fileSize">文件大小</param>
/// <returns>可访问的url地址</returns> /// <returns>文件名,可访问的url地址</returns>
public async Task<string> UploadAsync(string objectName, Stream fileStream, string contentType, long fileSize) public async Task<(string FileName, string Url)> UploadAsync(string objectName, Stream fileStream, string contentType, long fileSize)
{ {
using var minio = new MinioClient().WithEndpoint(uploadOptions.Value.Minio.ServerAddress) using var minio = new MinioClient().WithEndpoint(uploadOptions.Value.Minio.ServerAddress)
.WithCredentials( // .WithCredentials( //
@ -38,6 +38,6 @@ public sealed class MinioHelper(IOptions<UploadOptions> uploadOptions) : IScoped
.WithContentType(contentType); .WithContentType(contentType);
_ = await minio.PutObjectAsync(putArgs).ConfigureAwait(false); _ = await minio.PutObjectAsync(putArgs).ConfigureAwait(false);
return $"{uploadOptions.Value.Minio.AccessUrl}/{uploadOptions.Value.Minio.BucketName}/{objectName}"; return (objectName, $"{uploadOptions.Value.Minio.AccessUrl}/{uploadOptions.Value.Minio.BucketName}/{objectName}");
} }
} }

View File

@ -49,7 +49,9 @@ public sealed class RedisLocker : IAsyncDisposable
return new RedisLocker(redisDatabase, lockerName); return new RedisLocker(redisDatabase, lockerName);
} }
await Task.Delay(retryDelay).ConfigureAwait(false); if (retryCount > 1) {
await Task.Delay(retryDelay).ConfigureAwait(false);
}
} }
throw new NetAdminGetLockerException(lockerName); throw new NetAdminGetLockerException(lockerName);

View File

@ -14,7 +14,7 @@ public interface IApiModule : ICrudModule<CreateApiReq, QueryApiRsp // 创建类
/// <summary> /// <summary>
/// 平面查询接口 /// 平面查询接口
/// </summary> /// </summary>
public Task<IEnumerable<QueryApiRsp>> PlainQueryAsync(QueryReq<QueryApiReq> req); Task<IEnumerable<QueryApiRsp>> PlainQueryAsync(QueryReq<QueryApiReq> req);
/// <summary> /// <summary>
/// 同步接口 /// 同步接口

View File

@ -1,3 +1,5 @@
using NetAdmin.Domain.Dto.Sys.File;
namespace NetAdmin.SysComponent.Application.Modules.Sys; namespace NetAdmin.SysComponent.Application.Modules.Sys;
/// <summary> /// <summary>
@ -8,5 +10,5 @@ public interface IFileModule
/// <summary> /// <summary>
/// 文件上传 /// 文件上传
/// </summary> /// </summary>
Task<string> UploadAsync(IFormFile file); Task<UploadFileRsp> UploadAsync(IFormFile file);
} }

View File

@ -88,10 +88,7 @@ public sealed class CacheService(IConnectionMultiplexer connectionMultiplexer) /
, ExpireTime = DateTime.Now + await database.KeyTimeToLiveAsync(req.Key).ConfigureAwait(false) , ExpireTime = DateTime.Now + await database.KeyTimeToLiveAsync(req.Key).ConfigureAwait(false)
}; };
#pragma warning disable IDE0072 ret.Data = ret.Type switch {
ret.Data = ret.Type switch
#pragma warning restore IDE0072
{
RedisType.String => await database.StringGetAsync(req.Key).ConfigureAwait(false) RedisType.String => await database.StringGetAsync(req.Key).ConfigureAwait(false)
, RedisType.List => string.Join(", ", await database.ListRangeAsync(req.Key).ConfigureAwait(false)) , RedisType.List => string.Join(", ", await database.ListRangeAsync(req.Key).ConfigureAwait(false))
, RedisType.Set => string.Join(", ", await database.SetMembersAsync(req.Key).ConfigureAwait(false)) , RedisType.Set => string.Join(", ", await database.SetMembersAsync(req.Key).ConfigureAwait(false))

View File

@ -10,11 +10,6 @@ public sealed class CaptchaService : ServiceBase<ICaptchaService>, ICaptchaServi
private static readonly Assembly _currAsm = Assembly.GetAssembly(typeof(CaptchaService)); private static readonly Assembly _currAsm = Assembly.GetAssembly(typeof(CaptchaService));
private static readonly string _currAsmName = _currAsm.FullName![.._currAsm.FullName.IndexOf(',')]; private static readonly string _currAsmName = _currAsm.FullName![.._currAsm.FullName.IndexOf(',')];
/// <summary>
/// Initializes a new instance of the <see cref="CaptchaService" /> class.
/// </summary>
public CaptchaService() { }
/// <inheritdoc /> /// <inheritdoc />
public async Task<GetCaptchaRsp> GetCaptchaImageAsync() public async Task<GetCaptchaRsp> GetCaptchaImageAsync()
{ {

View File

@ -35,8 +35,11 @@ public sealed class ConstantService : ServiceBase<IConstantService>, IConstantSe
return [..ret, z.GetCallingCode().ToInvString()]; return [..ret, z.GetCallingCode().ToInvString()];
} }
var indicate = y.Attr<IndicatorAttribute>(); var decorationAttribute = y.Attr<EnumDecorationAttribute>() ?? new EnumDecorationAttribute();
return indicate == null ? ret : [..ret, indicate.Indicate.ToLowerInvariant(), indicate.Pulse.ToString().ToLowerInvariant()]; return [
..ret, decorationAttribute.Indicate.ToLowerInvariant(), decorationAttribute.Pulse.ToString().ToLowerInvariant()
, decorationAttribute.Sort.ToInvString()
];
} }
static string[] GetHttpStatusCodeDicValue(string name) static string[] GetHttpStatusCodeDicValue(string name)

View File

@ -10,7 +10,7 @@ public interface IApiService : IService, IApiModule
/// <summary> /// <summary>
/// 接口是否存在 /// 接口是否存在
/// </summary> /// </summary>
public Task<bool> ExistAsync(QueryReq<QueryApiReq> req); Task<bool> ExistAsync(QueryReq<QueryApiReq> req);
/// <summary> /// <summary>
/// 反射接口列表 /// 反射接口列表

View File

@ -10,7 +10,7 @@ public interface IUserService : IService, IUserModule
/// <summary> /// <summary>
/// 用户是否存在 /// 用户是否存在
/// </summary> /// </summary>
public Task<bool> ExistAsync(QueryReq<QueryUserReq> req); Task<bool> ExistAsync(QueryReq<QueryUserReq> req);
/// <summary> /// <summary>
/// 用户编号登录 /// 用户编号登录

View File

@ -1,3 +1,5 @@
using NetAdmin.Domain.Dto.Sys.File;
namespace NetAdmin.SysComponent.Application.Services.Sys; namespace NetAdmin.SysComponent.Application.Services.Sys;
/// <inheritdoc cref="IFileService" /> /// <inheritdoc cref="IFileService" />
@ -8,7 +10,7 @@ public sealed class FileService(IOptions<UploadOptions> uploadOptions, MinioHelp
/// <exception cref="NetAdminInvalidOperationException">文件不能为空</exception> /// <exception cref="NetAdminInvalidOperationException">文件不能为空</exception>
/// <exception cref="NetAdminInvalidOperationException">允许上传的文件格式</exception> /// <exception cref="NetAdminInvalidOperationException">允许上传的文件格式</exception>
/// <exception cref="NetAdminInvalidOperationException">允许的文件大小</exception> /// <exception cref="NetAdminInvalidOperationException">允许的文件大小</exception>
public async Task<string> UploadAsync(IFormFile file) public async Task<UploadFileRsp> UploadAsync(IFormFile file)
{ {
if (file == null || file.Length < 1) { if (file == null || file.Length < 1) {
throw new NetAdminInvalidOperationException(Ln.); throw new NetAdminInvalidOperationException(Ln.);
@ -22,9 +24,9 @@ public sealed class FileService(IOptions<UploadOptions> uploadOptions, MinioHelp
throw new NetAdminInvalidOperationException($"{Ln.允许的文件大小} {uploadOptions.Value.MaxSize}"); throw new NetAdminInvalidOperationException($"{Ln.允许的文件大小} {uploadOptions.Value.MaxSize}");
} }
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}"; var objectName = $"{UserToken.Id}/{file.FileName}";
var objectName = $"{UserToken.Id}/{fileName}";
await using var fs = file.OpenReadStream(); await using var fs = file.OpenReadStream();
return await minioHelper.UploadAsync(objectName, fs, file.ContentType, file.Length).ConfigureAwait(false); var (fileName, url) = await minioHelper.UploadAsync(objectName, fs, file.ContentType, file.Length).ConfigureAwait(false);
return new UploadFileRsp { FileName = fileName, Url = url };
} }
} }

View File

@ -97,7 +97,7 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
#if DBTYPE_SQLSERVER #if DBTYPE_SQLSERVER
return (await update.ExecuteUpdatedAsync().ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryJobRsp>(); return (await update.ExecuteUpdatedAsync().ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryJobRsp>();
#else #else
return await update.ExecuteAffrowsAsync().ConfigureAwait(false) <= 0 return await update.ExecuteEffectsAsync().ConfigureAwait(false) <= 0
? null ? null
: await GetAsync(new QueryJobReq { Id = req.Id }).ConfigureAwait(false); : await GetAsync(new QueryJobReq { Id = req.Id }).ConfigureAwait(false);
#endif #endif

View File

@ -57,7 +57,7 @@ public sealed class MenuService(BasicRepository<Sys_Menu, long> rpo, IUserServic
{ {
req.ThrowIfInvalid(); req.ThrowIfInvalid();
var ret = await Rpo.DeleteAsync(a => a.Id == req.Id).ConfigureAwait(false); var ret = await Rpo.DeleteAsync(a => a.Id == req.Id).ConfigureAwait(false);
_ = await Rpo.Orm.Delete<Sys_RoleMenu>().Where(a => a.MenuId == req.Id).ExecuteAffrowsAsync().ConfigureAwait(false); _ = await Rpo.Orm.Delete<Sys_RoleMenu>().Where(a => a.MenuId == req.Id).ExecuteEffectsAsync().ConfigureAwait(false);
return ret; return ret;
} }
@ -129,7 +129,7 @@ public sealed class MenuService(BasicRepository<Sys_Menu, long> rpo, IUserServic
private ISelect<Sys_Menu> QueryInternal(QueryReq<QueryMenuReq> req) private ISelect<Sys_Menu> QueryInternal(QueryReq<QueryMenuReq> req)
{ {
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter); var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
#pragma warning disable IDE0072
return req.Order switch { return req.Order switch {
Orders.None => ret Orders.None => ret
, Orders.Random => ret.OrderByRandom() , Orders.Random => ret.OrderByRandom()
@ -138,6 +138,5 @@ public sealed class MenuService(BasicRepository<Sys_Menu, long> rpo, IUserServic
.OrderBy(a => a.Name) .OrderBy(a => a.Name)
.OrderBy(a => a.Id) .OrderBy(a => a.Id)
}; };
#pragma warning restore IDE0072
} }
} }

Some files were not shown because too many files have changed in this diff Show More