!92 feat(#I4M1N3): 增加 Blazor 工程准备集成 BootstrapBlazor 组件库

* chore: 更新过滤解决方案文件
* refactor: 重新整理项目结构
* refactor: 改用 Update 方法
* refactor: 代码重构
* chore: 移除不使用的组件
* chore: 更新数据服务
* wip: 临时提交
* chore: 首页更新路由
* chore: 增加过滤项目文件
* feat: 更新菜单组件
* refactor: 移除不用的组件
* feat: 增加 BootstrapAppContext 服务
* refactor: 移除命名空间
* !91 feat(#I4LVUZ): 增加用户维护界面
* !90 feat(#I4LVUW): 增加字典表维护页面
* feat: 初始化 Blazor 版本
This commit is contained in:
Argo 2021-12-10 13:36:08 +00:00
parent 5c3be3a19f
commit 4e4a6a61e0
851 changed files with 2539 additions and 100 deletions

View File

@ -0,0 +1,11 @@
{
"solution": {
"path": "BootstrapAdmin.sln",
"projects": [
"src\\blazor\\admin\\Bootstrap.Admin.Blazor.DataAccess\\Bootstrap.Admin.Blazor.DataAccess.csproj",
"src\\blazor\\admin\\Bootstrap.Admin.Blazor\\Bootstrap.Admin.Blazor.csproj",
"src\\mvc\\admin\\Bootstrap.Admin\\Bootstrap.Admin.csproj",
"src\\mvc\\admin\\Bootstrap.DataAccess\\Bootstrap.DataAccess.csproj"
]
}
}

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29215.179
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLServer", "SQLServer", "{87319AF5-7C40-4362-B67C-35F9DD737DB4}"
ProjectSection(SolutionItems) = preProject
@ -10,15 +10,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLServer", "SQLServer", "{
db\SqlServer\Install.sql = db\SqlServer\Install.sql
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Admin", "src\admin\Bootstrap.Admin\Bootstrap.Admin.csproj", "{7B2B7043-3CB2-4C5A-BDF2-8C47F1A5471A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Admin", "src\mvc\admin\Bootstrap.Admin\Bootstrap.Admin.csproj", "{7B2B7043-3CB2-4C5A-BDF2-8C47F1A5471A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "db", "db", "{586410F2-C1F0-47CD-AB28-2CF506DED2C8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client", "src\client\Bootstrap.Client\Bootstrap.Client.csproj", "{C82A6E45-AB90-43D1-8429-5CBE953D8151}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client", "src\mvc\client\Bootstrap.Client\Bootstrap.Client.csproj", "{C82A6E45-AB90-43D1-8429-5CBE953D8151}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess", "src\admin\Bootstrap.DataAccess\Bootstrap.DataAccess.csproj", "{8D62BE79-BE13-43C8-969B-C9B00B3C84B7}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess", "src\mvc\admin\Bootstrap.DataAccess\Bootstrap.DataAccess.csproj", "{8D62BE79-BE13-43C8-969B-C9B00B3C84B7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLite", "SQLite", "{523515EC-2AD7-4282-9AF4-9D20371183B0}"
ProjectSection(SolutionItems) = preProject
@ -26,7 +26,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLite", "SQLite", "{523515
db\SQLite\Install.sql = db\SQLite\Install.sql
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess.MongoDB", "src\admin\Bootstrap.DataAccess.MongoDB\Bootstrap.DataAccess.MongoDB.csproj", "{8336F096-4B4A-4710-A1FA-0F5E44CD8D26}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess.MongoDB", "src\mvc\admin\Bootstrap.DataAccess.MongoDB\Bootstrap.DataAccess.MongoDB.csproj", "{8336F096-4B4A-4710-A1FA-0F5E44CD8D26}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MongoDB", "MongoDB", "{A06A0AD8-A246-4329-B024-7174AE4A3EDE}"
ProjectSection(SolutionItems) = preProject
@ -57,9 +57,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Postgresql", "Postgresql",
db\Postgresql\install.sql = db\Postgresql\install.sql
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess", "src\client\Bootstrap.Client.DataAccess\Bootstrap.Client.DataAccess.csproj", "{843811A2-FE49-410F-BF9F-9F1FB14A1DEE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess", "src\mvc\client\Bootstrap.Client.DataAccess\Bootstrap.Client.DataAccess.csproj", "{843811A2-FE49-410F-BF9F-9F1FB14A1DEE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess.MongoDB", "src\client\Bootstrap.Client.DataAccess.MongoDB\Bootstrap.Client.DataAccess.MongoDB.csproj", "{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess.MongoDB", "src\mvc\client\Bootstrap.Client.DataAccess.MongoDB\Bootstrap.Client.DataAccess.MongoDB.csproj", "{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6AD32A76-F3AA-423E-96EA-E5CC679934D1}"
EndProject
@ -74,9 +74,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{E057452E-0
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{85574E7C-7D58-4135-AB4B-76678552D271}"
ProjectSection(SolutionItems) = preProject
src\admin\Bootstrap.Admin\Dockerfile = src\admin\Bootstrap.Admin\Dockerfile
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "srcipts", "srcipts", "{72C103DB-E1D3-449F-97C2-DF12CA111FD4}"
EndProject
@ -130,9 +127,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "git", "git", "{64EACBD1-23D
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "blazor", "blazor", "{DAE3826B-AAAB-468A-9A06-2F56EF5C0767}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.Blazor", "src\blazor\Bootstrap.Client.Blazor\Bootstrap.Client.Blazor.csproj", "{90BC5C25-0F93-4CDE-833C-3D8243E19D3B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.Blazor", "src\blazor\client\Bootstrap.Client.Blazor\Bootstrap.Client.Blazor.csproj", "{90BC5C25-0F93-4CDE-833C-3D8243E19D3B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.Blazor.Shared", "src\blazor\Bootstrap.Client.Blazor.Shared\Bootstrap.Client.Blazor.Shared.csproj", "{B306BD58-1C73-40F2-86F7-E1763344007B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.Blazor.Shared", "src\blazor\client\Bootstrap.Client.Blazor.Shared\Bootstrap.Client.Blazor.Shared.csproj", "{B306BD58-1C73-40F2-86F7-E1763344007B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "github", "github", "{C07631B9-5E5E-417A-9A16-3C88956D574E}"
ProjectSection(SolutionItems) = preProject
@ -140,6 +137,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "github", "github", "{C07631
.github\workflows\docker.yml = .github\workflows\docker.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Admin.Blazor", "src\blazor\admin\Bootstrap.Admin.Blazor\Bootstrap.Admin.Blazor.csproj", "{485C1B75-7E3C-4AFC-8A91-2347FFEC1E96}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mvc", "mvc", "{C996F427-DA93-49D6-9804-4E665D195FC2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin", "admin", "{45ADEF9B-C8BD-4224-9E12-F6716E85A22C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{55A2459A-6BDE-4493-B2C0-5BE1673E99EE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bootstrap.Admin.Blazor.DataAccess", "src\blazor\admin\Bootstrap.Admin.Blazor.DataAccess\Bootstrap.Admin.Blazor.DataAccess.csproj", "{75730767-A53A-4CFB-BACB-B90401288FA6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -182,6 +189,14 @@ Global
{B306BD58-1C73-40F2-86F7-E1763344007B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B306BD58-1C73-40F2-86F7-E1763344007B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B306BD58-1C73-40F2-86F7-E1763344007B}.Release|Any CPU.Build.0 = Release|Any CPU
{485C1B75-7E3C-4AFC-8A91-2347FFEC1E96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{485C1B75-7E3C-4AFC-8A91-2347FFEC1E96}.Debug|Any CPU.Build.0 = Debug|Any CPU
{485C1B75-7E3C-4AFC-8A91-2347FFEC1E96}.Release|Any CPU.ActiveCfg = Release|Any CPU
{485C1B75-7E3C-4AFC-8A91-2347FFEC1E96}.Release|Any CPU.Build.0 = Release|Any CPU
{75730767-A53A-4CFB-BACB-B90401288FA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75730767-A53A-4CFB-BACB-B90401288FA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75730767-A53A-4CFB-BACB-B90401288FA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75730767-A53A-4CFB-BACB-B90401288FA6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -190,7 +205,7 @@ Global
{87319AF5-7C40-4362-B67C-35F9DD737DB4} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
{7B2B7043-3CB2-4C5A-BDF2-8C47F1A5471A} = {E03B7391-B52F-4449-B400-5CD9DE01F085}
{C82A6E45-AB90-43D1-8429-5CBE953D8151} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}
{C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
{C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0} = {C996F427-DA93-49D6-9804-4E665D195FC2}
{8D62BE79-BE13-43C8-969B-C9B00B3C84B7} = {E03B7391-B52F-4449-B400-5CD9DE01F085}
{523515EC-2AD7-4282-9AF4-9D20371183B0} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
{8336F096-4B4A-4710-A1FA-0F5E44CD8D26} = {E03B7391-B52F-4449-B400-5CD9DE01F085}
@ -200,7 +215,7 @@ Global
{6F61C2AC-84D4-48A9-8A48-680657CC8175} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
{843811A2-FE49-410F-BF9F-9F1FB14A1DEE} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}
{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}
{E03B7391-B52F-4449-B400-5CD9DE01F085} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
{E03B7391-B52F-4449-B400-5CD9DE01F085} = {C996F427-DA93-49D6-9804-4E665D195FC2}
{C6F2DCA0-7941-4C28-9328-2D495F5DCB00} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
{FDCFC3E3-14CF-40B2-9FE5-5BC239AAC110} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
{5F732D4E-133B-4DA6-811B-C369CDC3FB89} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
@ -208,8 +223,13 @@ Global
{41E078CA-F005-4B66-B440-FD7EB731AD61} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
{64EACBD1-23DD-4168-BEED-55D47DB1A8BB} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
{DAE3826B-AAAB-468A-9A06-2F56EF5C0767} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
{90BC5C25-0F93-4CDE-833C-3D8243E19D3B} = {DAE3826B-AAAB-468A-9A06-2F56EF5C0767}
{B306BD58-1C73-40F2-86F7-E1763344007B} = {DAE3826B-AAAB-468A-9A06-2F56EF5C0767}
{90BC5C25-0F93-4CDE-833C-3D8243E19D3B} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
{B306BD58-1C73-40F2-86F7-E1763344007B} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
{485C1B75-7E3C-4AFC-8A91-2347FFEC1E96} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
{C996F427-DA93-49D6-9804-4E665D195FC2} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
{45ADEF9B-C8BD-4224-9E12-F6716E85A22C} = {DAE3826B-AAAB-468A-9A06-2F56EF5C0767}
{55A2459A-6BDE-4493-B2C0-5BE1673E99EE} = {DAE3826B-AAAB-468A-9A06-2F56EF5C0767}
{75730767-A53A-4CFB-BACB-B90401288FA6} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {221EAE38-5F75-4391-9A48-E462A9F3B8FC}

View File

@ -11,17 +11,17 @@
<Target Condition=" $(IsWebProject) == true Or $(IsTestProject) == true" Name="PostBuild" AfterTargets="PostBuildEvent">
<Message Text="Copy lic file -> $(TargetDir)" Importance="high" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src\mvc\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src/mvc/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
</Target>
<Target Condition=" $(IsWebProject) == true " Name="PostPublish" AfterTargets="Publish">
<Message Text="Publish lic file -> $(PublishDir)" Importance="high" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\mvc\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/mvc/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
<Message Text="Publish db file -> $(PublishDir)" Importance="high" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\admin\Bootstrap.Admin\BootstrapAdmin.db" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/admin/Bootstrap.Admin/BootstrapAdmin.db" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\mvc\admin\Bootstrap.Admin\BootstrapAdmin.db" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/mvc/admin/Bootstrap.Admin/BootstrapAdmin.db" SkipUnchangedFiles="true" />
</Target>
</Project>

View File

@ -2,6 +2,10 @@
<Import Project="..\Directory.Build.props" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageProjectUrl>https://gitee.com/LongbowEnterprise/BootstrapAdmin</PackageProjectUrl>
<RepositoryUrl>https://gitee.com/LongbowEnterprise/BootstrapAdmin.git</RepositoryUrl>
@ -10,8 +14,4 @@
<DocumentationFile>$(MSBuildProjectName).xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="PetaPoco.Extensions" Version="5.2.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,38 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
using PetaPoco;
namespace Bootstrap.Admin.Blazor.DataAccess
{
/// <summary>
/// 字典配置项
/// </summary>
[TableName("Dicts")]
public class Dict
{
/// <summary>
/// 获得/设置 字典主键 数据库自增列
/// </summary>
public string? Id { get; set; }
/// <summary>
/// 获得/设置 字典分类
/// </summary>
public string Category { get; set; } = "";
/// <summary>
/// 获得/设置 字典名称
/// </summary>
public string Name { get; set; } = "";
/// <summary>
/// 获得/设置 字典字典值
/// </summary>
public string Code { get; set; } = "";
/// <summary>
/// 获得/设置 字典定义值 0 表示系统使用1 表示用户自定义 默认为 1
/// </summary>
public int Define { get; set; } = 1;
}
}

View File

@ -0,0 +1,11 @@
<BootstrapBlazorRoot>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<PageTitle>@Title</PageTitle>
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(NotFoundLayout)" />
</NotFound>
</Router>
</BootstrapBlazorRoot>

View File

@ -0,0 +1,27 @@
namespace Bootstrap.Admin.Blazor
{
/// <summary>
///
/// </summary>
public partial class App
{
/// <summary>
///
/// </summary>
public string? Title { get; set; }
[Inject]
[NotNull]
private BootstrapAppContext? AppContext { get; set; }
/// <summary>
///
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
//Title = DictHelper.RetrieveWebTitle(AppContext.AppId);
}
}
}

View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.1.1-beta01" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Bootstrap.Admin.Blazor.DataAccess\Bootstrap.Admin.Blazor.DataAccess.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Bootstrap.Admin.Blazor.Models" />
<Using Include="Bootstrap.Admin.Blazor.Services" />
<Using Include="BootstrapBlazor.Components" />
<Using Include="Microsoft.AspNetCore.Components" />
<Using Include="System.Diagnostics.CodeAnalysis" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,18 @@
@typeparam TItem
<Table TItem="TItem" IsBordered="true" IsStriped="true" IsMultipleSelect="true"
IsPagination="IsPagination" PageItemsSource="PageItemsSource"
UseInjectDataService="true" DataService="DataService" OnQueryAsync="OnQueryAsync!"
ShowToolbar="true" ShowExtendButtons="true" ShowSearch="true"
ShowCardView="true" ShowColumnList="true"
CustomerSearchModel="@TableSearchModel">
<TableToolbarTemplate>
@TableToolbarTemplate
</TableToolbarTemplate>
<TableColumns>
@ColumnsTemplete(context)
</TableColumns>
<CustomerSearchTemplate>
@CustomerSearchTemplate(context)
</CustomerSearchTemplate>
</Table>

View File

@ -0,0 +1,60 @@
namespace Bootstrap.Admin.Blazor.Components
{
/// <summary>
///
/// </summary>
[CascadingTypeParameter(nameof(TItem))]
public partial class BlazorTable<TItem> where TItem : class, new()
{
/// <summary>
///
/// </summary>
[Parameter]
public IEnumerable<int>? PageItemsSource { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
[Parameter]
public RenderFragment<TItem>? ColumnsTemplete { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
[Parameter]
public RenderFragment<ITableSearchModel>? CustomerSearchTemplate { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
[Parameter]
public RenderFragment? TableToolbarTemplate { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public bool IsPagination { get; set; } = true;
/// <summary>
///
/// </summary>
[Parameter]
public ITableSearchModel? TableSearchModel { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public IDataService<TItem>? DataService { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public Func<QueryPageOptions, Task<QueryData<TItem>>>? OnQueryAsync { get; set; }
}
}

View File

@ -0,0 +1,27 @@
<div class="row g-3">
<div class="col-sm-6 col-md-6">
<BootstrapInput @bind-Value="Value.Name" ShowLabel="true" DisplayText="字典名称" />
</div>
<div class="col-sm-6 col-md-6">
<BootstrapInput @bind-Value="Value.Category" ShowLabel="true" DisplayText="字典标签" />
</div>
<div class="col-sm-6 col-md-6">
<Select Items="@Items" @bind-Value="Value.Define" ShowLabel="true" DisplayText="字典类型"></Select>
</div>
</div>
@code {
private IEnumerable<SelectedItem>? Items { get; set; } = new List<SelectedItem>()
{
new SelectedItem("","全部"),
new SelectedItem("0","系统使用"),
new SelectedItem("1","自定义"),
};
[Parameter]
[NotNull]
public DictsSearchModel? Value { get; set; }
[Parameter]
public EventCallback<DictsSearchModel> ValueChanged { get; set; }
}

View File

@ -0,0 +1,238 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using System.Security.Claims;
namespace Bootstrap.Admin.Controllers
{
///// <summary>
///// Account controller.
///// </summary>
//[AllowAnonymous]
//[AutoValidateAntiforgeryToken]
//public class AccountController : Controller
//{
//private const string MobileSchema = "Mobile";
///// <summary>
///// 系统锁屏界面
///// </summary>
///// <returns></returns>
//[HttpGet]
//public async Task<ActionResult> Lock()
//{
// if (!User.Identity!.IsAuthenticated) return Login();
// var authenticationType = User.Identity.AuthenticationType;
// await HttpContext.SignOutAsync();
// var urlReferrer = Request.Headers["Referer"].FirstOrDefault();
// if (urlReferrer?.Contains("/Pages", StringComparison.OrdinalIgnoreCase) ?? false) urlReferrer = "/Pages";
// return View(new LockModel(User.Identity.Name)
// {
// AuthenticationType = authenticationType,
// ReturnUrl = WebUtility.UrlEncode(string.IsNullOrEmpty(urlReferrer) ? CookieAuthenticationDefaults.LoginPath.Value : urlReferrer)
// });
//}
///// <summary>
///// 系统锁屏界面
///// </summary>
///// <param name="provider"></param>
///// <param name="userName"></param>
///// <param name="password"></param>
///// <param name="authType"></param>
///// <returns></returns>
//[HttpPost]
//[IgnoreAntiforgeryToken]
//public Task<IActionResult> Lock([FromServices] ISMSProvider provider, string userName, string password, string authType)
//{
// // 根据不同的登陆方式
// Task<IActionResult> ret;
// if (authType == MobileSchema) ret = Mobile(provider, userName, password);
// else ret = Login(userName, password, string.Empty);
// return ret;
//}
///// <summary>
///// 系统登录方法
///// </summary>
///// <param name="appId"></param>
///// <param name="view"></param>
///// <returns></returns>
//[HttpGet]
//public ActionResult Login([FromQuery] string? appId = null, [FromQuery] string view = "")
//{
// if (DictHelper.RetrieveSystemModel())
// {
// ViewBag.UserName = "Admin";
// ViewBag.Password = "123789";
// }
// return User.Identity!.IsAuthenticated ? (ActionResult)Redirect("~/Home/Index") : LoginView(view, new LoginModel(appId));
//}
//private ViewResult LoginView(string view, LoginModel model)
//{
// if (string.IsNullOrEmpty(view))
// {
// // retrieve login view from db
// view = DictHelper.RetrieveLoginView();
// }
// return View(view, model);
//}
///// <summary>
///// 短信验证登陆方法
///// </summary>
///// <param name="provider"></param>
///// <param name="phone"></param>
///// <param name="code"></param>
///// <returns></returns>
//[HttpPost()]
//public async Task<IActionResult> Mobile([FromServices] ISMSProvider provider, string phone, string code)
//{
// if (string.IsNullOrEmpty(phone) || string.IsNullOrEmpty(code)) return RedirectLogin();
// var auth = provider.Validate(phone, code);
// await HttpContext.Log(phone, auth);
// if (auth)
// {
// var user = UserHelper.Retrieves().FirstOrDefault(u => u.UserName == phone);
// if (user == null)
// {
// user = new User()
// {
// ApprovedBy = "Mobile",
// ApprovedTime = DateTime.Now,
// DisplayName = "手机用户",
// UserName = phone,
// Password = code,
// Icon = "default.jpg",
// Description = "手机用户",
// App = provider.Options.App
// };
// if (UserHelper.Save(user) && !string.IsNullOrEmpty(user.Id))
// {
// // 根据配置文件设置默认角色
// var roles = RoleHelper.Retrieves().Where(r => provider.Options.Roles.Any(rl => rl.Equals(r.RoleName, StringComparison.OrdinalIgnoreCase))).Select(r => r.Id!);
// RoleHelper.SaveByUserId(user.Id, roles);
// }
// }
// }
// return auth ? await SignInAsync(phone, true, MobileSchema) : RedirectLogin();
//}
//private IActionResult RedirectLogin()
//{
// var query = Request.Query.Aggregate(new Dictionary<string, string?>(), (d, v) =>
// {
// d.Add(v.Key, v.Value.ToString());
// return d;
// });
// return Redirect(QueryHelpers.AddQueryString(Request.PathBase + CookieAuthenticationDefaults.LoginPath, query));
//}
///// <summary>
///// Login the specified userName, password and remember.
///// </summary>
///// <returns>The login.</returns>
///// <param name="userName">User name.</param>
///// <param name="password">Password.</param>
///// <param name="remember">Remember.</param>
//[HttpPost]
//public async Task<IActionResult> Login(string userName, string password, string remember)
//{
// if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password)) return RedirectLogin();
// var auth = UserHelper.Authenticate(userName, password);
// await HttpContext.Log(userName, auth);
// return auth ? await SignInAsync(userName, remember == "true") : LoginView("", new LoginModel() { AuthFailed = true });
//}
//private async Task<IActionResult> SignInAsync(string userName, bool persistent, string authenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme)
//{
// var identity = new ClaimsIdentity(authenticationScheme);
// identity.AddClaim(new Claim(ClaimTypes.Name, userName));
// await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties { ExpiresUtc = DateTimeOffset.Now.AddDays(DictHelper.RetrieveCookieExpiresPeriod()), IsPersistent = persistent });
// // redirect origin url
// var originUrl = Request.Query[CookieAuthenticationDefaults.ReturnUrlParameter].FirstOrDefault() ?? "~/Home/Index";
// return Redirect(originUrl);
//}
///// <summary>
///// Logout this instance.
///// </summary>
///// <param name="appId"></param>
///// <returns>The logout.</returns>
//[HttpGet]
//public async Task<IActionResult> Logout([FromQuery] string appId)
//{
// await HttpContext.SignOutAsync();
// return Redirect(QueryHelpers.AddQueryString(Request.PathBase + CookieAuthenticationDefaults.LoginPath, "AppId", appId ?? BootstrapAppContext.AppId));
//}
///// <summary>
///// Accesses the denied.
///// </summary>
///// <returns>The denied.</returns>
//[ResponseCache(Duration = 600)]
//[HttpGet]
//public ActionResult AccessDenied() => View("Error", ErrorModel.CreateById(403));
///// <summary>
///// Gitee 认证
///// </summary>
///// <returns></returns>
//[HttpGet]
//public IActionResult Gitee([FromServices] IConfiguration config)
//{
// var enabled = config.GetValue($"{nameof(GiteeOptions)}:Enabled", false);
// return Challenge(enabled ? GiteeDefaults.AuthenticationScheme : CookieAuthenticationDefaults.AuthenticationScheme);
//}
///// <summary>
///// GitHub 认证
///// </summary>
///// <returns></returns>
//[HttpGet]
//public IActionResult GitHub([FromServices] IConfiguration config)
//{
// var enabled = config.GetValue($"{nameof(GitHubOptions)}:Enabled", false);
// return Challenge(enabled ? GitHubDefaults.AuthenticationScheme : CookieAuthenticationDefaults.AuthenticationScheme);
//}
///// <summary>
///// Tencent 认证
///// </summary>
///// <returns></returns>
//[HttpGet]
//public IActionResult Tencent([FromServices] IConfiguration config)
//{
// var enabled = config.GetValue($"{nameof(TencentOptions)}:Enabled", false);
// return Challenge(enabled ? TencentDefaults.AuthenticationScheme : CookieAuthenticationDefaults.AuthenticationScheme);
//}
///// <summary>
///// Alipay 认证
///// </summary>
///// <returns></returns>
//[HttpGet]
//public IActionResult Alipay([FromServices] IConfiguration config)
//{
// var enabled = config.GetValue($"{nameof(AlipayOptions)}:Enabled", false);
// return Challenge(enabled ? AlipayDefaults.AuthenticationScheme : CookieAuthenticationDefaults.AuthenticationScheme);
//}
///// <summary>
///// WeChat 认证
///// </summary>
///// <returns></returns>
//[HttpGet]
//public IActionResult WeChat([FromServices] IConfiguration config)
//{
// var enabled = config.GetValue($"{nameof(WeChatOptions)}:Enabled", false);
// return Challenge(enabled ? WeChatDefaults.AuthenticationScheme : CookieAuthenticationDefaults.AuthenticationScheme);
//}
//}
}

View File

@ -0,0 +1,127 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/
using PetaPoco;
using System.Linq.Expressions;
using System.Reflection;
namespace BootstrapBlazor.DataAcces.PetaPoco
{
/// <summary>
///
/// </summary>
public static class DatabaseExtensions
{
/// <summary>
///
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <returns></returns>
public static Task<List<TModel>> FetchAsync<TModel>(this IDatabase db, IEnumerable<IFilterAction> where, string? sortName = null, SortOrder sortOrder = SortOrder.Unset)
{
var exp = where.GetFilterLambda<TModel>();
var sql = new Sql();
AnalysisExpression(exp, db, sql);
if (!string.IsNullOrEmpty(sortName) && sortOrder != SortOrder.Unset)
{
sql.OrderBy(sortOrder == SortOrder.Asc ? sortName : $"{sortName} desc");
}
return db.FetchAsync<TModel>(sql);
}
/// <summary>
///
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <returns></returns>
public static Task<Page<TModel>> PageAsync<TModel>(this IDatabase db, long pageIndex, long pageItems, IEnumerable<IFilterAction> where, string? sortName = null, SortOrder sortOrder = SortOrder.Unset)
{
var exp = where.GetFilterLambda<TModel>();
var sql = new Sql();
AnalysisExpression(exp, db, sql);
if (!string.IsNullOrEmpty(sortName) && sortOrder != SortOrder.Unset)
{
sql.OrderBy(sortOrder == SortOrder.Asc ? sortName : $"{sortName} desc");
}
return db.PageAsync<TModel>(pageIndex, pageItems, sql);
}
private static void AnalysisExpression(Expression expression, IDatabase db, Sql sql)
{
switch (expression.NodeType)
{
case ExpressionType.Lambda:
if (expression is LambdaExpression exp)
{
AnalysisExpression(exp.Body, db, sql);
}
break;
case ExpressionType.AndAlso:
if (expression is BinaryExpression andExp)
{
AnalysisExpression(andExp.Left, db, sql);
AnalysisExpression(andExp.Right, db, sql);
}
break;
case ExpressionType.Call:
if (expression is MethodCallExpression callExp)
{
if (callExp.Method.Name == "Contains")
{
if (callExp.Object is MemberExpression callLeft)
{
var callColName = GetColumnName(callLeft.Member) ?? callLeft.Member.Name;
var p = (callExp.Arguments[0] as ConstantExpression)?.Value;
if (p != null)
{
sql.Where($"{db.Provider.EscapeSqlIdentifier(callColName)} like @0", $"%{p}%");
}
}
}
}
break;
case ExpressionType.Equal:
case ExpressionType.NotEqual:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
var binaryExp = (expression as BinaryExpression)!;
var left = (binaryExp.Left as MemberExpression)!;
// 查找 PetaPoco.Column 标签
var columnName = GetColumnName(left.Member) ?? left.Member.Name;
// 查找操作符右侧
var right = (binaryExp.Right as ConstantExpression)!;
var v = right.Value;
if (v != null)
{
var operatorExp = GetOperatorExpression(expression);
sql.Where($"{db.Provider.EscapeSqlIdentifier(columnName)} {operatorExp} @0", v);
}
break;
}
}
private static string? GetColumnName(MemberInfo member) => member.CustomAttributes
.FirstOrDefault(i => i.AttributeType == typeof(ColumnAttribute))?.NamedArguments
.FirstOrDefault(i => i.MemberName == "Name").TypedValue.Value?.ToString();
private static string GetOperatorExpression(Expression expression) => expression.NodeType switch
{
ExpressionType.Equal => "=",
ExpressionType.NotEqual => "!=",
ExpressionType.GreaterThan => ">",
ExpressionType.GreaterThanOrEqual => ">=",
ExpressionType.LessThan => "<",
ExpressionType.LessThanOrEqual => "<=",
_ => ""
};
}
}

View File

@ -0,0 +1,76 @@
using BootstrapBlazor.DataAcces.PetaPoco;
using System.Text;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
///
/// </summary>
public static class ServicesExtensions
{
/// <summary>
/// 添加示例后台任务
/// </summary>
/// <param name="services"></param>
public static IServiceCollection AddBootstrapBlazorAdminServices(this IServiceCollection services)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
// 增加后台任务服务
//services.AddTaskServices();
//services.AddLogging(logging => logging.AddFileLogger().AddCloudLogger().AddDBLogger(ExceptionsHelper.Log));
services.AddCors();
services.AddResponseCompression();
//services.AddCodePageProvider();
//services.AddCacheManager();
//services.AddDbAdapter();
//services.AddIPLocator(DictHelper.ConfigIPLocator);
//services.AddOnlineUsers();
//services.AddSignalR().AddJsonProtocol(op => op.PayloadSerializerOptions.AddDefaultConverters());
//services.AddBootstrapAdminAuthentication(Configuration)
// .AddGitee(OAuthHelper.Configure)
// .AddGitHub(OAuthHelper.Configure)
// .AddTencent(OAuthHelper.Configure)
// .AddAlipay(OAuthHelper.Configure);
//services.AddAuthorization(options => options.DefaultPolicy = new AuthorizationPolicyBuilder().RequireBootstrapAdminAuthorizate().Build());
//services.AddButtonAuthorization(MenuHelper.AuthorizateButtons);
//services.AddBootstrapAdminBackgroundTask();
//services.AddHttpClient<GiteeHttpClient>();
//services.AddAdminHealthChecks();
//services.AddSMSProvider();
//services.AddSwagger();
//services.AddApiVersioning(option =>
//{
// option.DefaultApiVersion = new ApiVersion(1, 0);
// option.ReportApiVersions = true;
// option.AssumeDefaultVersionWhenUnspecified = true;
// option.ApiVersionReader = ApiVersionReader.Combine(new HeaderApiVersionReader("api-version"), new QueryStringApiVersionReader("api-version"));
//});
//services.AddExceptionless();
//services.AddControllersWithViews(options =>
//{
// options.Filters.Add<BootstrapAdminAuthorizeFilter>();
// options.Filters.Add<ExceptionFilter>();
// options.Filters.Add<SignalRExceptionFilter<SignalRHub>>();
//}).AddJsonOptions(op => op.JsonSerializerOptions.AddDefaultConverters());
//services.AddControllersWithViews().AddJsonOptions(op => op.JsonSerializerOptions.AddDefaultConverters());
// 增加 BootstrapBlazor 组件
services.AddBootstrapBlazor();
// 增加数据服务
services.AddSingleton(typeof(IDataService<>), typeof(DefaultDataService<>));
// 增加 BootstrapApp 上下文服务
services.AddSingleton<BootstrapAppContext>();
// 增加数据服务
services.AddSingleton<IBootstrapMenuService, IBootstrapMenuService>();
return services;
}
}
}

View File

@ -0,0 +1,62 @@
using Bootstrap.Admin.Blazor.DataAccess;
namespace Bootstrap.Admin.Blazor.Models
{
/// <summary>
///
/// </summary>
public class DictsSearchModel : ITableSearchModel
{
/// <summary>
///
/// </summary>
public string? Category { get; set; }
/// <summary>
///
/// </summary>
public int? Define { get; set; }
/// <summary>
///
/// </summary>
public string? Name { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public IEnumerable<IFilterAction> GetSearchs()
{
var ret = new List<IFilterAction>();
if (!string.IsNullOrEmpty(Name))
{
ret.Add(new SearchFilterAction(nameof(Dict.Name), Name));
}
if (!string.IsNullOrEmpty(Category))
{
ret.Add(new SearchFilterAction(nameof(Dict.Category), Category));
}
if (Define.HasValue)
{
ret.Add(new SearchFilterAction(nameof(Dict.Define), Define, FilterAction.Equal));
}
return ret;
}
/// <summary>
///
/// </summary>
/// <exception cref="NotImplementedException"></exception>
public void Reset()
{
Category = null;
Name = null;
Define = null;
}
}
}

View File

@ -0,0 +1,27 @@
namespace Bootstrap.Admin.Blazor.Models
{
/// <summary>
/// 登陆页面 Model
/// </summary>
public class LoginModel
{
///// <summary>
///// 默认构造函数
///// </summary>
///// <param name="appId"></param>
//public LoginModel(string? appId = null)
//{
// //ImageLibUrl = DictHelper.RetrieveImagesLibUrl();
//}
/// <summary>
/// 验证码图床地址
/// </summary>
public string? ImageLibUrl { get; protected set; }
/// <summary>
/// 是否登录认证失败 为真时客户端弹出滑块验证码
/// </summary>
public bool AuthFailed { get; set; }
}
}

View File

@ -0,0 +1,22 @@
@page "/admin/dicts"
<BlazorTable TItem="Dict" IsPagination="false" TableSearchModel="@DictsSearchModel">
<ColumnsTemplete>
<TableColumn @bind-Field="context.Category" Text="字典标签" Filterable="true" Searchable="true" Sortable="true"></TableColumn>
<TableColumn @bind-Field="context.Name" Text="字典名称" Filterable="true" Searchable="true" Sortable="true"></TableColumn>
<TableColumn @bind-Field="context.Code" Text="字典代码" Filterable="true" Searchable="true" Sortable="true"></TableColumn>
<TableColumn @bind-Field="context.Define" Text="字典类型" Filterable="true" Searchable="true" Sortable="true" Lookup="@LookUp">
<EditTemplate Context="v">
<div class="col-sm-6 col-md-6">
<Select Items="@EditDefines" @bind-Value="v!.Define" DisplayText="字典类型"></Select>
</div>
</EditTemplate>
</TableColumn>
</ColumnsTemplete>
<CustomerSearchTemplate>
@if (context is DictsSearchModel searchModel)
{
<DictSearch @bind-Value="@searchModel"></DictSearch>
}
</CustomerSearchTemplate>
</BlazorTable>

View File

@ -0,0 +1,30 @@
namespace Bootstrap.Admin.Blazor.Pages.Admin
{
/// <summary>
///
/// </summary>
public partial class Dicts
{
private IEnumerable<SelectedItem>? EditDefines { get; set; }
private IEnumerable<SelectedItem>? LookUp { get; set; }
private ITableSearchModel? DictsSearchModel { get; set; } = new DictsSearchModel();
/// <summary>
///
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
EditDefines = new List<SelectedItem>()
{
new SelectedItem("0","系统使用"),
new SelectedItem("1","自定义"),
};
LookUp = EditDefines;
}
}
}

View File

@ -0,0 +1,6 @@
@page "/"
@page "/admin"
@page "/admin/index"
@attribute [TabItemOption(Text = "后台管理")]
<h4>欢迎使用后台管理</h4>

View File

@ -0,0 +1,17 @@
@page "/admin/users"
@*<BlazorTable TItem="User">
<TableToolbarTemplate>
<TableToolbarButton TItem="User" Color="Color.Info" Icon="fa fa-bank" Text="分配部门" OnClickCallback="OnAssignmentDept" />
<TableToolbarButton TItem="User" Color="Color.Warning" Icon="fa fa-sitemap" Text="分配角色" OnClickCallback="OnAssignmentRoles" />
</TableToolbarTemplate>
<ColumnsTemplete>
<TableColumn @bind-Field="@context.UserName" Text="登录名称" Sortable="true" Filterable="true" Searchable="true"></TableColumn>
<TableColumn @bind-Field="@context.DisplayName" Text="显示名称" Sortable="true" Filterable="true" Searchable="true"></TableColumn>
<TableColumn @bind-Field="@context.RegisterTime" Text="注册时间" Sortable="true" Filterable="true"></TableColumn>
<TableColumn @bind-Field="@context.ApprovedTime" Text="授权时间" Sortable="true" Filterable="true"></TableColumn>
<TableColumn @bind-Field="@context.ApprovedBy" Text="授权人" Sortable="true" Filterable="true"></TableColumn>
<TableColumn @bind-Field="@context.Description" Text="说明" Sortable="true" Filterable="true"></TableColumn>
</ColumnsTemplete>
</BlazorTable>
*@

View File

@ -0,0 +1,60 @@
using Task = System.Threading.Tasks.Task;
namespace Bootstrap.Admin.Blazor.Pages.Admin
{
/// <summary>
///
/// </summary>
public partial class Users
{
//[Inject]
//[NotNull]
//private DialogService? DialogService { get; set; }
//[Inject]
//[NotNull]
//private ToastService? ToastService { get; set; }
//private async Task OnAssignmentDept(IEnumerable<User> users)
//{
// if (users.Count() == 1)
// {
// var option = new DialogOption()
// {
// Title = "部门授权",
// BodyTemplate = BootstrapDynamicComponent.CreateComponent<CheckboxList<string>>(new Dictionary<string, object>
// {
// [nameof(CheckboxList<string>.Items)] = GroupHelper.Retrieves().Select(s => new SelectedItem(s.GroupCode, s.GroupName))
// }).Render()
// };
// await DialogService.Show(option);
// }
// else
// {
// await ToastService.Warning("部门授权", "请选择一个用户");
// }
//}
//private async Task OnAssignmentRoles(IEnumerable<User> users)
//{
// if (users.Count() != 0)
// {
// var option = new DialogOption()
// {
// Title = "分配角色",
// BodyTemplate = BootstrapDynamicComponent.CreateComponent<CheckboxList<string>>(new Dictionary<string, object>
// {
// [nameof(CheckboxList<string>.Items)] = RoleHelper.Retrieves().Select(s => new SelectedItem(s.Id!, s.RoleName) { Active = s.Checked == "" ? false : true })
// }).Render()
// };
// await DialogService.Show(option);
// }
// else
// {
// await ToastService.Warning("分配角色", "请选择一个用户");
// }
//}
}
}

View File

@ -0,0 +1 @@
@attribute [Authorize]

View File

@ -0,0 +1,3 @@
@page "/home"
@page "/home/index"
@attribute [TabItemOption(Text = "首页")]

View File

@ -0,0 +1,8 @@
@page "/"
@namespace Bootstrap.Admin.Blazor.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout";
}
<component type="typeof(App)" render-mode="ServerPrerendered" />

View File

@ -0,0 +1,42 @@
@using Microsoft.AspNetCore.Components.Web
@namespace Bootstrap.Admin.Blazor.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="~/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="~/favicon.ico" type="image/x-icon" />
<link rel="apple-touch-icon" href="~/favicon.png" />
<base href="~/" />
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css" rel="stylesheet">
<link href="_content/BootstrapBlazor/css/motronic.min.css" rel="stylesheet">
<link href="css/site.css" rel="stylesheet" />
<link href="css/motronic.css" rel="stylesheet" />
<link href="Bootstrap.Admin.Blazor.styles.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
<body>
@RenderBody()
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.server.js"></script>
<script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,30 @@
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
// 注入项目服务
builder.Services.AddBootstrapBlazorAdminServices();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
// 开启缓存中间件
//app.UseCacheManager();
// 开启 webapi
app.MapDefaultControllerRoute();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();

View File

@ -0,0 +1,28 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:24748",
"sslPort": 0
}
},
"profiles": {
"Bootstrap.Admin.Blazor": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5110",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,22 @@
namespace Bootstrap.Admin.Blazor.Services
{
/// <summary>
///
/// </summary>
public class BootstrapAppContext
{
/// <summary>
///
/// </summary>
public string AppId { get; }
/// <summary>
///
/// </summary>
/// <param name="configuration"></param>
public BootstrapAppContext(IConfiguration configuration)
{
AppId = configuration.GetValue("AppId", "demo");
}
}
}

View File

@ -0,0 +1,9 @@
namespace Bootstrap.Admin.Blazor.Services
{
/// <summary>
///
/// </summary>
public class BootstrapMenuService : IBootstrapMenuService
{
}
}

View File

@ -0,0 +1,91 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/
using PetaPoco;
using PetaPoco.Extensions;
using PetaPoco.Providers;
namespace BootstrapBlazor.DataAcces.PetaPoco
{
/// <summary>
/// PetaPoco ORM 的 IDataService 接口实现
/// </summary>
internal class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class, new()
{
private readonly IDatabase _db;
/// <summary>
/// 构造函数
/// </summary>
public DefaultDataService(IConfiguration configuration)
{
//TODO: 后期改造成自定适配
var connString = configuration.GetConnectionString("bb");
_db = new Database<SQLiteDatabaseProvider>(connString);
}
/// <summary>
/// 删除方法
/// </summary>
/// <param name="models"></param>
/// <returns></returns>
public override Task<bool> DeleteAsync(IEnumerable<TModel> models)
{
// 通过模型获取主键列数据
// 支持批量删除
_db.DeleteBatch(models);
return Task.FromResult(true);
}
/// <summary>
/// 保存方法
/// </summary>
/// <param name="model"></param>
/// <param name="changedType"></param>
/// <returns></returns>
public override async Task<bool> SaveAsync(TModel model, ItemChangedType changedType)
{
if (changedType == ItemChangedType.Add)
{
await _db.InsertAsync(model);
}
else
{
await _db.UpdateAsync(model);
}
return true;
}
/// <summary>
/// 查询方法
/// </summary>
/// <param name="option"></param>
/// <returns></returns>
public override async Task<QueryData<TModel>> QueryAsync(QueryPageOptions option)
{
var ret = new QueryData<TModel>()
{
IsSorted = true,
IsFiltered = true,
IsSearch = true
};
var filters = option.Filters.Concat(option.Searchs).Concat(option.CustomerSearchs);
if (option.IsPage)
{
var items = await _db.PageAsync<TModel>(option.PageIndex, option.PageItems, filters, option.SortName, option.SortOrder);
ret.TotalCount = Convert.ToInt32(items.TotalItems);
ret.Items = items.Items;
}
else
{
var items = await _db.FetchAsync<TModel>(filters, option.SortName, option.SortOrder);
ret.TotalCount = items.Count;
ret.Items = items;
}
return ret;
}
}
}

View File

@ -0,0 +1,9 @@
namespace Bootstrap.Admin.Blazor.Services
{
/// <summary>
///
/// </summary>
public interface IBootstrapMenuService
{
}
}

View File

@ -0,0 +1,33 @@
@inherits LayoutComponentBase
<Layout SideWidth="0" IsPage="true" IsFullSide="true" IsFixedHeader="true" IsFixedFooter="false"
ShowFooter="true" ShowGotoTop="true" ShowCollapseBar="true" Menus="@MenuItems"
UseTabSet="true" TabDefaultUrl="/admin/index">
<Header>
<span class="ms-3 flex-fill">Bootstrap of Blazor</span>
<img src="/images/Argo.png" class="layout-avatar-right" />
<span class="mx-3 d-none d-sm-block">超级管理员</span>
<div class="layout-drawer"><i class="fa fa-gears"></i></div>
</Header>
<Side>
<div class="layout-banner">
<img class="layout-logo" src="/images/brand.png" />
<div class="layout-title">
<span>后台管理</span>
</div>
</div>
<div class="layout-user">
<img class="layout-avatar" src="/images/Argo-C.png">
<div class="layout-title">
<span>管理员</span>
</div>
<div class="layout-user-state"></div>
</div>
</Side>
<Main>
@Body
</Main>
<Footer>
<div class="flex-fill text-center text-dark">Bootstrap Admin Blazor 版 &copy;</div>
</Footer>
</Layout>

View File

@ -0,0 +1,32 @@
namespace Bootstrap.Admin.Blazor.Shared
{
/// <summary>
/// MainLayout 布局类
/// </summary>
public partial class MainLayout
{
private IEnumerable<MenuItem>? MenuItems { get; set; }
/// <summary>
///
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
// TODO: 暂时写死 Admin 账号
//MenuItems = DataAccess.MenuHelper.RetrieveSystemMenus("Admin").Select(s => new MenuItem()
//{
// Url = s.Url.Replace("~", ""),
// Text = s.Name,
// Icon = s.Icon,
// Items = s.Menus.Select(x => new MenuItem
// {
// Url = x.Url.Replace("~", ""),
// Text = x.Name,
// Icon = x.Icon
// })
//});
}
}
}

View File

@ -0,0 +1,9 @@
@inherits LayoutComponentBase
<div class="error">
<div class="bg">
<img alt="404" src="@Image" />
</div>
<h3>请求资源未找到</h3>
<p>资源不存在或者没有访问权限,点击这里 <a href="/">返回首页</a> <span>或者</span> <a href="/healths-ui">系统自检</a></p>
</div>

View File

@ -0,0 +1,12 @@
namespace Bootstrap.Admin.Blazor.Shared
{
/// <summary>
/// NotFoundLayout 模板类
/// </summary>
public partial class NotFoundLayout
{
private string Image { get; set; } = "images/404.png";
private bool IsNotAuthorizated { get; set; }
}
}

View File

@ -0,0 +1,25 @@
.error {
position: absolute;
bottom: 0;
top: 0;
right: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background: #f7f7f7;
}
h3 {
font-size: 1.28rem;
font-weight: bold;
margin: 1.125rem 0;
}
.bg {
background-image: url('../images/bg404.png');
width: 458px;
height: 215px;
text-align: center;
}

View File

@ -0,0 +1,17 @@
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using BootstrapBlazor.Components
@using Bootstrap.Admin.Blazor
@using Bootstrap.Admin.Blazor.Components
@using Bootstrap.Admin.Blazor.Models
@using Bootstrap.Admin.Blazor.Shared
@using Bootstrap.Admin.Blazor.DataAccess

View File

@ -0,0 +1,331 @@
{
"DetailedErrors": true,
"AutoGenerateDatabase": true,
"DB": [
{
"Enabled": false,
"ProviderName": "SqlServer",
"SqlFolder": "..\\..\\..\\db\\SqlServer",
"ConnectionStrings": {
"ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa"
}
},
{
"Enabled": true,
"ProviderName": "Sqlite",
"SqlFolder": "..\\..\\..\\db\\SQLite",
"ConnectionStrings": {
"ba": "Data Source=BootstrapAdmin.db;"
}
},
{
"Enabled": false,
"ProviderName": "MySql",
"SqlFolder": "..\\..\\..\\db\\MySQL",
"ConnectionStrings": {
"ba": "Server=localhost;Database=BA;Uid=argozhang;Pwd=argo@163.com;SslMode=none;"
}
},
{
"Enabled": false,
"ProviderName": "Oracle",
"ConnectionStrings": {
"ba": "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=XXXXXX)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)));User Id=XX;Password=XX"
}
},
{
"Enabled": false,
"ProviderName": "Npgsql",
"ConnectionStrings": {
"ba": "Server=localhost;Database=BootstrapAdmin;User ID=argozhang;Password=argo@163.com;"
}
},
{
"Enabled": false,
"Widget": "Bootstrap.DataAccess.MongoDB",
"ProviderName": "MongoDB",
"SqlFolder": "..\\..\\..\\db\\MongoDB",
"ConnectionStrings": {
"ba": "mongodb://localhost:27017/BootstrapAdmin"
}
}
],
"SwaggerPathBase": "",
"GiteeHealthChecks": "true",
"AllowOrigins": "http://localhost:49185",
"HealthsCloudUrl": "https://client.blazor.zone/api/Interface/Healths",
"FileStorageOptions": {
"Enabled": true,
"Folder": "TaskStorage",
"Secure": false
},
"GiteeOptions": {
"Enabled": true,
"ClientId": "9bfe9b95d813ca7d613b110a54eda28bf227154b314c95f0c69e7680d64525e1",
"ClientSecret": "3427f2d901ba9afc76c1842a7303b2d67f8e098e71acc15051f89fe6f3d265db",
"CallbackPath": "/signin-gitee",
"HomePath": "/Admin/Profiles",
"Scope": [ "user_info", "projects" ],
"Roles": [ "Administrators" ],
"App": "Demo",
"StarredUrl": "https://gitee.com/api/v5/user/starred/LongbowEnterprise/BootstrapAdmin"
},
"GitHubOptions": {
"Enabled": true,
"ClientId": "ec53ecfe238558a0423b",
"ClientSecret": "ffa759ca599df941b869efecb5e750bc1b27334e",
"CallbackPath": "/signin-github",
"HomePath": "/Admin/Profiles",
"Scope": [ "user_info", "repo" ],
"Roles": [ "Administrators" ],
"App": "Demo",
"StarredUrl": "https://api.github.com/user/starred/ArgoZhang/BootstrapAdmin"
},
"WeChatOptions": {
"Enabled": true,
"ClientId": "<ClientId>",
"ClientSecret": "<secret>",
"CallbackPath": "/signin-weixin",
"HomePath": "/Admin/Profiles",
"Scope": [ "snsapi_login" ],
"Roles": [ "Administrators" ],
"App": "Demo"
},
"TencentOptions": {
"Enabled": true,
"ClientId": "<ClientId>",
"ClientSecret": "<ClientSecret>",
"CallbackPath": "/signin-tencent",
"HomePath": "/Admin/Profiles",
"Scope": [ "get_user_info" ],
"Roles": [ "Administrators" ],
"App": "Demo"
},
"SMSOptions": {
"CompanyCode": "<CompanyCode>",
"MD5Key": "MD5Key",
"Roles": [ "Administrators" ],
"HomePath": "/Admin/Profiles",
"App": "Demo"
},
"AlipayOptions": {
"Enabled": true,
"ClientId": "<ClientId>",
"ClientSecret": "<ClientSecret>",
"CallbackPath": "/signin-alipay",
"HomePath": "/Admin/Profiles",
"SignKey": "",
"Scope": [ "auth_user" ],
"Roles": [ "Administrators" ],
"App": "Demo"
},
"TencentSMSOptions": {
"AppId": "<TencentAppId>",
"AppKey": "<TencentAppKey>",
"TplId": 0,
"Sign": "<TencentSign>",
"Roles": [ "Default" ],
"HomePath": "/Admin/Profiles",
"App": "Demo",
"Debug": true
},
"AppMenus": [
"首页",
"测试页面",
"关于",
"返回码云",
"多级菜单",
"第二层",
"第三层",
"第四层"
],
"LongbowCache": {
"Enabled": true,
"CorsItems": [
{
"Enabled": true,
"Key": "ba",
"Url": "CacheList.axd",
"Desc": "后台管理数据缓存接口",
"Self": true
},
{
"Enabled": true,
"Key": "App",
"Url": "http://localhost:49185/CacheList.axd",
"Desc": "测试系统",
"Self": false
}
],
"CacheItems": [
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRolesByUserName",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "指定用户角色数据缓存"
},
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRolesByUrl",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过菜单获得角色数据"
},
{
"Enabled": true,
"Key": "AppHelper-RetrieveAppsByUserName",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "指定用户授权应用数据缓存"
},
{
"Enabled": true,
"Key": "BootstrapUser-RetrieveUsersByName",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "登录用户数据"
},
{
"Enabled": true,
"Key": "BootstrapDict-RetrieveDicts",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "所有字典数据缓存"
},
{
"Enabled": true,
"Key": "BootstrapMenu-RetrieveMenus",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "用户所有菜单数据缓存"
},
{
"Enabled": true,
"Key": "GroupHelper-RetrieveGroupsByUserName",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "指定用户组数据缓存"
},
{
"Enabled": true,
"Key": "UserHelper-RetrieveUsers",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "所有用户数据"
},
{
"Enabled": true,
"Key": "UserHelper-RetrieveUsersByRoleId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过角色ID获得所有用户数据"
},
{
"Enabled": true,
"Key": "UserHelper-RetrieveUsersByGroupId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过部门ID获得所有用户数据"
},
{
"Enabled": true,
"Key": "UserHelper-RetrieveNewUsers",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "新用户数据"
},
{
"Enabled": true,
"Key": "MenuHelper-RetrieveMenusByRoleId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过角色ID获得所有菜单数据"
},
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRoles",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "所有角色数据"
},
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRolesByUserId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过用户ID获得所有角色数据"
},
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRolesByMenuId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过菜单ID获得所有角色数据"
},
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRolesByGroupId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过部门ID获得所有角色数据"
},
{
"Enabled": true,
"Key": "GroupHelper-RetrieveGroups",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "所有部门数据"
},
{
"Enabled": true,
"Key": "GroupHelper-RetrieveGroupsByUserId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过用户ID获得所有部门数据"
},
{
"Enabled": true,
"Key": "GroupHelper-RetrieveGroupsByRoleId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过角色ID获得所有部门数据"
},
{
"Enabled": true,
"Key": "AppHelper-RetrieveAppsByRoleId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过角色ID获得所有应用程序数据"
},
{
"Enabled": true,
"Key": "DictHelper-RetrieveDictsCategory",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "字典分类数据"
},
{
"Enabled": true,
"Key": "ExceptionHelper-RetrieveExceptions",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "程序异常数据"
},
{
"Enabled": true,
"Key": "MessageHelper-RetrieveMessages",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "站内消息数据"
},
{
"Enabled": true,
"Key": "TaskHelper-RetrieveTasks",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "所有任务数据"
}
]
}
}

View File

@ -0,0 +1,350 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"LgbFile": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Error"
},
"FileName": "Error\\Log.log"
},
"Cloud": {
"LogLevel": {
"Default": "Error"
},
"Url": "https://client.blazor.zone/api/Interface/Log"
}
},
"ConnectionStrings": {
"ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa",
"bb": "Data Source=BootstrapAdmin.db;"
},
"AutoGenerateDatabase": false,
"DB": [
{
"Enabled": false,
"ProviderName": "SqlServer",
"ConnectionStrings": {
"ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa"
}
},
{
"Enabled": true,
"ProviderName": "Sqlite",
"ConnectionStrings": {
"ba": "Data Source=BootstrapAdmin.db;"
}
},
{
"Enabled": false,
"ProviderName": "MySql",
"ConnectionStrings": {
"ba": "Server=localhost;Database=BA;Uid=argozhang;Pwd=argo@163.com;SslMode=none;"
}
},
{
"Enabled": false,
"ProviderName": "Npgsql",
"ConnectionStrings": {
"ba": "Server=localhost;Database=BootstrapAdmin;User ID=argozhang;Password=argo@163.com;"
}
},
{
"Enabled": false,
"Widget": "Bootstrap.DataAccess.MongoDB",
"ProviderName": "MongoDB",
"ConnectionStrings": {
"ba": "mongodb://localhost:27017/BootstrapAdmin"
}
}
],
"AppId": "BA",
"UseHttps": true,
"SwaggerPathBase": "",
"AllowOrigins": "http://localhost,http://admin.blazor.zone",
"HealthsCloudUrl": "https://client.blazor.zone/api/Interface/Healths",
"GiteeHealthChecks": false,
"Sentry": {
"Dsn": "https://70bdfff562e84fa7b9a43d65924ab9ad@sentry.io/1469396"
},
"BootstrapBlazorOptions": {
"DefaultCultureInfo": "zh-CN"
},
"Exceptionless": {
"ApiKey": "AgQlY1MRWpX5qOF2edpK2IZYBhgPYImhr4UnZdAT"
},
"TokenValidateOption": {
"Issuer": "BA",
"Audience": "api",
"Expires": 5,
"SecurityKey": "BootstrapAdmin-V1.1"
},
"TaskServicesOptions": {
"ShutdownTimeout": "00:00:05"
},
"FileStorageOptions": {
"Enabled": true,
"Folder": "TaskStorage",
"Secure": true
},
"GiteeOptions": {
"Enabled": true,
"ClientId": "<ClientId>",
"ClientSecret": "<ClientSecret>",
"CallbackPath": "/signin-gitee",
"HomePath": "/Home/Index",
"Scope": [ "user_info", "projects" ],
"Roles": [ "Default" ],
"App": "Demo"
},
"GitHubOptions": {
"Enabled": true,
"ClientId": "<ClientId>",
"ClientSecret": "<ClientSecret>",
"CallbackPath": "/signin-github",
"HomePath": "/Home/Index",
"Scope": [ "user_info", "repo" ],
"Roles": [ "Default" ],
"App": "Demo"
},
"WeChatOptions": {
"Enabled": true,
"ClientId": "<ClientId>",
"ClientSecret": "<secret>",
"CallbackPath": "/signin-weixin",
"HomePath": "/Admin/Profiles",
"Scope": [ "snsapi_login" ],
"Roles": [ "Default" ],
"App": "Demo"
},
"TencentOptions": {
"Enabled": true,
"ClientId": "<ClientId>",
"ClientSecret": "<ClientSecret>",
"CallbackPath": "/signin-tencent",
"HomePath": "/Admin/Profiles",
"Scope": [ "get_user_info" ],
"Roles": [ "Administrators" ],
"App": "Demo"
},
"AlipayOptions": {
"Enabled": true,
"ClientId": "<ClientId>",
"ClientSecret": "<ClientSecret>",
"CallbackPath": "/signin-alipay",
"HomePath": "/Admin/Profiles",
"SignKey": "",
"Scope": [ "auth_user" ],
"Roles": [ "Administrators" ],
"App": "Demo"
},
"SMSOptions": {
"CompanyCode": "<CompanyCode>",
"MD5Key": "MD5Key",
"Roles": [ "Default" ],
"HomePath": "/Home/Index",
"App": "Demo"
},
"TencentSMSOptions": {
"AppId": "<TencentAppId>",
"AppKey": "<TencentAppKey>",
"TplId": 0,
"Sign": "<TencentSign>",
"Roles": [ "Default" ],
"HomePath": "/Admin/Profiles",
"App": "Demo"
},
"LongbowCache": {
"Enabled": true,
"CorsItems": [
{
"Enabled": true,
"Key": "ba",
"Url": "CacheList.axd",
"Desc": "后台管理数据缓存接口",
"Self": true
},
{
"Enabled": true,
"Key": "App",
"Url": "../Client/CacheList.axd",
"Desc": "测试系统",
"Self": false
}
],
"CacheItems": [
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRolesByUserName",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "指定用户角色数据缓存"
},
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRolesByUrl",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过菜单获得角色数据"
},
{
"Enabled": true,
"Key": "AppHelper-RetrieveAppsByUserName",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "指定用户授权应用数据缓存"
},
{
"Enabled": true,
"Key": "BootstrapUser-RetrieveUsersByName",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "登录用户数据"
},
{
"Enabled": true,
"Key": "BootstrapDict-RetrieveDicts",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "所有字典数据缓存"
},
{
"Enabled": true,
"Key": "BootstrapMenu-RetrieveMenus",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "用户所有菜单数据缓存"
},
{
"Enabled": true,
"Key": "GroupHelper-RetrieveGroupsByUserName",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "指定用户组数据缓存"
},
{
"Enabled": true,
"Key": "UserHelper-RetrieveUsers",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "所有用户数据"
},
{
"Enabled": true,
"Key": "UserHelper-RetrieveUsersByRoleId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过角色ID获得所有用户数据"
},
{
"Enabled": true,
"Key": "UserHelper-RetrieveUsersByGroupId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过部门ID获得所有用户数据"
},
{
"Enabled": true,
"Key": "UserHelper-RetrieveNewUsers",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "新用户数据"
},
{
"Enabled": true,
"Key": "MenuHelper-RetrieveMenusByRoleId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过角色ID获得所有菜单数据"
},
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRoles",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "所有角色数据"
},
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRolesByUserId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过用户ID获得所有角色数据"
},
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRolesByMenuId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过菜单ID获得所有角色数据"
},
{
"Enabled": true,
"Key": "RoleHelper-RetrieveRolesByGroupId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过部门ID获得所有角色数据"
},
{
"Enabled": true,
"Key": "GroupHelper-RetrieveGroups",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "所有部门数据"
},
{
"Enabled": true,
"Key": "GroupHelper-RetrieveGroupsByUserId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过用户ID获得所有部门数据"
},
{
"Enabled": true,
"Key": "GroupHelper-RetrieveGroupsByRoleId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过角色ID获得所有部门数据"
},
{
"Enabled": true,
"Key": "AppHelper-RetrieveAppsByRoleId",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "通过角色ID获得所有应用程序数据"
},
{
"Enabled": true,
"Key": "DictHelper-RetrieveDictsCategory",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "字典分类数据"
},
{
"Enabled": true,
"Key": "ExceptionHelper-RetrieveExceptions",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "程序异常数据"
},
{
"Enabled": true,
"Key": "MessageHelper-RetrieveMessages",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "站内消息数据"
},
{
"Enabled": true,
"Key": "TaskHelper-RetrieveTasks",
"Interval": 600000,
"SlidingExpiration": true,
"Desc": "所有任务数据"
}
]
}
}

View File

@ -0,0 +1,28 @@
.layout.is-page .layout-side {
color: #3f4254;
background-color: #fff;
box-shadow: 0 0 28px 0 rgb(82 63 105 / 5%);
}
.layout.is-page .layout-user .layout-title {
color: #3f4254;
}
.layout.is-page .layout-footer {
background-color: #f8f9fa;
}
.layout-gotop {
background: #e9ecef;
color: #3f4254;
}
.layout-gotop:hover {
background-color: #dee2e6;
}
@media (min-width: 768px) {
.sidebar {
background-color: #fff !important;
}
}

View File

@ -0,0 +1,36 @@
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
.blazor-error-boundary::after {
content: "An error has occurred."
}
.tabs-border-card {
box-shadow: none;
}

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 523 KiB

After

Width:  |  Height:  |  Size: 523 KiB

View File

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 217 KiB

After

Width:  |  Height:  |  Size: 217 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 152 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 385 KiB

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 314 KiB

After

Width:  |  Height:  |  Size: 314 KiB

View File

Before

Width:  |  Height:  |  Size: 288 B

After

Width:  |  Height:  |  Size: 288 B

View File

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 973 B

After

Width:  |  Height:  |  Size: 973 B

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 193 KiB

After

Width:  |  Height:  |  Size: 193 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 203 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 973 B

After

Width:  |  Height:  |  Size: 973 B

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 288 B

After

Width:  |  Height:  |  Size: 288 B

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

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