├── .github
└── workflows
│ └── dotnet.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_zh.md
└── src
├── .template.config
└── template.json
└── BlazorAdmin
├── .dockerignore
├── BlazorAdmin.Modules
├── BlazorAdmin.About
│ ├── BlazorAdmin.About.Client--
│ │ ├── BlazorAdmin.About.Client2.csproj
│ │ ├── Pages
│ │ │ ├── AboutPage.razor
│ │ │ ├── AboutPage.razor.cs
│ │ │ ├── TestComponent.razor
│ │ │ └── TestComponent.razor.cs
│ │ ├── Program.cs
│ │ ├── _Imports.razor
│ │ └── wwwroot
│ │ │ ├── appsettings.Development.json
│ │ │ └── appsettings.json
│ ├── BlazorAdmin.About.Client
│ │ ├── BlazorAdmin.About.Client.csproj
│ │ ├── Pages
│ │ │ ├── AboutPage.razor
│ │ │ ├── AboutPage.razor.cs
│ │ │ ├── TestComponent.razor
│ │ │ └── TestComponent.razor.cs
│ │ └── _Imports.razor
│ └── BlazorAdmin.About.Server
│ │ ├── BlazorAdmin.About.Server.csproj
│ │ └── Controllers
│ │ └── AboutController.cs
├── BlazorAdmin.Ai
│ ├── BlazorAdmin.Ai.csproj
│ ├── Pages
│ │ ├── Config
│ │ │ ├── Config.razor
│ │ │ ├── Config.razor.cs
│ │ │ └── Dialogs
│ │ │ │ ├── EditConfigDialog.razor
│ │ │ │ └── EditConfigDialog.razor.cs
│ │ ├── Prompt
│ │ │ ├── Dialogs
│ │ │ │ └── PromptDialog.razor
│ │ │ └── Prompt.razor
│ │ └── RequestRecord
│ │ │ ├── Dialogs
│ │ │ ├── DetailDialog.razor
│ │ │ └── DetailDialog.razor.cs
│ │ │ ├── RequestRecord.razor
│ │ │ └── RequestRecord.razor.cs
│ ├── Resources
│ │ ├── AiCulture.Designer.cs
│ │ ├── AiCulture.en.resx
│ │ └── AiCulture.resx
│ └── _Imports.razor
├── BlazorAdmin.Clients
│ ├── BlazorAdmin.Clients.Core
│ │ ├── BlazorAdmin.Clients.Core.csproj
│ │ └── Common
│ │ │ ├── EmptyLayout.razor
│ │ │ ├── EmptyLayout.razor.cs
│ │ │ └── ProvidersAggregate.razor
│ └── BlazorAdmin.Clients
│ │ ├── BlazorAdmin.Clients.csproj
│ │ ├── Program.cs
│ │ └── Properties
│ │ └── launchSettings.json
├── BlazorAdmin.Im
│ ├── Backgrounds
│ │ └── SendMessageBackgroundService.cs
│ ├── BlazorAdmin.Im.csproj
│ ├── Components
│ │ ├── Chat.razor
│ │ ├── Chat.razor.cs
│ │ ├── ChatDialog.razor
│ │ ├── ChatDialog.razor.cs
│ │ ├── ChatDialog.razor.css
│ │ ├── Messages
│ │ │ ├── OtherMessage.razor
│ │ │ └── SelfMessage.razor
│ │ ├── UserPickerDialog.razor
│ │ └── UserPickerDialog.razor.cs
│ ├── Core
│ │ ├── ChatHub.cs
│ │ └── IChatClient.cs
│ ├── Events
│ │ └── UpdateNoReadCountEvent.cs
│ ├── ImModule.cs
│ ├── Resources
│ │ ├── ImCulture.Designer.cs
│ │ ├── ImCulture.en.resx
│ │ └── ImCulture.resx
│ ├── _Imports.razor
│ └── wwwroot
│ │ └── js
│ │ └── scroll.js
├── BlazorAdmin.Layout
│ ├── BlazorAdmin.Layout.csproj
│ ├── Components
│ │ ├── Culture
│ │ │ └── CultureIcon.razor
│ │ ├── NavMenus
│ │ │ ├── NavItemMenu.razor
│ │ │ ├── NavItemMenu.razor.cs
│ │ │ ├── NavMenu.razor
│ │ │ ├── NavMenu.razor.cs
│ │ │ ├── NavMenu.razor.css
│ │ │ └── NavOpenButton.razor
│ │ ├── NavTabs
│ │ │ ├── NavTab.razor
│ │ │ └── NavTab.razor.cs
│ │ ├── Notification
│ │ │ ├── ActivatableContainer.razor
│ │ │ └── NotificationIcon.razor
│ │ ├── Themes
│ │ │ ├── DarkToggleButton.razor
│ │ │ ├── PrimaryChangeButton.razor
│ │ │ └── ProvidersAggregate.razor
│ │ └── UserAvatar
│ │ │ ├── Dialogs
│ │ │ ├── Com
│ │ │ │ ├── AvatarEditDialog.razor
│ │ │ │ ├── AvatarEditDialog.razor.cs
│ │ │ │ ├── AvatarEditDialog.razor.css
│ │ │ │ ├── BasicInfoConfig.razor
│ │ │ │ ├── BasicInfoConfig.razor.cs
│ │ │ │ ├── ChangePasswordDialog.razor
│ │ │ │ └── ChangePasswordDialog.razor.cs
│ │ │ └── ProfileSetting.razor
│ │ │ └── UserMenuAvatar.razor
│ ├── LayoutModule.cs
│ ├── Resources
│ │ ├── LayoutCulture.Designer.cs
│ │ ├── LayoutCulture.en.resx
│ │ └── LayoutCulture.resx
│ ├── States
│ │ └── LayoutState.cs
│ ├── _Imports.razor
│ └── wwwroot
│ │ └── js
│ │ └── drawer.js
├── BlazorAdmin.Log
│ ├── BlazorAdmin.Log.csproj
│ ├── Pages
│ │ ├── AuditLog
│ │ │ ├── AuditLog.razor
│ │ │ ├── AuditLog.razor.cs
│ │ │ └── Dialogs
│ │ │ │ ├── AuditLogDetailDialog.razor
│ │ │ │ └── AuditLogDetailDialog.razor.cs
│ │ └── LoginLog
│ │ │ ├── LoginLog.razor
│ │ │ └── LoginLog.razor.cs
│ └── _Imports.razor
├── BlazorAdmin.Metric
│ ├── BlazorAdmin.Metric.csproj
│ ├── Core
│ │ ├── MetricData.cs
│ │ └── MetricEventListener.cs
│ ├── MetricModule.cs
│ ├── Pages
│ │ └── AppMetric.razor
│ ├── Resources
│ │ ├── MetricCulture.Designer.cs
│ │ ├── MetricCulture.en.resx
│ │ └── MetricCulture.resx
│ ├── _Imports.razor
│ └── wwwroot
│ │ ├── background.png
│ │ └── exampleJsInterop.js
├── BlazorAdmin.Rbac
│ ├── BlazorAdmin.Rbac.csproj
│ ├── Components
│ │ ├── IconSelect.razor
│ │ ├── IconSelect.razor.cs
│ │ ├── IconSelect.razor.css
│ │ ├── MenuTreeSelect.razor
│ │ └── MenuTreeSelect.razor.cs
│ ├── Pages
│ │ ├── Menu
│ │ │ ├── Menu.razor
│ │ │ ├── Menu.razor.cs
│ │ │ └── Menu.razor.css
│ │ ├── Organization
│ │ │ ├── Dialogs
│ │ │ │ ├── MemberSelect.razor
│ │ │ │ └── MemberSelect.razor.cs
│ │ │ ├── Organization.razor
│ │ │ └── Organization.razor.cs
│ │ ├── Role
│ │ │ ├── Dialogs
│ │ │ │ ├── CreateRoleDialog.razor
│ │ │ │ ├── CreateRoleDialog.razor.cs
│ │ │ │ ├── RoleMenuDialog.razor
│ │ │ │ ├── RoleMenuDialog.razor.cs
│ │ │ │ ├── UpdateRoleDialog.razor
│ │ │ │ └── UpdateRoleDialog.razor.cs
│ │ │ ├── Role.razor
│ │ │ └── Role.razor.cs
│ │ └── User
│ │ │ ├── Dialogs
│ │ │ ├── ChangePasswordDialog.razor
│ │ │ ├── ChangePasswordDialog.razor.cs
│ │ │ ├── CreateUserDialog.razor
│ │ │ ├── CreateUserDialog.razor.cs
│ │ │ ├── UpdateUserDialog.razor
│ │ │ ├── UpdateUserDialog.razor.cs
│ │ │ ├── UserRoleDialog.razor
│ │ │ └── UserRoleDialog.razor.cs
│ │ │ ├── User.razor
│ │ │ └── User.razor.cs
│ ├── Resources
│ │ ├── RbacCulture.Designer.cs
│ │ ├── RbacCulture.en.resx
│ │ └── RbacCulture.resx
│ ├── _Imports.razor
│ └── wwwroot
│ │ └── js
│ │ └── sort.js
└── BlazorAdmin.Setting
│ ├── BlazorAdmin.Setting.csproj
│ ├── Pages
│ ├── Codes
│ │ └── CodeGenerator.razor
│ └── Setting
│ │ ├── Com
│ │ ├── JwtCom.razor
│ │ └── JwtCom.razor.cs
│ │ ├── Dialogs
│ │ ├── ConfirmUpdateRsa.razor
│ │ └── ConfirmUpdateRsa.razor.cs
│ │ ├── SettingPage.razor
│ │ └── SettingPage.razor.cs
│ ├── Resources
│ ├── SettingCulture.Designer.cs
│ ├── SettingCulture.en.resx
│ └── SettingCulture.resx
│ └── _Imports.razor
├── BlazorAdmin.Servers.Core
├── Auth
│ ├── ApiAuthorizeAttribute.cs
│ ├── ApiAuthorizeHandler.cs
│ ├── ApiAuthorizeRequirement.cs
│ ├── BlazorAuthorizationMiddlewareResultHandler.cs
│ ├── JwtAuthStateProvider.cs
│ ├── JwtOptionsExtension.cs
│ └── UserStateExtension.cs
├── BlazorAdmin.Servers.Core.csproj
├── Chat
│ ├── ChatMessageReceivedModel.cs
│ ├── ChatMessageSendModel.cs
│ └── MessageSender.cs
├── Components
│ ├── Dialogs
│ │ ├── CommonDeleteDialog.razor
│ │ ├── CommonDeleteDialog.razor.cs
│ │ ├── CommonDialog.cs
│ │ ├── CommonDialogEventArgs.cs
│ │ ├── ConfirmUserPasswordDialog.razor
│ │ └── ConfirmUserPasswordDialog.razor.cs
│ ├── Pages
│ │ ├── PageDataGridConfig.cs
│ │ ├── PageHeader.razor
│ │ └── PagePagination.razor
│ └── Select
│ │ ├── OrganizationTreeSelect.razor
│ │ └── OrganizationTreeSelect.razor.cs
├── CurrentApplication.cs
├── Data
│ ├── Attributes
│ │ └── IgnoreAudit.cs
│ ├── BlazorAdminDbContext.cs
│ ├── Constants
│ │ ├── ClaimConstant.cs
│ │ ├── CommonConstant.cs
│ │ ├── IconsConstant.cs
│ │ └── JwtConstant.cs
│ ├── DatabaseExtension.cs
│ ├── Entities
│ │ ├── Ai
│ │ │ ├── AiConfig.cs
│ │ │ ├── AiPrompt.cs
│ │ │ └── AiRequestRecord.cs
│ │ ├── Chat
│ │ │ ├── Group.cs
│ │ │ ├── GroupMember.cs
│ │ │ ├── GroupMessage.cs
│ │ │ ├── GroupSetting.cs
│ │ │ ├── NotReadedMessage.cs
│ │ │ ├── PrivateMessage.cs
│ │ │ └── PrivateSetting.cs
│ │ ├── Log
│ │ │ ├── AuditLog.cs
│ │ │ ├── AuditLogDetail.cs
│ │ │ └── LoginLog.cs
│ │ ├── Notification
│ │ │ ├── Notification.cs
│ │ │ └── NotificationReceiver.cs
│ │ ├── Rbac
│ │ │ ├── Menu.cs
│ │ │ ├── Organization.cs
│ │ │ ├── OrganizationUser.cs
│ │ │ ├── Role.cs
│ │ │ ├── RoleMenu.cs
│ │ │ ├── User.cs
│ │ │ └── UserRole.cs
│ │ └── Setting
│ │ │ ├── Setting.cs
│ │ │ └── UserSetting.cs
│ ├── Extensions
│ │ ├── OrganizationSetExtensions.cs
│ │ └── SettingSetExtensions.cs
│ └── QuartzExtension.cs
├── Dynamic
│ ├── DynamicEntityAttribute.cs
│ ├── DynamicEntityInfo.cs
│ ├── DynamicLoader.cs
│ └── DynamicPropertyAttribute.cs
├── Extension
│ ├── ClaimsPrincipalExtensions.cs
│ └── QueryableExtension.cs
├── Helper
│ ├── AiHelper.cs
│ ├── ChannelHelper.cs
│ ├── EventHelper.cs
│ ├── HashHelper.cs
│ ├── JwtHelper.cs
│ ├── NotificationHelper.cs
│ ├── RandomHelper.cs
│ ├── ReflectionHelper.cs
│ └── SeleniumHelper.cs
├── Modules
│ └── IModule.cs
├── Resources
│ ├── CommonComponent.Designer.cs
│ ├── CommonComponent.en.resx
│ ├── CommonComponent.resx
│ ├── CusCulture.Designer.cs
│ ├── CusCulture.en.resx
│ └── CusCulture.resx
├── Services
│ ├── AccessService.cs
│ ├── JobService.cs
│ ├── LoopBackgroundService.cs
│ └── TestJob.cs
└── States
│ └── ThemeState.cs
├── BlazorAdmin.Web
├── BlazorAdmin.Web.csproj
├── Components
│ ├── App.razor
│ ├── App.razor.cs
│ ├── Layout
│ │ ├── AuthorizedLayout.razor
│ │ ├── AuthorizedLayout.razor.cs
│ │ ├── EmptyLayout.razor
│ │ ├── EmptyLayout.razor.cs
│ │ ├── MainLayout.razor
│ │ └── MainLayout.razor.css
│ ├── Pages
│ │ ├── Error.razor
│ │ ├── Home.razor
│ │ ├── Home.razor.cs
│ │ ├── Login.razor
│ │ ├── Login.razor.cs
│ │ └── Login.razor.css
│ ├── Routes.razor
│ ├── Routes.razor.cs
│ ├── Shared
│ │ ├── Loading.razor
│ │ ├── Loading.razor.cs
│ │ ├── Loading.razor.css
│ │ ├── LoggerErrorBoundary.cs
│ │ ├── NoAuthorizedPage.razor
│ │ ├── NoAuthorizedPage.razor.cs
│ │ ├── NoAuthorizedPage.razor.css
│ │ ├── NotFoundPage.razor
│ │ └── NotFoundPage.razor.css
│ └── _Imports.razor
├── Controllers
│ └── CultureController.cs
├── Dockerfile
├── Program.cs
├── Properties
│ └── launchSettings.json
├── appsettings.Development.json
├── appsettings.json
└── wwwroot
│ ├── app.css
│ ├── favicon.png
│ ├── images
│ └── back.jpg
│ ├── js
│ ├── common.js
│ └── cookieUtil.js
│ └── libs
│ └── Sortable.min.js
└── BlazorAdmin.sln
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a .NET project
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
3 |
4 | name: .NET
5 |
6 | on:
7 | push:
8 | branches: [ "main" ]
9 | pull_request:
10 | branches: [ "main" ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v3
19 | - name: Setup .NET
20 | uses: actions/setup-dotnet@v3
21 | with:
22 | dotnet-version: 9.x
23 | - name: Restore dependencies
24 | run: |
25 | cd src
26 | cd BlazorAdmin
27 | dotnet restore
28 | - name: Build
29 | run: |
30 | cd src
31 | cd BlazorAdmin
32 | dotnet build --no-restore
33 | - name: Test
34 | run: |
35 | cd src
36 | cd BlazorAdmin
37 | dotnet test --no-build --verbosity normal
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 tenka
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### BlazorAdmin
2 |
3 | A simple management system template written using Blazor and MudBlazor.
4 |
5 | [中文版](README_zh.md)
6 |
7 | ---
8 |
9 | #### Features:
10 |
11 | - Support Interactive Auto Render Mode
12 |
13 | - Implemented RBAC
14 |
15 | - JWT Authentication
16 |
17 | - Built on Mudblazor
18 |
19 | - Theme light/dark and color switch
20 |
21 | - Localization
22 |
23 | - Audit/Login Log
24 |
25 | - Modularization
26 |
27 | - Quartz Support
28 |
29 | ---
30 |
31 | #### Technology stack:
32 |
33 | - .NET 9
34 |
35 | - Blazor
36 |
37 | - MudBlazor
38 |
39 | - Entity Framework Core
40 |
41 | ---
42 |
43 | #### Getting Started:
44 |
45 | ##### Run the Project:
46 |
47 | 1. Clone the repository
48 | 2. Navigate to the src/BlazorAdmin directory
49 | 3. Run `dotnet restore` to restore dependencies
50 | 4. Run `dotnet run --project BlazorAdmin.Web` to start the application
51 | 5. Open your browser and navigate to `https://localhost:37219`
52 |
53 | ##### Credentials:
54 |
55 | Username:BlazorAdmin
56 |
57 | Password:BlazorAdmin
58 |
59 | ##### Create New Project from Template:
60 |
61 | 1. Enter the folder:
62 | ```bash
63 | cd src
64 | ```
65 |
66 | 2. Install the template:
67 | ```bash
68 | dotnet new install .
69 | ```
70 |
71 | 3. Create a new project in other folder:
72 | ```bash
73 | dotnet new batpl -n YourProjectName
74 | ```
75 |
76 | 4. Uninstall the template in src folder:
77 | ```bash
78 | dotnet new uninstall .
79 | ```
80 |
--------------------------------------------------------------------------------
/README_zh.md:
--------------------------------------------------------------------------------
1 | ### BlazorAdmin
2 |
3 | 一个使用 Blazor 和 MudBlazor 编写的简单管理系统模板。
4 |
5 | [English](README.md)
6 |
7 | ---
8 |
9 | #### 特性:
10 |
11 | - 支持交互式自动渲染模式
12 |
13 | - 实现了基于角色的访问控制(RBAC)
14 |
15 | - JWT 身份认证
16 |
17 | - 基于 MudBlazor 构建
18 |
19 | - 主题明暗及颜色切换
20 |
21 | - 本地化支持
22 |
23 | - 审计/登录日志
24 |
25 | - 模块化设计
26 |
27 | - Quartz 支持
28 |
29 | ---
30 |
31 | #### 技术栈:
32 |
33 | - .NET 9
34 |
35 | - Blazor
36 |
37 | - MudBlazor
38 |
39 | - Entity Framework Core
40 |
41 | ---
42 |
43 | #### 快速开始:
44 |
45 | ##### 运行项目:
46 |
47 | 1. 克隆仓库
48 | 2. 进入 src/BlazorAdmin 目录
49 | 3. 运行 `dotnet restore` 恢复依赖
50 | 4. 运行 `dotnet run --project BlazorAdmin.Web` 启动应用
51 | 5. 打开浏览器访问 `https://localhost:37219`
52 |
53 | ##### 登录凭据:
54 |
55 | 用户名:BlazorAdmin
56 |
57 | 密码:BlazorAdmin
58 |
59 | ##### 从模板创建新项目:
60 |
61 | 1. 进入目录:
62 | ```bash
63 | cd src
64 | ```
65 |
66 | 2. 安装模板:
67 | ```bash
68 | dotnet new install .
69 | ```
70 |
71 | 3. 在其他目录创建新项目:
72 | ```bash
73 | dotnet new batpl -n 你的项目名称
74 | ```
75 |
76 | 4. 在 src 目录卸载模板:
77 | ```bash
78 | dotnet new uninstall .
79 | ```
--------------------------------------------------------------------------------
/src/.template.config/template.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "aishang2015",
3 | "classifications": [ "Web/WebAPI" ],
4 | "name": "BlazorAdmin",
5 | "identity": "BlazorAdminTpl",
6 | "shortName": "batpl",
7 | "tags": {
8 | "language": "C#",
9 | "type": "project"
10 | },
11 | "sourceName": "BlazorAdmin",
12 | "preferNameDirectory": true,
13 | "sources":[
14 | {
15 | "exclude":[
16 | "**/[Bb]in/**",
17 | "**/[Oo]bj/**",
18 | ".template.config/**/*",
19 | "**/*.filelist",
20 | "**/*.user",
21 | "**/*.lock.json",
22 | "**/node_modules/**",
23 | ".github/**",
24 | ".git/**",
25 | "LICENSE",
26 | "README.md",
27 | "**/.vs/**",
28 | "**/.vscode/**",
29 |
30 | ]
31 | }
32 | ]
33 |
34 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.gitignore
6 | **/.project
7 | **/.settings
8 | **/.toolstarget
9 | **/.vs
10 | **/.vscode
11 | **/*.*proj.user
12 | **/*.dbmdl
13 | **/*.jfm
14 | **/azds.yaml
15 | **/bin
16 | **/charts
17 | **/docker-compose*
18 | **/Dockerfile*
19 | **/node_modules
20 | **/npm-debug.log
21 | **/obj
22 | **/secrets.dev.yaml
23 | **/values.dev.yaml
24 | LICENSE
25 | README.md
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client--/BlazorAdmin.About.Client2.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0
4 | enable
5 | enable
6 | true
7 | Default
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client--/Pages/AboutPage.razor:
--------------------------------------------------------------------------------
1 | @page "/about"
2 | @using System.Net.Http.Headers
3 | @using Flurl
4 | @using Flurl.Http
5 |
6 | @rendermode InteractiveAuto
7 |
8 |
9 |
About
10 |
11 | Get A Number From Server
14 | Get A Number From Server Without Auth Token
17 |
18 | @code {
19 |
20 | private string _colorValue;
21 |
22 | private bool _isLoading = false;
23 |
24 | private int currentCount = 0;
25 |
26 | private async Task GetCount()
27 | {
28 | _isLoading = true;
29 |
30 | var cookieUtil = await _jsRuntime.InvokeAsync("import", "./js/cookieUtil.js");
31 | var token = await cookieUtil.InvokeAsync("getCookie", "AccessToken");
32 |
33 | var result = await _navManager.BaseUri
34 | .AppendPathSegment("api/about/GetRandomNumber")
35 | .WithOAuthBearerToken(token)
36 | .PostJsonAsync(new { })
37 | .ReceiveString();
38 |
39 | _snackbarService.Add("The Number Is " + result, Severity.Success);
40 |
41 | _isLoading = false;
42 | }
43 |
44 | private async Task GetCountWithAuthToken(){
45 |
46 | _isLoading = true;
47 |
48 | try
49 | {
50 | var result = await _navManager.BaseUri
51 | .AppendPathSegment("api/about/GetRandomNumber")
52 | .PostJsonAsync(new { })
53 | .ReceiveString();
54 |
55 | _snackbarService.Add("The Number Is " + result, Severity.Success);
56 | }
57 | catch (FlurlHttpException ex)
58 | {
59 | _snackbarService.Add("Error: " + ex.Message, Severity.Error);
60 | }
61 | catch (Exception ex)
62 | {
63 | _snackbarService.Add("An unexpected error occurred: " + ex.Message, Severity.Error);
64 | }
65 | finally
66 | {
67 | _isLoading = false;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client--/Pages/AboutPage.razor.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorAdmin.About.Client.Pages
2 | {
3 | public partial class AboutPage
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client--/Pages/TestComponent.razor:
--------------------------------------------------------------------------------
1 | @page "/testcomponent"
2 |
3 | @rendermode InteractiveWebAssembly
4 | @attribute [AllowAnonymous]
5 |
6 | @layout EmptyLayout
7 |
8 | TestComponent
9 |
10 | aa
11 |
12 | @(code)
13 | --------------------------------------
14 | @(code2)
15 | @code {
16 | }
17 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client--/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
2 | using MudBlazor;
3 | using MudBlazor.Services;
4 |
5 | var builder = WebAssemblyHostBuilder.CreateDefault(args);
6 | builder.Services.AddMudServices(config =>
7 | {
8 | config.SnackbarConfiguration.PositionClass = Defaults.Classes.Position.TopCenter;
9 |
10 | config.SnackbarConfiguration.PreventDuplicates = false;
11 | config.SnackbarConfiguration.NewestOnTop = false;
12 | config.SnackbarConfiguration.ShowCloseIcon = true;
13 | config.SnackbarConfiguration.VisibleStateDuration = 3000;
14 | config.SnackbarConfiguration.HideTransitionDuration = 200;
15 | config.SnackbarConfiguration.ShowTransitionDuration = 200;
16 | config.SnackbarConfiguration.SnackbarVariant = Variant.Filled;
17 | });
18 | await builder.Build().RunAsync();
19 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client--/_Imports.razor:
--------------------------------------------------------------------------------
1 | @using System.Net.Http
2 | @using System.Net.Http.Json
3 | @using Microsoft.AspNetCore.Components.Forms
4 | @using Microsoft.AspNetCore.Components.Routing
5 | @using Microsoft.AspNetCore.Components.Web
6 | @using Microsoft.AspNetCore.Authorization
7 | @using static Microsoft.AspNetCore.Components.Web.RenderMode
8 | @using Microsoft.AspNetCore.Components.Web.Virtualization
9 | @using Microsoft.JSInterop
10 | @using MudBlazor
11 | @using BlazorAdmin.Clients.Core.Common
12 |
13 | @inject IJSRuntime _jsRuntime;
14 | @inject ISnackbar _snackbarService;
15 | @inject NavigationManager _navManager;
16 |
17 | @attribute [Authorize]
18 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client--/wwwroot/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client--/wwwroot/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client/BlazorAdmin.About.Client.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client/Pages/AboutPage.razor:
--------------------------------------------------------------------------------
1 | @page "/about"
2 | @using System.Net.Http.Headers
3 | @using Flurl
4 | @using Flurl.Http
5 |
6 | @rendermode InteractiveAuto
7 |
8 |
9 | About
10 |
11 | Get A Number From Server
14 | Get A Number From Server Without Auth Token
17 |
18 | @code {
19 |
20 | private string _colorValue;
21 |
22 | private bool _isLoading = false;
23 |
24 | private int currentCount = 0;
25 |
26 | private async Task GetCount()
27 | {
28 | _isLoading = true;
29 |
30 | var cookieUtil = await _jsRuntime.InvokeAsync("import", "./js/cookieUtil.js");
31 | var token = await cookieUtil.InvokeAsync("getCookie", "AccessToken");
32 |
33 | var result = await _navManager.BaseUri
34 | .AppendPathSegment("api/about/GetRandomNumber")
35 | .WithOAuthBearerToken(token)
36 | .PostJsonAsync(new { })
37 | .ReceiveString();
38 |
39 | _snackbarService.Add("The Number Is " + result, Severity.Success);
40 |
41 | _isLoading = false;
42 | }
43 |
44 | private async Task GetCountWithAuthToken(){
45 |
46 | _isLoading = true;
47 |
48 | try
49 | {
50 | var result = await _navManager.BaseUri
51 | .AppendPathSegment("api/about/GetRandomNumber")
52 | .PostJsonAsync(new { })
53 | .ReceiveString();
54 |
55 | _snackbarService.Add("The Number Is " + result, Severity.Success);
56 | }
57 | catch (FlurlHttpException ex)
58 | {
59 | _snackbarService.Add("Error: " + ex.Message, Severity.Error);
60 | }
61 | catch (Exception ex)
62 | {
63 | _snackbarService.Add("An unexpected error occurred: " + ex.Message, Severity.Error);
64 | }
65 | finally
66 | {
67 | _isLoading = false;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client/Pages/AboutPage.razor.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorAdmin.About.Client.Pages
2 | {
3 | public partial class AboutPage
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client/Pages/TestComponent.razor:
--------------------------------------------------------------------------------
1 | @page "/testcomponent"
2 |
3 | @rendermode InteractiveWebAssembly
4 | @attribute [AllowAnonymous]
5 |
6 | @layout EmptyLayout
7 |
8 | TestComponent
9 |
10 | aa
11 |
12 | @(code)
13 | --------------------------------------
14 | @(code2)
15 | @code {
16 | }
17 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Client/_Imports.razor:
--------------------------------------------------------------------------------
1 | @using System.Net.Http
2 | @using System.Net.Http.Json
3 | @using Microsoft.AspNetCore.Components.Forms
4 | @using Microsoft.AspNetCore.Components.Routing
5 | @using Microsoft.AspNetCore.Components.Web
6 | @using Microsoft.AspNetCore.Authorization
7 | @using static Microsoft.AspNetCore.Components.Web.RenderMode
8 | @using Microsoft.AspNetCore.Components.Web.Virtualization
9 | @using Microsoft.JSInterop
10 | @using MudBlazor
11 | @using BlazorAdmin.Clients.Core.Common
12 |
13 | @inject IJSRuntime _jsRuntime;
14 | @inject ISnackbar _snackbarService;
15 | @inject NavigationManager _navManager;
16 |
17 | @attribute [Authorize]
18 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Server/BlazorAdmin.About.Server.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0
4 | enable
5 | enable
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.About/BlazorAdmin.About.Server/Controllers/AboutController.cs:
--------------------------------------------------------------------------------
1 | using BlazorAdmin.Servers.Core.Auth;
2 | using BlazorAdmin.Servers.Core.Data;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.EntityFrameworkCore;
5 |
6 | namespace BlazorAdmin.Web.Controllers
7 | {
8 | [Route("api/[controller]/[action]")]
9 | [ApiController]
10 | public class AboutController : ControllerBase
11 | {
12 | [ApiAuthorize]
13 | [HttpPost]
14 | public async Task GetRandomNumber([FromServices] IDbContextFactory _dbFactory)
15 | {
16 | using var context = await _dbFactory.CreateDbContextAsync();
17 | return Ok(new Random(context.AuditLogs.Count()).Next(0, 9999));
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Ai/BlazorAdmin.Ai.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Ai/Pages/Config/Dialogs/EditConfigDialog.razor.cs:
--------------------------------------------------------------------------------
1 | using BlazorAdmin.Servers.Core.Data.Entities.Ai;
2 | using Microsoft.AspNetCore.Components;
3 | using Microsoft.EntityFrameworkCore;
4 | using MudBlazor;
5 |
6 | namespace BlazorAdmin.Ai.Pages.Config.Dialogs
7 | {
8 | public partial class EditConfigDialog
9 | {
10 | [CascadingParameter] IMudDialogInstance MudDialog { get; set; } = null!;
11 |
12 | [Parameter] public int ConfigId { get; set; }
13 |
14 | private AiConfig Config { get; set; } = new();
15 |
16 | private MudForm form = null!;
17 |
18 | protected override async Task OnInitializedAsync()
19 | {
20 | if (ConfigId != 0)
21 | {
22 | using var context = await _dbFactory.CreateDbContextAsync();
23 | var config = await context.AiConfigs.FindAsync(ConfigId);
24 | if (config != null)
25 | {
26 | Config = new AiConfig
27 | {
28 | Id = config.Id,
29 | ConfigName = config.ConfigName,
30 | Endpoint = config.Endpoint,
31 | ApiKey = config.ApiKey,
32 | ModelName = config.ModelName,
33 | ContextLength = config.ContextLength,
34 | InputPricePerToken = config.InputPricePerToken,
35 | OutputPricePerToken = config.OutputPricePerToken,
36 | Description = config.Description,
37 | };
38 | }
39 | }
40 | }
41 |
42 | private async Task Submit()
43 | {
44 | await form.Validate();
45 | if (form.IsValid)
46 | {
47 | using var context = await _dbFactory.CreateDbContextAsync();
48 | if (ConfigId == 0)
49 | {
50 | context.AiConfigs.Add(Config);
51 | await context.SaveChangesAsync();
52 | _snackbarService.Add(Loc["AIConfig_CreateSuccess"], Severity.Success);
53 | }
54 | else
55 | {
56 | context.Entry(Config).State = EntityState.Modified;
57 | await context.SaveChangesAsync();
58 | _snackbarService.Add(Loc["AIConfig_EditSuccess"], Severity.Success);
59 | }
60 | MudDialog.Close(DialogResult.Ok(true));
61 | }
62 | }
63 |
64 | private void Cancel()
65 | {
66 | MudDialog.Cancel();
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Ai/Pages/Prompt/Dialogs/PromptDialog.razor:
--------------------------------------------------------------------------------
1 | @using BlazorAdmin.Servers.Core.Data.Entities.Ai
2 | @using BlazorAdmin.Servers.Core.Helper
3 | @inject IStringLocalizer localizer
4 |
5 |
6 |
7 |
8 |
9 |
10 |
13 |
16 |
17 |
18 | @localizer["PromptDialog_Cancel"]
19 | @localizer["PromptDialog_Submit"]
20 |
21 |
22 |
23 |
24 |
25 |
26 | @code {
27 | [CascadingParameter] IMudDialogInstance MudDialog { get; set; } = null!;
28 |
29 | [Parameter]
30 | public AiPrompt Model { get; set; } = new();
31 |
32 | private void Cancel()
33 | {
34 | MudDialog.Cancel();
35 | }
36 |
37 | private async Task Submit()
38 | {
39 | using var context = await _dbFactory.CreateDbContextAsync();
40 | if (Model.Id == 0)
41 | {
42 | await context.Set().AddAsync(Model);
43 | }
44 | else
45 | {
46 | context.Update(Model);
47 | }
48 | await context.SaveChangesAsync();
49 | MudDialog.Close(DialogResult.Ok(true));
50 |
51 | }
52 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Ai/Pages/RequestRecord/Dialogs/DetailDialog.razor:
--------------------------------------------------------------------------------
1 | @using BlazorAdmin.Servers.Core.Data.Entities.Ai
2 | @using BlazorAdmin.Servers.Core.Helper
3 | @inject IDbContextFactory _dbFactory
4 |
5 |
6 |
7 | @Loc["AIRequestRecord_RequestContent"]:
@Record?.RequestContent
8 | @Loc["AIRequestRecord_ResponseContent"]:
@Record?.ResponseContent
9 |
10 |
11 | @Loc["Button_Close"]
12 |
13 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Ai/Pages/RequestRecord/Dialogs/DetailDialog.razor.cs:
--------------------------------------------------------------------------------
1 | using BlazorAdmin.Servers.Core.Data.Entities.Ai;
2 | using Microsoft.AspNetCore.Components;
3 | using MudBlazor;
4 |
5 | namespace BlazorAdmin.Ai.Pages.RequestRecord.Dialogs
6 | {
7 | public partial class DetailDialog
8 | {
9 | [CascadingParameter] IMudDialogInstance MudDialog { get; set; } = null!;
10 |
11 | [Parameter] public int RecordId { get; set; }
12 |
13 | private AiRequestRecord? Record { get; set; }
14 |
15 | protected override async Task OnInitializedAsync()
16 | {
17 | using var context = await _dbFactory.CreateDbContextAsync();
18 | Record = await context.AiRequestRecords.FindAsync(RecordId);
19 | }
20 |
21 | private void Cancel()
22 | {
23 | MudDialog.Close();
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Ai/Resources/AiCulture.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace BlazorAdmin.Ai.Resources {
12 | using System;
13 |
14 |
15 | ///
16 | /// 一个强类型的资源类,用于查找本地化的字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public class AiCulture {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal AiCulture() {
33 | }
34 |
35 | ///
36 | /// 返回此类使用的缓存的 ResourceManager 实例。
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | public static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BlazorAdmin.Ai.Resources.AiCulture", typeof(AiCulture).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// 重写当前线程的 CurrentUICulture 属性,对
51 | /// 使用此强类型资源类的所有资源查找执行重写。
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Ai/_Imports.razor:
--------------------------------------------------------------------------------
1 | @using System.Net.Http
2 | @using BlazorAdmin
3 | @using BlazorAdmin.Ai.Resources
4 |
5 | @using BlazorAdmin.Servers.Core.Auth;
6 | @using BlazorAdmin.Servers.Core.Components.Pages;
7 | @using BlazorAdmin.Servers.Core.Components.Select;
8 | @using BlazorAdmin.Servers.Core.Data;
9 | @using BlazorAdmin.Servers.Core.Helper
10 | @using BlazorAdmin.Servers.Core.Resources;
11 | @using BlazorAdmin.Servers.Core.Services;
12 | @using Microsoft.AspNetCore.Authorization
13 | @using Microsoft.AspNetCore.Components.Authorization
14 | @using Microsoft.AspNetCore.Components.Forms
15 | @using Microsoft.AspNetCore.Components.Routing
16 | @using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
17 | @using Microsoft.AspNetCore.Components.Web
18 | @using Microsoft.AspNetCore.Components.Web.Virtualization
19 | @using Microsoft.EntityFrameworkCore;
20 | @using Microsoft.Extensions.Localization;
21 | @using Microsoft.JSInterop
22 | @using MudBlazor
23 |
24 | @inject IJSRuntime _jsRuntime;
25 | @inject IDbContextFactory _dbFactory;
26 | @inject IDialogService _dialogService;
27 | @inject ISnackbar _snackbarService;
28 | @inject IAccessService _accessService;
29 |
30 | @inject JwtHelper _jwtHelper;
31 | @inject AiHelper _aiHelper;
32 |
33 | @inject AuthenticationStateProvider _stateProvider;
34 | @inject ExternalAuthService _authService;
35 | @inject ProtectedLocalStorage _localStorage;
36 | @inject NavigationManager _navManager;
37 | @inject IJobService _jobService;
38 |
39 | @inject IStringLocalizer Loc;
40 |
41 | @attribute [Authorize]
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Clients/BlazorAdmin.Clients.Core/BlazorAdmin.Clients.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Clients/BlazorAdmin.Clients.Core/Common/EmptyLayout.razor:
--------------------------------------------------------------------------------
1 |
2 | @inherits LayoutComponentBase
3 |
4 |
5 |
6 |
7 | @Body
8 |
9 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Clients/BlazorAdmin.Clients.Core/Common/EmptyLayout.razor.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorAdmin.Clients.Core.Common
2 | {
3 | public partial class EmptyLayout
4 | {
5 | protected override async Task OnInitializedAsync()
6 | {
7 | await base.OnInitializedAsync();
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Clients/BlazorAdmin.Clients.Core/Common/ProvidersAggregate.razor:
--------------------------------------------------------------------------------
1 | @using Microsoft.AspNetCore.Components.Web
2 | @using MudBlazor
3 |
4 | @rendermode RenderMode.InteractiveWebAssembly
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Clients/BlazorAdmin.Clients/BlazorAdmin.Clients.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | true
8 | Default
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Clients/BlazorAdmin.Clients/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
2 | using MudBlazor;
3 | using MudBlazor.Services;
4 |
5 | var builder = WebAssemblyHostBuilder.CreateDefault(args);
6 | builder.Services.AddMudServices(config =>
7 | {
8 | config.SnackbarConfiguration.PositionClass = Defaults.Classes.Position.TopCenter;
9 |
10 | config.SnackbarConfiguration.PreventDuplicates = false;
11 | config.SnackbarConfiguration.NewestOnTop = false;
12 | config.SnackbarConfiguration.ShowCloseIcon = true;
13 | config.SnackbarConfiguration.VisibleStateDuration = 3000;
14 | config.SnackbarConfiguration.HideTransitionDuration = 200;
15 | config.SnackbarConfiguration.ShowTransitionDuration = 200;
16 | config.SnackbarConfiguration.SnackbarVariant = Variant.Filled;
17 | });
18 | await builder.Build().RunAsync();
19 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Clients/BlazorAdmin.Clients/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/launchsettings.json",
3 | "profiles": {
4 | "http": {
5 | "commandName": "Project",
6 | "dotnetRunMessages": true,
7 | "launchBrowser": true,
8 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
9 | "applicationUrl": "http://localhost:5186",
10 | "environmentVariables": {
11 | "ASPNETCORE_ENVIRONMENT": "Development"
12 | }
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/BlazorAdmin.Im.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0
4 | enable
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | True
18 | True
19 | ImCulture.resx
20 |
21 |
22 |
23 |
24 | PublicResXFileCodeGenerator
25 | ImCulture.Designer.cs
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/Components/Chat.razor:
--------------------------------------------------------------------------------
1 | @using BlazorAdmin.Servers.Core.Helper
2 | @implements IAsyncDisposable
3 | @rendermode InteractiveServer
4 |
5 |
6 | @if (_noReadCount > 0 && !_isDialogOpen)
7 | {
8 |
10 |
12 |
13 |
14 | }
15 | else
16 | {
17 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/Components/ChatDialog.razor.css:
--------------------------------------------------------------------------------
1 | #chat-title{
2 |
3 | }
4 |
5 | #chat-area {
6 | width: 80vw;
7 | height: 80vh;
8 | }
9 |
10 |
11 | #channel-list {
12 | width: 300px;
13 | height: 100%;
14 | padding: 0 10px;
15 | }
16 |
17 | #message-list {
18 | flex: 1;
19 | height: 100%;
20 | }
21 |
22 |
23 | #message-area {
24 | overflow: auto;
25 | }
26 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/Components/Messages/OtherMessage.razor:
--------------------------------------------------------------------------------
1 | @using BlazorAdmin.Servers.Core.Helper
2 |
3 |
4 | @if (string.IsNullOrEmpty(Avatar))
5 | {
6 |
7 | @RealName?.First()
8 |
9 | }
10 | else
11 | {
12 |
13 |
14 |
15 | }
16 |
17 |
18 | @Message
19 |
20 |
21 | @SendTime
22 |
23 |
24 |
25 |
26 | @code {
27 | [Parameter] public string? Avatar { get; set; }
28 |
29 | [Parameter] public string? RealName { get; set; }
30 |
31 | [Parameter] public DateTime? SendTime { get; set; }
32 |
33 | [Parameter] public string? Message { get; set; }
34 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/Components/Messages/SelfMessage.razor:
--------------------------------------------------------------------------------
1 | @using BlazorAdmin.Servers.Core.Helper
2 |
3 | @if (string.IsNullOrEmpty(Avatar))
4 | {
5 |
6 | @RealName?.First()
7 |
8 | }
9 | else
10 | {
11 |
12 |
13 |
14 | }
15 |
16 |
17 | @Message
18 |
19 |
20 | @SendTime
21 |
22 |
23 |
24 |
25 |
26 |
27 | @code {
28 | [Parameter] public string? Avatar { get; set; }
29 |
30 | [Parameter] public string? RealName { get; set; }
31 |
32 | [Parameter] public DateTime? SendTime { get; set; }
33 |
34 | [Parameter] public string? Message { get; set; }
35 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/Components/UserPickerDialog.razor:
--------------------------------------------------------------------------------
1 | @using BlazorAdmin.Servers.Core.Helper
2 |
3 |
4 |
5 |
6 | 选择用户
7 |
8 | @if (_checkedUserSet.Count > 0)
9 | {
10 | 已选择@(_checkedUserSet.Count)个用户
11 | }
12 |
13 |
16 |
17 |
18 |
19 |
21 | @if (string.IsNullOrEmpty(context.Avatar))
22 | {
23 |
24 | @context.RealName?.First()
25 |
26 | }
27 | else
28 | {
29 |
30 |
31 |
32 | }
33 |
34 | @context.RealName
35 |
36 |
37 |
38 |
39 | @if (_checkedUserSet.Count > 0)
40 | {
41 |
42 |
43 | 确定
44 |
45 | }
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/Core/ChatHub.cs:
--------------------------------------------------------------------------------
1 | using BlazorAdmin.Servers.Core.Extension;
2 | using BlazorAdmin.Servers.Core.Helper;
3 | using Microsoft.AspNetCore.Http.Features;
4 | using Microsoft.AspNetCore.SignalR;
5 | using System.Collections.Concurrent;
6 |
7 | namespace BlazorAdmin.Im.Core
8 | {
9 | public class ChatHub : Hub
10 | {
11 | private readonly JwtHelper _jwtHelper;
12 |
13 | public static readonly string ChatHubUrl = "/blazoradmin-chat";
14 |
15 | public static ConcurrentDictionary OnlineUsers = new ConcurrentDictionary();
16 |
17 | public ChatHub(JwtHelper jwtHelper)
18 | {
19 | _jwtHelper = jwtHelper;
20 | }
21 |
22 | public override async Task OnConnectedAsync()
23 | {
24 | var httpContextFeature = Context.Features.FirstOrDefault(f => f.Value is IHttpRequestFeature).Value as IHttpRequestFeature;
25 | var authToken = httpContextFeature?.Headers.Authorization.ToString().Split(" ").Last();
26 | var userPrincipal = _jwtHelper.ValidToken(authToken ?? string.Empty);
27 |
28 | if (userPrincipal == null)
29 | {
30 | throw new HubException("认证失败!拒绝连接!");
31 | }
32 |
33 | OnlineUsers.AddOrUpdate(userPrincipal.GetUserId(), Context.ConnectionId, (key, value) => Context.ConnectionId);
34 | await base.OnConnectedAsync();
35 | }
36 |
37 | public override async Task OnDisconnectedAsync(Exception? exception)
38 | {
39 | var httpContextFeature = Context.Features.FirstOrDefault(f => f.Value is IHttpRequestFeature).Value as IHttpRequestFeature;
40 | var authToken = httpContextFeature?.Headers.Authorization.ToString().Split(" ").Last();
41 | var userPrincipal = _jwtHelper.ValidToken(authToken ?? string.Empty);
42 | OnlineUsers.Remove(userPrincipal.GetUserId(), out var connectionId);
43 | await base.OnDisconnectedAsync(exception);
44 | }
45 |
46 | public record OnlineUser
47 | {
48 | public string ConnectionId { get; set; } = null!;
49 |
50 | public int UserId { get; set; }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/Core/IChatClient.cs:
--------------------------------------------------------------------------------
1 | using BlazorAdmin.Servers.Core.Chat;
2 |
3 | namespace BlazorAdmin.Im.Core
4 | {
5 | public interface IChatClient
6 | {
7 | Task ReceiveMessage(ChatMessageReceivedModel message);
8 |
9 | Task ChangeMessageCount();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/Events/UpdateNoReadCountEvent.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorAdmin.Im.Events
2 | {
3 | public class UpdateNoReadCountEvent
4 | {
5 | public UpdateNoCountEventType Type { get; set; }
6 |
7 | public int Count { get; set; }
8 | }
9 |
10 | public enum UpdateNoCountEventType
11 | {
12 | Add,
13 | Sub,
14 | Refresh,
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/ImModule.cs:
--------------------------------------------------------------------------------
1 | using BlazorAdmin.Im.Backgrounds;
2 | using BlazorAdmin.Im.Core;
3 | using BlazorAdmin.Im.Events;
4 | using BlazorAdmin.Servers.Core.Helper;
5 | using BlazorAdmin.Servers.Core.Modules;
6 | using Microsoft.AspNetCore.Builder;
7 | using Microsoft.Extensions.DependencyInjection;
8 |
9 | namespace BlazorAdmin.Im
10 | {
11 | public class ImModule : IModule
12 | {
13 | public IServiceCollection Add(IServiceCollection services)
14 | {
15 | services.AddHostedService();
16 | services.AddScoped>();
17 |
18 | return services;
19 | }
20 |
21 | public WebApplication Use(WebApplication app)
22 | {
23 | app.MapHub(ChatHub.ChatHubUrl);
24 | return app;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/_Imports.razor:
--------------------------------------------------------------------------------
1 | @using System.Net.Http
2 | @using BlazorAdmin
3 |
4 | @using BlazorAdmin.Im.Events
5 | @using BlazorAdmin.Im.Resources
6 | @using BlazorAdmin.Servers.Core.Auth;
7 | @using BlazorAdmin.Servers.Core.Chat
8 | @using BlazorAdmin.Servers.Core.Components.Pages;
9 | @using BlazorAdmin.Servers.Core.Data;
10 | @using BlazorAdmin.Servers.Core.Helper
11 | @using BlazorAdmin.Servers.Core.Resources;
12 | @using BlazorAdmin.Servers.Core.Services;
13 | @using Microsoft.AspNetCore.Authorization
14 | @using Microsoft.AspNetCore.Components.Authorization
15 | @using Microsoft.AspNetCore.Components.Forms
16 | @using Microsoft.AspNetCore.Components.Routing
17 | @using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
18 | @using Microsoft.AspNetCore.Components.Web
19 | @using Microsoft.AspNetCore.Components.Web.Virtualization
20 | @using Microsoft.EntityFrameworkCore;
21 | @using Microsoft.Extensions.Localization;
22 | @using Microsoft.JSInterop
23 | @using MudBlazor
24 | @using static Microsoft.AspNetCore.Components.Web.RenderMode
25 |
26 | @inject IJSRuntime _jsRuntime;
27 | @inject IDbContextFactory _dbFactory;
28 | @inject IDialogService _dialogService;
29 | @inject ISnackbar _snackbarService;
30 | @inject IAccessService _accessService;
31 |
32 | @inject JwtHelper _jwtHelper;
33 | @inject AuthenticationStateProvider _stateProvider;
34 | @inject ExternalAuthService _authService;
35 | @inject ProtectedLocalStorage _localStorage;
36 | @inject NavigationManager _navManager;
37 | @inject IStringLocalizer _loc;
38 | @inject EventHelper _updateNoReadCountEventHelper;
39 | @inject MessageSender _messageSender;
40 |
41 | @attribute [Authorize]
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Im/wwwroot/js/scroll.js:
--------------------------------------------------------------------------------
1 | export function scrollToBottom() {
2 | let element = document.getElementById("message-area");
3 | element.scrollTop = element.scrollHeight ;
4 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Layout/BlazorAdmin.Layout.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0
4 | enable
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | True
16 | True
17 | LayoutCulture.resx
18 |
19 |
20 |
21 |
22 | ResXFileCodeGenerator
23 | LayoutCulture.Designer.cs
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Layout/Components/Culture/CultureIcon.razor:
--------------------------------------------------------------------------------
1 | @using BlazorAdmin.Servers.Core.Helper
2 | @using BlazorAdmin.Servers.Core.States
3 | @rendermode InteractiveServer
4 |
5 | @if (IsText)
6 | {
7 |
9 |
10 |
11 | @_loc["CultureLanguage"]
12 |
13 |
14 |
15 | @Loc["AuthorizedLayout_Language_zhcn"]
16 |
17 |
18 | @Loc["AuthorizedLayout_Language_enus"]
19 |
20 |
21 |
22 | }
23 | else
24 | {
25 |
27 |
28 | @Loc["AuthorizedLayout_Language_zhcn"]
29 |
30 |
31 | @Loc["AuthorizedLayout_Language_enus"]
32 |
33 |
34 | }
35 |
36 | @code {
37 | [Parameter] public bool IsText { get; set; } = false;
38 |
39 | private void CultureChanged(string culture)
40 | {
41 | if (!string.IsNullOrEmpty(culture))
42 | {
43 | var uri = new Uri(_navManager.Uri)
44 | .GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
45 | var cultureEscaped = Uri.EscapeDataString(culture);
46 | //var uriEscaped = Uri.EscapeDataString(uri);
47 |
48 | _navManager.NavigateTo(
49 | $"api/Culture/Set?culture={cultureEscaped}&redirectUri={uri}",
50 | forceLoad: true);
51 | }
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Layout/Components/NavMenus/NavItemMenu.razor:
--------------------------------------------------------------------------------
1 | @using BlazorAdmin.Servers.Core.Helper
2 | @using BlazorAdmin.Servers.Core.States
3 | @foreach (var m in NavMenuItems)
4 | {
5 | if (m.Childs.Count == 0)
6 | {
7 | NavClick(m)">@_loc[m.MenuName]
9 | }
10 | else
11 | {
12 |
14 |
15 |
16 | }
17 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Layout/Components/NavMenus/NavItemMenu.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 |
3 | namespace BlazorAdmin.Layout.Components.NavMenus
4 | {
5 | public partial class NavItemMenu
6 | {
7 | [Parameter] public HashSet NavMenuItems { get; set; } = new();
8 |
9 | [Parameter] public EventCallback NavTo { get; set; }
10 |
11 | private bool _shouldRender = false;
12 |
13 | protected override bool ShouldRender() => _shouldRender;
14 |
15 | private async Task NavClick(NavMenuItem item)
16 | {
17 | await NavTo.InvokeAsync(item);
18 | }
19 |
20 | public record NavMenuItem
21 | {
22 | public string? MenuIcon { get; set; }
23 |
24 | public string? MenuName { get; set; }
25 |
26 | public string? Route { get; set; }
27 |
28 | public HashSet Childs { get; set; } = new();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Layout/Components/NavMenus/NavMenu.razor:
--------------------------------------------------------------------------------
1 | @using BlazorAdmin.Servers.Core.Helper
2 | @using BlazorAdmin.Servers.Core.States
3 | @rendermode InteractiveServer
4 |
5 |
6 |
7 |
8 | BlazorAdmin
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | @code {
19 |
20 | protected override void OnInitialized()
21 | {
22 | base.OnInitialized();
23 | _layoutState.NavIsOpenEvent += () => StateHasChanged();
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/src/BlazorAdmin/BlazorAdmin.Modules/BlazorAdmin.Layout/Components/NavMenus/NavMenu.razor.cs:
--------------------------------------------------------------------------------
1 | using BlazorAdmin.Servers.Core.Data.Entities.Rbac;
2 | using static BlazorAdmin.Layout.Components.NavMenus.NavItemMenu;
3 |
4 | namespace BlazorAdmin.Layout.Components.NavMenus
5 | {
6 | public partial class NavMenu
7 | {
8 |
9 | private List