Compare commits

...

41 Commits

Author SHA1 Message Date
p53209761 351a86ba4b Update README.md 2022-08-16 00:09:59 +08:00
p53209761 81b7a18773 Update README.md 2022-08-16 00:09:47 +08:00
Argo-Lenovo 760c83457a Revert "refactor: 移除 ICacheManager 服务代码"
This reverts commit 544441a5fc.
2022-07-22 09:30:51 +08:00
Argo-Lenovo c4eeda3ae8 db: 更新数据库 2022-07-20 14:17:08 +08:00
Argo-Lenovo 544441a5fc refactor: 移除 ICacheManager 服务代码 2022-07-20 14:09:15 +08:00
Argo-Lenovo 4686a75744 test: 更新依赖包 2022-07-20 14:06:50 +08:00
Argo-Lenovo 9be53cf009 chore: 更新依赖包到最新版 2022-07-20 14:06:43 +08:00
Argo-Lenovo 312f771313 chore: 更新依赖到最新版 2022-07-20 14:05:07 +08:00
Argo-Lenovo 234063b3bd refactor: 更新 form-footer 样式 2022-07-12 12:01:34 +08:00
Argo-Lenovo 43cb329757 refactor: 增加 await 关键字 2022-07-12 12:01:21 +08:00
Argo-Lenovo c0d21fcbb6 refactor: 增加 Key 关键字 2022-07-12 11:54:14 +08:00
Argo-Lenovo 994f439d40 refactor: 更新参数名更改 Text 为 DisplayText 2022-07-12 11:52:09 +08:00
Argo-Lenovo 8bf3f20fa5 test: 修复单元测试脚本错误 2022-07-11 11:43:30 +08:00
Argo-Lenovo c8329d5b84 chore: 更新项目过滤配置 2022-07-11 11:43:12 +08:00
Argo-Lenovo ea461e433e chore: 更新项目依赖包版本 2022-07-11 11:43:00 +08:00
Argo-Lenovo 213e9155a5 chore: 更新过滤项目配置 2022-07-11 11:28:46 +08:00
Argo-Lenovo e3b67c9427 feat: 菜单默认全部展开 2022-07-06 15:06:21 +08:00
Argo-Lenovo 35cc0f5174 feat: 支持树状结构 2022-07-06 15:06:08 +08:00
OneNewPerson 9343a9522e !106 fix TableTreeNode && freesql Trace实体映射
* fix TableTreeNode && freesql Trace实体映射
* Revert "fix TableTreeNode && freesql Trace实体映射"
* fix TableTreeNode && freesql Trace实体映射
2022-07-06 02:19:58 +00:00
Argo-Lenovo 026b1bb990 fix(#I543FE): 修复重复脚本问题
close https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues/I543FE
2022-06-08 09:54:31 +08:00
Argo-Lenovo f030cb4be9 feat: Client 工程增加 DBManagerService 2022-06-02 12:18:05 +08:00
zhangpeihang 3f6834de5f refactor: 重构 菜单服务 2022-06-02 11:00:15 +08:00
Argo-Lenovo 08df8d8da0 refactor: 更新 LoginService 服务 2022-06-02 10:59:39 +08:00
zhangpeihang e9c5bd2c08 refactor: 重构 Role 服务 2022-06-02 10:57:50 +08:00
Argo-Lenovo 2ef69da9e1 refactor: 更新 GroupService 服务 2022-06-02 10:57:11 +08:00
Argo-Lenovo ed5790ff72 refactor: 更新 ExceptionService 服务 2022-06-02 10:54:45 +08:00
Argo-Lenovo 5d4de2c766 refactor: 更新代码 2022-06-02 10:53:08 +08:00
zhangpeihang 9a02d45e27 refactor: 重构 trace 服务 2022-06-02 10:51:57 +08:00
zhangpeihang ab6e260b6b refactor: 重构 User 服务 2022-06-02 10:51:57 +08:00
Argo-Lenovo 0e58b81d19 refactor: 更新 DictService 服务类 2022-06-02 10:43:40 +08:00
Argo-Lenovo 34e376d712 refactor: 更新 DefaultDataService 服务 2022-06-02 10:39:50 +08:00
Argo-Lenovo b96aab631f refactor: 更新 AppService 服务使用 DBManagerService 2022-06-02 10:17:15 +08:00
Argo-Lenovo 09bf567698 refactor: 更改命名空间 2022-06-02 10:13:18 +08:00
Argo-Lenovo 2481a4a577 feat: 增加 IDBManager 接口负责维护 IDatabase 2022-06-02 10:13:00 +08:00
Argo-Lenovo f7b2c059ef feat: 增加 Dummy 示例页面 2022-06-01 20:55:06 +08:00
Argo-Lenovo 7a95ddc039 feat: 增加 IDummy 示例服务 2022-06-01 18:49:53 +08:00
Argo-Lenovo 9dfd95ce41 feat: 增加多库服务支持 2022-06-01 18:49:30 +08:00
Argo-Lenovo 371d188d76 chore: 更新启动配置项 2022-06-01 17:56:54 +08:00
Argo-Lenovo 134d0ee8a8 feat: Client 增加 Table 自定义组件 2022-06-01 17:23:49 +08:00
Argo-Lenovo 4995899c4c chore: 更改 Client 配置 2022-06-01 17:19:28 +08:00
Argo-Lenovo 6ccbadd1ea chore: 更新配置文件 2022-06-01 17:02:34 +08:00
67 changed files with 1013 additions and 880 deletions

View File

@ -11,10 +11,7 @@
"src\\blazor\\client\\BootstrapClient.Shared\\BootstrapClient.Web.Shared.csproj",
"src\\blazor\\client\\BootstrapClient.Web.Core\\BootstrapClient.Web.Core.csproj",
"src\\blazor\\client\\BootstrapClient.Web.Models\\BootstrapClient.DataAccess.Models.csproj",
"src\\blazor\\client\\BootstrapClient.Web\\BootstrapClient.Web.csproj",
"src\\mvc\\admin\\Bootstrap.Admin\\Bootstrap.Admin.csproj",
"src\\mvc\\admin\\Bootstrap.DataAccess\\Bootstrap.DataAccess.csproj",
"test\\UnitTest\\UnitTest.csproj"
"src\\blazor\\client\\BootstrapClient.Web\\BootstrapClient.Web.csproj"
]
}
}

View File

@ -157,7 +157,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.Web", "src\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootStarpAdmin.DataAccess.FreeSql", "src\blazor\admin\BootStarpAdmin.DataAccess.FreeSql\BootStarpAdmin.DataAccess.FreeSql.csproj", "{11122D97-B349-4A3E-B7DD-73B8B363C47C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootStarpAdmin.DataAccess.SqlSugar", "src\blazor\admin\BootStarpAdmin.DataAccess.SqlSugar\BootStarpAdmin.DataAccess.SqlSugar.csproj", "{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootStarpAdmin.DataAccess.SqlSugar", "src\blazor\admin\BootStarpAdmin.DataAccess.SqlSugar\BootStarpAdmin.DataAccess.SqlSugar.csproj", "{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.Web.Core", "src\blazor\client\BootstrapClient.Web.Core\BootstrapClient.Web.Core.csproj", "{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}"
EndProject

184
README.md
View File

@ -1,178 +1,8 @@
# BootstrapAdmin
# 第一点
## 部署手册
<span>English</span> | <a href="README.zh-CN.md">中文</a>
---
##### Version & Coverage
[![Release](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=red&color=green&label=release&url=https://admin.blazor.zone/api/Gitee/Releases?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/releases)
[![Coveralls](https://img.shields.io/coveralls/github/ArgoZhang/BootstrapAdmin/master.svg?logo=ReverbNation&logoColor=green&label=coveralls)](https://coveralls.io/github/ArgoZhang/BootstrapAdmin)
[![Codecov](https://img.shields.io/codecov/c/gh/argozhang/bootstrapadmin/master.svg?logo=codecov&label=codecov)](https://codecov.io/gh/argozhang/bootstrapadmin/branch/master)
##### Gitee
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://admin.blazor.zone/api/Gitee/Builds?projName=bootstrapadmin-9m1jm)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm)
[![Build Status](https://img.shields.io/appveyor/ci/ArgoZhang/bootstrapadmin-9m1jm/master.svg?logo=appveyor&label=master)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm/branch/master)
[![Test](https://img.shields.io/appveyor/tests/ArgoZhang/bootstrapadmin-9m1jm/master.svg?logo=appveyor&)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm/branch/master/tests)
[![Issue Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=critical&label=issues&url=https://admin.blazor.zone/api/Gitee/Issues?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues)
[![Pull Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=green&color=success&label=pulls&url=https://admin.blazor.zone/api/Gitee/Pulls?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/pulls)
##### GitHub
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://admin.blazor.zone/api/Gitee/Builds?projName=bootstrapadmin)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin)
[![master status](https://img.shields.io/appveyor/ci/ArgoZhang/bootstrapadmin/master.svg?logo=appveyor&label=master)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin/branch/master)
[![Test](https://img.shields.io/appveyor/tests/argozhang/bootstrapadmin/master.svg?logo=appveyor&)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin/branch/master/tests)
[![Github build](https://img.shields.io/github/workflow/status/ArgoZhang/BootstrapAdmin/Auto%20Build%20CI/master?label=master&logoColor=green&logo=github)](https://github.com/ArgoZhang/BootstrapAdmin/actions?query=workflow%3A%22Auto+Build+CI%22+branch%3Amaster)
[![Repo Size](https://img.shields.io/github/repo-size/ArgoZhang/BootstrapAdmin.svg?logo=github&logoColor=green&label=repo)](https://github.com/ArgoZhang/BootstrapAdmin)
[![Commit Date](https://img.shields.io/github/last-commit/ArgoZhang/BootstrapAdmin/master.svg?logo=github&logoColor=green&label=commit)](https://github.com/ArgoZhang/BootstrapAdmin)
## Introduce
Because the dependent on Bootstrap v4, so it is called **Bootstrap Admin**. This system can be integrated with asp.net and asp.net core applications. The database supports multiple databases at the same time. The detailed list is shown in the following **database** detailed list. Switching the data source only needs to change the configuration file without restarting the application. The configuration is simple and flexible. The UI front-end uses the popular Bootstrap framework layout, which is very compatible with mobile devices and adapts to almost all terminal devices in the current market. The system also has the feature of single background supporting multi-front desk, and provides the ability of **single sign-on (SSO)**.
### Notes
Bootstrap Admin does not require secondary development, but only integration with the front-end system. The front-end system model project is **Bootstrap. Client**
The original starting point of the project is to separate the privilege system from the business system. The project development focuses on functions. For detailed configuration instructions, please click on [View Documents](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E7%B3%BB%E7%BB%9F%E9%89B%86%E6%88%90).
### Features
1. Integration with Front-end Website through Configuration
2. Constructing Hierarchical Menu of Front-end System
3. Provide a single background to support multiple front-end application configurations
4. Provide single sign-on(SSO)
5. Integrated System Authentication and Authorization Module
6. Provide role, department, user, menu, foreground application authorization
Role Authorization to Users
Role-to-Menu Authorization
Role Authorization to Departments
Role-to-application authorization (multiple front-end applications share a back-end privilege management system)
Departments Authorize Users
7. Provide dictionary tables for personalized configuration of front-end websites
8. Fully responsive layout (supporting all mainstream devices such as computers, tablets, mobile phones, etc.)
9. Built-in multi-data source support, simple configuration and immediate effect without restart
10. Built-in data memory caching mechanism, page fast response
11. Built-in Data **Operation Log** and User **Log on**
[Update log](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/更新日志)
### Advantage
1. The front-end system does not need to write login, authorization and authentication modules; it is only responsible for writing business modules.
2. Background system can be used directly without any secondary development.
3. Front-end and back-end systems are separated, which are different systems (domain name can be independent)
4. Extensible to multi-tenant applications
For more information, please click [wiki](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D)
### Database
**MSSQL/Oracle/SQLite/MySql/MariaDB/Firebird/MongoDB**
For more information, please click [wiki](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/数据库连接配置?sort_id=1333482)
### Browser
![chrome](https://img.shields.io/badge/chrome->%3D4.5-success.svg?logo=google%20chrome&logoColor=red)
![firefox](https://img.shields.io/badge/firefox->38-success.svg?logo=mozilla%20firefox&logoColor=red)
![edge](https://img.shields.io/badge/edge->%3D12-success.svg?logo=microsoft%20edge&logoColor=blue)
![ie](https://img.shields.io/badge/ie->%3D11-success.svg?logo=internet%20explorer&logoColor=blue)
![Safari](https://img.shields.io/badge/safari->%3D9-success.svg?logo=safari&logoColor=blue)
![Andriod](https://img.shields.io/badge/andriod->%3D4.4-success.svg?logo=android)
![oper](https://img.shields.io/badge/opera->%3D3.0-success.svg?logo=opera&logoColor=red)
```json
"browserslist": [
"Chrome >= 45",
"Firefox >= 38",
"Edge >= 12",
"Explorer >= 11",
"iOS >= 9",
"Safari >= 9",
"Android >= 4.4",
"Opera >= 30"
]
```
### Mobile
![ios](https://img.shields.io/badge/ios-supported-success.svg?logo=apple&logoColor=white)
![Andriod](https://img.shields.io/badge/andriod-suported-success.svg?logo=android)
![windows](https://img.shields.io/badge/windows-suported-success.svg?logo=windows&logoColor=blue)
| | **Chrome** | **Firefox** | **Safari** | **Android Browser & WebView** | **Microsoft Edge** |
| ------- | --------- | --------- | ------ | ------------------------- | -------------- |
| **iOS** | Supported | Supported | Supported | N/A | Supported |
| **Android** | Supported | Supported | N/A | Android v5.0+ supported | Supported |
| **Windows 10 Mobile** | N/A | N/A | N/A | N/A | Supported |
### Desktop
![macOS](https://img.shields.io/badge/macOS-supported-success.svg?logo=apple&logoColor=white)
![linux](https://img.shields.io/badge/linux-suported-success.svg?logo=linux&logoColor=white)
![windows](https://img.shields.io/badge/windows-suported-success.svg?logo=windows)
| | Chrome | Firefox | Internet Explorer | Microsoft Edge | Opera | Safari |
| ------- | --------- | --------- | ----------------- | -------------- | --------- | ------------- |
| Mac | Supported | Supported | N/A | N/A | Supported | Supported |
| Linux | Supported | Supported | N/A | N/A | N/A | N/A |
| Windows | Supported | Supported | Supported, IE10+ | Supported | Supported | Not supported |
## QQ Group
[![QQ](https://img.shields.io/badge/QQ-795206915-green.svg?logo=tencent%20qq&logoColor=red)](https://shang.qq.com/wpa/qunwpa?idkey=d381355e50ff91db410c3da3eadb081ba859f64c2877e86343f4709b171f28b8)
## Installation
1. Install .net core sdk [Offical website](http://www.microsoft.com/net/download)
2. Install Visual Studio 2019 lastest [Offical website](https://visualstudio.microsoft.com/vs/getting-started/)
3. Git clone `git clone https://gitee.com/LongbowEnterprise/BootstrapAdmin.git`
4. Login as Admin/123789
## Branchs
[Details](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/分支说明)
## Online Demonstration
[![website1](https://img.shields.io/badge/linux-http://ba.zylweb.cn-success.svg?logo=buzzfeed&logoColor=green)](http://ba.zylweb.cn)
[![website2](https://img.shields.io/badge/linux-http://admin.blazor.zone-success.svg?logo=buzzfeed&logoColor=green)](http://admin.blazor.zone)
### Login
Administrator: Admin/123789
User: User/123789
## Docker Images
[![Docker](https://img.shields.io/docker/cloud/automated/argozhang/ba.svg?logo=docker&logoColor=success)](https://hub.docker.com/r/argozhang/ba)
[![Docker](https://img.shields.io/docker/cloud/build/argozhang/ba.svg?logo=docker&logoColor=success)](https://hub.docker.com/r/argozhang/ba/builds)
[![Docker](https://img.shields.io/github/workflow/status/ArgoZhang/BootstrapAdmin/Docker%20Image%20CI/master?label=Docker%20Image%20CI&logo=github&logoColor=green)](https://github.com/ArgoZhang/BootstrapAdmin/actions?query=workflow%3A%22Docker+Image+CI%22%3Amaster)
### Docker Hub
Mirror [Portal](https://hub.docker.com/r/argozhang/ba)
```bash
docker pull argozhang/ba
```
### Qiniu Cloud:
Mirror [Portal](https://hub.qiniu.com/store/argozhang/ba)
```bash
docker pull reg.qiniu.com/argozhang/ba
```
## Configurations
Detailed configuration instructions please click [wikis](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis)
## Q&A
Please click [wikis](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98Q&A)
## License
[![Gitee license](https://img.shields.io/github/license/argozhang/bootstrapadmin.svg?logo=git&logoColor=red)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/blob/master/LICENSE)
## GVP award
[View](https://images.gitee.com/uploads/images/2021/0112/112021_9d570be1_554725.png "GiteeGVP.png")
## Screenshots
Home
![Home](https://gitee.com/LongbowEnterprise/Pictures/raw/master/BootstrapAdmin/BA02-01.png "BAHome-01.png")
For more screenshots, Click [wiki](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis)
## Contribution
1. Fork
2. Create Feat_xxx branch
3. Commit
4. Create Pull Request
## Donate
If this project is helpful to you, please scan the QR code below for a cup of coffee.
![WeChat](https://gitee.com/LongbowEnterprise/Pictures/raw/master/WeChat/WeChat.png "WeChat")
# 第二点
## 环境要求
# 第三点
## 软件要求

View File

@ -143,16 +143,6 @@ CREATE TABLE Tasks(
AssignTime DATE NOT NULL
);
CREATE TABLE RejectUsers(
ID SERIAL PRIMARY KEY,
UserName VARCHAR (50) NOT NULL,
DisplayName VARCHAR (50) NOT NULL,
RegisterTime DATE NOT NULL,
RejectedBy VARCHAR (50) NOT NULL,
RejectedTime DATE NOT NULL,
RejectedReason VARCHAR (50) NULL
);
CREATE TABLE RejectUsers(
ID SERIAL PRIMARY KEY,
UserName VARCHAR (50) NOT NULL,

View File

@ -6,8 +6,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.*" />
<PackageReference Include="FreeSql.Provider.Sqlite" Version="3.0.100" />
<PackageReference Include="BootstrapBlazor" Version="6.8.13" />
<PackageReference Include="FreeSql.Provider.Sqlite" Version="3.2.665" />
</ItemGroup>
</Project>

View File

@ -24,6 +24,10 @@ static class FreeSqlExtensions
i.Property(n => n.Period).IsIgnore(true);
i.Property(n => n.IsReset).IsIgnore(true);
});
freeSql.CodeFirst.ConfigEntity<Trace>(i =>
{
i.Name("Traces");
});
freeSql.CodeFirst.ConfigEntity<Group>(i =>
{
i.Name("Groups");

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.*" />
<PackageReference Include="SqlSugarCore" Version="5.0.5.2" />
<PackageReference Include="BootstrapBlazor" Version="6.8.13" />
<PackageReference Include="SqlSugarCore" Version="5.0.9.7" />
</ItemGroup>
<ItemGroup>

View File

@ -8,7 +8,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
</ItemGroup>
</Project>

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.1" />
<PackageReference Include="BootstrapBlazor" Version="6.8.13" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.7" />
</ItemGroup>
<ItemGroup>

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.*" />
<PackageReference Include="Longbow.Security.Cryptography" Version="5.2.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.1" />
<PackageReference Include="BootstrapBlazor" Version="6.8.13" />
<PackageReference Include="Longbow.Security.Cryptography" Version="6.0.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.7" />
<PackageReference Include="PetaPoco.Extensions" Version="6.0.0" />
</ItemGroup>

View File

@ -6,7 +6,6 @@ using BootstrapAdmin.DataAccess.PetaPoco;
using BootstrapAdmin.DataAccess.PetaPoco.Services;
using BootstrapAdmin.Web.Core;
using BootstrapBlazor.Components;
using BootstrapBlazor.DataAcces.PetaPoco.Services;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
@ -27,43 +26,10 @@ public static class ServiceCollectionExtensions
///
/// </summary>
/// <param name="services"></param>
/// <param name="builder"></param>
/// <returns></returns>
public static IServiceCollection AddPetaPocoDataAccessServices(this IServiceCollection services, Action<IServiceProvider, IDatabaseBuildConfiguration> builder)
public static IServiceCollection AddPetaPocoDataAccessServices(this IServiceCollection services)
{
services.TryAddSingleton<IDatabase>(provider =>
{
var option = DatabaseConfiguration.Build();
builder(provider, option);
option.UsingDefaultMapper<BootstrapAdminConventionMapper>();
var db = new Database(option);
var logger = provider.GetRequiredService<ILogger<Database>>();
db.ExceptionThrown += (sender, e) =>
{
var message = e.Exception.Format(new NameValueCollection()
{
[nameof(db.LastCommand)] = db.LastCommand,
[nameof(db.LastArgs)] = string.Join(",", db.LastArgs)
});
logger.LogError(new EventId(1001, "GlobalException"), e.Exception, message);
};
var env = provider.GetRequiredService<IWebHostEnvironment>();
if (env.IsDevelopment())
{
db.CommandExecuted += (sender, args) =>
{
var parameters = new StringBuilder();
foreach (DbParameter p in args.Command.Parameters)
{
parameters.AppendFormat("{0}: {1} ", p.ParameterName, p.Value);
}
logger.LogInformation(args.Command.CommandText);
logger.LogInformation(parameters.ToString());
};
};
return db;
});
services.TryAddSingleton<IDBManager, DBManagerService>();
// 增加数据服务
services.AddSingleton(typeof(IDataService<>), typeof(DefaultDataService<>));

View File

@ -12,29 +12,34 @@ class AppService : IApp
{
private const string AppServiceGetAppsByRoleIdCacheKey = "AppService-GetAppsByRoleId";
private IDatabase Database { get; }
private IDBManager DBManager { get; }
public AppService(IDatabase db)
public AppService(IDBManager db)
{
Database = db;
DBManager = db;
}
public List<string> GetAppsByRoleId(string? roleId) => CacheManager.GetOrAdd($"{AppServiceGetAppsByRoleIdCacheKey}-{roleId}", entry => Database.Fetch<string>("select AppID from RoleApp where RoleID = @0", roleId));
public List<string> GetAppsByRoleId(string? roleId) => CacheManager.GetOrAdd($"{AppServiceGetAppsByRoleIdCacheKey}-{roleId}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>("select AppID from RoleApp where RoleID = @0", roleId);
});
public bool SaveAppsByRoleId(string? roleId, IEnumerable<string> appIds)
{
var ret = false;
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
Database.Execute("delete from RoleApp where RoleID = @0", roleId);
Database.InsertBatch("RoleApp", appIds.Select(g => new { AppID = g, RoleID = roleId }));
Database.CompleteTransaction();
db.BeginTransaction();
db.Execute("delete from RoleApp where RoleID = @0", roleId);
db.InsertBatch("RoleApp", appIds.Select(g => new { AppID = g, RoleID = roleId }));
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
if (ret)

View File

@ -0,0 +1,78 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapBlazor.Components;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using PetaPoco;
using PetaPoco.Providers;
using System.Collections.Specialized;
using System.Data.Common;
using System.Text;
namespace BootstrapAdmin.DataAccess.PetaPoco.Services;
internal class DBManagerService : IDBManager
{
private IConfiguration Configuration { get; set; }
private ILogger<DBManagerService> Logger { get; set; }
private IWebHostEnvironment WebHost { get; set; }
public DBManagerService(IConfiguration configuration, ILogger<DBManagerService> logger, IWebHostEnvironment host)
{
Configuration = configuration;
Logger = logger;
WebHost = host;
}
/// <summary>
/// 创建 IDatabase 实例方法
/// </summary>
/// <param name="connectionName">连接字符串键值</param>
/// <param name="keepAlive"></param>
/// <returns></returns>
public IDatabase Create(string? connectionName = "ba", bool keepAlive = false)
{
var conn = Configuration.GetConnectionString(connectionName) ?? throw new ArgumentNullException(nameof(connectionName));
var option = DatabaseConfiguration.Build();
option.UsingDefaultMapper<BootstrapAdminConventionMapper>();
// connectionstring
option.UsingConnectionString(conn);
// provider
option.UsingProvider<SQLiteDatabaseProvider>();
var db = new Database(option) { KeepConnectionAlive = keepAlive };
db.ExceptionThrown += (sender, e) =>
{
var message = e.Exception.Format(new NameValueCollection()
{
[nameof(db.LastCommand)] = db.LastCommand,
[nameof(db.LastArgs)] = string.Join(",", db.LastArgs)
});
Logger.LogError(new EventId(1001, "GlobalException"), e.Exception, message);
};
if (WebHost.IsDevelopment())
{
db.CommandExecuted += (sender, args) =>
{
var parameters = new StringBuilder();
foreach (DbParameter p in args.Command.Parameters)
{
parameters.AppendFormat("{0}: {1} ", p.ParameterName, p.Value);
}
Logger.LogInformation(args.Command.CommandText);
Logger.LogInformation(parameters.ToString());
};
};
return db;
}
}

View File

@ -9,21 +9,21 @@ using BootstrapBlazor.Components;
using PetaPoco;
using PetaPoco.Extensions;
namespace BootstrapBlazor.DataAcces.PetaPoco.Services;
namespace BootstrapAdmin.DataAccess.PetaPoco.Services;
/// <summary>
/// PetaPoco ORM 的 IDataService 接口实现
/// </summary>
class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class, new()
{
private IDatabase Database { get; }
private IDBManager DBManager { get; }
private IUser UserService { get; }
/// <summary>
/// 构造函数
/// </summary>
public DefaultDataService(IDatabase db, IUser userService) => (Database, UserService) = (db, userService);
public DefaultDataService(IDBManager db, IUser userService) => (DBManager, UserService) = (db, userService);
/// <summary>
/// 删除方法
@ -34,7 +34,8 @@ class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class,
{
// 通过模型获取主键列数据
// 支持批量删除
Database.DeleteBatch(models);
using var db = DBManager.Create();
db.DeleteBatch(models);
return Task.FromResult(true);
}
@ -52,13 +53,14 @@ class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class,
}
else
{
using var db = DBManager.Create();
if (changedType == ItemChangedType.Add)
{
await Database.InsertAsync(model);
await db.InsertAsync(model);
}
else
{
await Database.UpdateAsync(model);
await db.UpdateAsync(model);
}
}
return true;
@ -79,16 +81,17 @@ class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class,
IsAdvanceSearch = option.AdvanceSearchs.Any() || option.CustomerSearchs.Any()
};
using var db = DBManager.Create();
if (option.IsPage)
{
var items = await Database.PageAsync<TModel>(option);
var items = await db.PageAsync<TModel>(option);
ret.TotalCount = Convert.ToInt32(items.TotalItems);
ret.Items = items.Items;
}
else
{
var items = await Database.FetchAsync<TModel>(option);
var items = await db.FetchAsync<TModel>(option);
ret.TotalCount = items.Count;
ret.Items = items;
}

View File

@ -17,7 +17,7 @@ class DictService : IDict
{
private const string DictServiceCacheKey = "DictService-GetAll";
private IDatabase Database { get; }
private IDBManager DBManager { get; }
private string AppId { get; set; }
@ -26,13 +26,17 @@ class DictService : IDict
/// </summary>
/// <param name="db"></param>
/// <param name="configuration"></param>
public DictService(IDatabase db, IConfiguration configuration)
public DictService(IDBManager db, IConfiguration configuration)
{
Database = db;
DBManager = db;
AppId = configuration.GetValue("AppId", "BA");
}
public List<Dict> GetAll() => CacheManager.GetOrAdd(DictServiceCacheKey, entry => Database.Fetch<Dict>());
public List<Dict> GetAll() => CacheManager.GetOrAdd(DictServiceCacheKey, entry =>
{
using var db = DBManager.Create();
return db.Fetch<Dict>();
});
public Dictionary<string, string> GetApps()
{
@ -178,7 +182,8 @@ class DictService : IDict
private bool SaveDict(Dict dict)
{
var ret = Database.Update<Dict>("set Code = @Code where Category = @Category and Name = @Name", dict) == 1;
using var db = DBManager.Create();
var ret = db.Update<Dict>("set Code = @Code where Category = @Category and Name = @Name", dict) == 1;
if (ret)
{
// 更新缓存
@ -417,9 +422,10 @@ class DictService : IDict
if (!string.IsNullOrEmpty(client.AppId))
{
DeleteClient(client.AppId);
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
db.BeginTransaction();
var items = new List<Dict>()
{
new Dict { Category = "应用程序", Name = client.AppName, Code = client.AppId, Define = EnumDictDefine.System },
@ -432,13 +438,13 @@ class DictService : IDict
new Dict { Category = client.AppId, Name = "系统设置地址", Code = client.SettingsUrl, Define = EnumDictDefine.Customer },
new Dict { Category = client.AppId, Name = "系统通知地址", Code = client.NotificationUrl, Define = EnumDictDefine.Customer }
};
Database.InsertBatch(items);
Database.CompleteTransaction();
db.InsertBatch(items);
db.CompleteTransaction();
ret = true;
}
catch (DbException)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
}
@ -466,12 +472,13 @@ class DictService : IDict
public bool DeleteClient(string appId)
{
bool ret;
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
Database.Execute("delete Dicts where Category=@0 and Name=@1 and Define=@2", "应用首页", appId, EnumDictDefine.System);
Database.Execute("delete Dicts where Category=@0 and Code=@1 and Define=@2", "应用程序", appId, EnumDictDefine.System);
Database.Execute("delete Dicts where Category=@Category and Name in (@Names)", new
db.BeginTransaction();
db.Execute("delete Dicts where Category=@0 and Name=@1 and Define=@2", "应用首页", appId, EnumDictDefine.System);
db.Execute("delete Dicts where Category=@0 and Code=@1 and Define=@2", "应用程序", appId, EnumDictDefine.System);
db.Execute("delete Dicts where Category=@Category and Name in (@Names)", new
{
Category = appId,
Names = new List<string>
@ -485,12 +492,12 @@ class DictService : IDict
"系统通知地址"
}
});
Database.CompleteTransaction();
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
return ret;

View File

@ -10,15 +10,16 @@ namespace BootstrapAdmin.DataAccess.PetaPoco.Services;
class ExceptionService : IException
{
private IDatabase Database { get; }
private IDBManager DBManager { get; }
public ExceptionService(IDatabase db) => Database = db;
public ExceptionService(IDBManager db) => DBManager = db;
public bool Log(Error exception)
{
try
{
Database.Insert(exception);
using var db = DBManager.Create();
db.Insert(exception);
}
catch { }
return true;
@ -59,7 +60,8 @@ class ExceptionService : IException
sql.OrderBy("Logtime desc", "ErrorPage", "UserId");
}
var data = Database.Page<Error>(pageIndex, pageItems, sql);
using var db = DBManager.Create();
var data = db.Page<Error>(pageIndex, pageItems, sql);
return (data.Items, Convert.ToInt32(data.TotalItems));
}
}

View File

@ -17,26 +17,34 @@ class GroupService : IGroup
private const string GroupServiceGetGroupsByRoleIdCacheKey = "GroupService-GetGroupsByRoleId";
private IDatabase Database { get; }
private IDBManager DBManager { get; }
/// <summary>
///
/// </summary>
/// <param name="db"></param>
public GroupService(IDatabase db) => Database = db;
public GroupService(IDBManager db) => DBManager = db;
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<Group> GetAll() => CacheManager.GetOrAdd(GroupServiceGetAllCacheKey, entry => Database.Fetch<Group>());
public List<Group> GetAll() => CacheManager.GetOrAdd(GroupServiceGetAllCacheKey, entry =>
{
using var db = DBManager.Create();
return db.Fetch<Group>();
});
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public List<string> GetGroupsByUserId(string? userId) => CacheManager.GetOrAdd($"{GroupServiceGetGroupsByUserIdCacheKey}-{userId}", entry => Database.Fetch<string>("select GroupID from UserGroup where UserID = @0", userId));
public List<string> GetGroupsByUserId(string? userId) => CacheManager.GetOrAdd($"{GroupServiceGetGroupsByUserIdCacheKey}-{userId}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>("select GroupID from UserGroup where UserID = @0", userId);
});
/// <summary>
///
@ -47,17 +55,18 @@ class GroupService : IGroup
public bool SaveGroupsByUserId(string? userId, IEnumerable<string> groupIds)
{
var ret = false;
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
Database.Execute("delete from UserGroup where UserID = @0", userId);
Database.InsertBatch("UserGroup", groupIds.Select(g => new { GroupID = g, UserID = userId }));
Database.CompleteTransaction();
db.BeginTransaction();
db.Execute("delete from UserGroup where UserID = @0", userId);
db.InsertBatch("UserGroup", groupIds.Select(g => new { GroupID = g, UserID = userId }));
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
if (ret)
@ -72,7 +81,11 @@ class GroupService : IGroup
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public List<string> GetGroupsByRoleId(string? roleId) => CacheManager.GetOrAdd($"{GroupServiceGetGroupsByRoleIdCacheKey}-{roleId}", entry => Database.Fetch<string>("select GroupID from RoleGroup where RoleID = @0", roleId));
public List<string> GetGroupsByRoleId(string? roleId) => CacheManager.GetOrAdd($"{GroupServiceGetGroupsByRoleIdCacheKey}-{roleId}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>("select GroupID from RoleGroup where RoleID = @0", roleId);
});
/// <summary>
///
@ -83,17 +96,18 @@ class GroupService : IGroup
public bool SaveGroupsByRoleId(string? roleId, IEnumerable<string> groupIds)
{
var ret = false;
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
Database.Execute("delete from RoleGroup where RoleID = @0", roleId);
Database.InsertBatch("RoleGroup", groupIds.Select(g => new { GroupID = g, RoleID = roleId }));
Database.CompleteTransaction();
db.BeginTransaction();
db.Execute("delete from RoleGroup where RoleID = @0", roleId);
db.InsertBatch("RoleGroup", groupIds.Select(g => new { GroupID = g, RoleID = roleId }));
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}

View File

@ -0,0 +1,19 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using PetaPoco;
namespace BootstrapAdmin.DataAccess.PetaPoco.Services;
/// <summary>
///
/// </summary>
public interface IDBManager
{
/// <summary>
///
/// </summary>
/// <returns></returns>
IDatabase Create(string? connectionName = "ba", bool keepAlive = false);
}

View File

@ -4,15 +4,14 @@
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using PetaPoco;
namespace BootstrapAdmin.DataAccess.PetaPoco.Services;
class LoginService : ILogin
{
private IDatabase Database { get; }
private IDBManager DBManager { get; }
public LoginService(IDatabase database) => Database = database;
public LoginService(IDBManager database) => DBManager = database;
/// <summary>
///
@ -38,7 +37,8 @@ class LoginService : ILogin
UserAgent = userAgent,
Result = result ? "登录成功" : "登录失败"
};
Database.Insert(loginUser);
using var db = DBManager.Create();
db.Insert(loginUser);
return true;
}
}

View File

@ -18,13 +18,16 @@ class NavigationService : INavigation
private const string NavigationServiceGetMenusByRoleIdCacheKey = "NavigationService-GetMenusByRoleId";
private IDatabase Database { get; }
private IDBManager DBManager { get; }
/// <summary>
///
/// </summary>
/// <param name="db"></param>
public NavigationService(IDatabase db) => Database = db;
public NavigationService(IDBManager db)
{
DBManager = db;
}
/// <summary>
/// 获得指定用户名可访问的所有菜单集合
@ -33,9 +36,10 @@ class NavigationService : INavigation
/// <returns>未层次化的菜单集合</returns>
public List<Navigation> GetAllMenus(string userName) => CacheManager.GetOrAdd($"{NavigationServiceGetAllCacheKey}-{userName}", entry =>
{
using var db = DBManager.Create();
// 缓存所有菜单数据移除 SQL 语句降低复杂度
var order = Database.Provider.EscapeSqlIdentifier("Order");
return Database.Fetch<Models.Navigation>($"select n.ID, n.ParentId, n.Name, n.{order}, n.Icon, n.Url, n.Category, n.Target, n.IsResource, n.Application from Navigations n inner join (select nr.NavigationID from Users u inner join UserRole ur on ur.UserID = u.ID inner join NavigationRole nr on nr.RoleID = ur.RoleID where u.UserName = @UserName union select nr.NavigationID from Users u inner join UserGroup ug on u.ID = ug.UserID inner join RoleGroup rg on rg.GroupID = ug.GroupID inner join NavigationRole nr on nr.RoleID = rg.RoleID where u.UserName = @UserName union select n.ID from Navigations n where EXISTS (select UserName from Users u inner join UserRole ur on u.ID = ur.UserID inner join Roles r on ur.RoleID = r.ID where u.UserName = @UserName and r.RoleName = @RoleName)) nav on n.ID = nav.NavigationID ORDER BY n.Application, n.{order}", new { UserName = userName, RoleName = "Administrators" });
var order = db.Provider.EscapeSqlIdentifier("Order");
return db.Fetch<Models.Navigation>($"select n.ID, n.ParentId, n.Name, n.{order}, n.Icon, n.Url, n.Category, n.Target, n.IsResource, n.Application from Navigations n inner join (select nr.NavigationID from Users u inner join UserRole ur on ur.UserID = u.ID inner join NavigationRole nr on nr.RoleID = ur.RoleID where u.UserName = @UserName union select nr.NavigationID from Users u inner join UserGroup ug on u.ID = ug.UserID inner join RoleGroup rg on rg.GroupID = ug.GroupID inner join NavigationRole nr on nr.RoleID = rg.RoleID where u.UserName = @UserName union select n.ID from Navigations n where EXISTS (select UserName from Users u inner join UserRole ur on u.ID = ur.UserID inner join Roles r on ur.RoleID = r.ID where u.UserName = @UserName and r.RoleName = @RoleName)) nav on n.ID = nav.NavigationID ORDER BY n.Application, n.{order}", new { UserName = userName, RoleName = "Administrators" });
});
/// <summary>
@ -43,7 +47,11 @@ class NavigationService : INavigation
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public List<string> GetMenusByRoleId(string? roleId) => CacheManager.GetOrAdd($"{NavigationServiceGetMenusByRoleIdCacheKey}-{roleId}", entry => Database.Fetch<string>("select NavigationID from NavigationRole where RoleID = @0", roleId));
public List<string> GetMenusByRoleId(string? roleId) => CacheManager.GetOrAdd($"{NavigationServiceGetMenusByRoleIdCacheKey}-{roleId}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>("select NavigationID from NavigationRole where RoleID = @0", roleId);
});
/// <summary>
///
@ -54,17 +62,18 @@ class NavigationService : INavigation
public bool SaveMenusByRoleId(string? roleId, List<string> menuIds)
{
var ret = false;
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
Database.Execute("delete from NavigationRole where RoleID = @0", roleId);
Database.InsertBatch("NavigationRole", menuIds.Select(g => new { NavigationID = g, RoleID = roleId }));
Database.CompleteTransaction();
db.BeginTransaction();
db.Execute("delete from NavigationRole where RoleID = @0", roleId);
db.InsertBatch("NavigationRole", menuIds.Select(g => new { NavigationID = g, RoleID = roleId }));
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
if (ret)

View File

@ -19,25 +19,44 @@ class RoleService : IRole
private const string RoleServiceGetRolesByMenuIdCacheKey = "RoleService-GetRolesByMenusId";
private IDatabase Database { get; }
private IDBManager DBManager { get; }
/// <summary>
///
/// </summary>
/// <param name="db"></param>
public RoleService(IDatabase db) => Database = db;
public RoleService(IDBManager db)
{
DBManager = db;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<Role> GetAll() => CacheManager.GetOrAdd(RoleServiceGetAllCacheKey, entry => CacheManager.GetOrAdd(RoleServiceGetAllCacheKey, entry => Database.Fetch<Role>()));
public List<Role> GetAll() => CacheManager.GetOrAdd(RoleServiceGetAllCacheKey, entry => CacheManager.GetOrAdd(RoleServiceGetAllCacheKey, entry =>
{
using var db = DBManager.Create();
return db.Fetch<Role>();
}));
public List<string> GetRolesByGroupId(string? groupId) => CacheManager.GetOrAdd($"{RoleServiceGetRolesByGroupIdCacheKey}-{groupId}", entry => Database.Fetch<string>("select RoleID from RoleGroup where GroupID = @0", groupId));
public List<string> GetRolesByGroupId(string? groupId) => CacheManager.GetOrAdd($"{RoleServiceGetRolesByGroupIdCacheKey}-{groupId}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>("select RoleID from RoleGroup where GroupID = @0", groupId);
});
public List<string> GetRolesByUserId(string? userId) => CacheManager.GetOrAdd($"{RoleServiceGetRolesByUserIdCacheKey}-{userId}", entry => Database.Fetch<string>("select RoleID from UserRole where UserID = @0", userId));
public List<string> GetRolesByUserId(string? userId) => CacheManager.GetOrAdd($"{RoleServiceGetRolesByUserIdCacheKey}-{userId}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>("select RoleID from UserRole where UserID = @0", userId);
});
public List<string> GetRolesByMenuId(string? menuId) => CacheManager.GetOrAdd($"{RoleServiceGetRolesByMenuIdCacheKey}-{menuId}", entry => Database.Fetch<string>("select RoleID from NavigationRole where NavigationID = @0", menuId));
public List<string> GetRolesByMenuId(string? menuId) => CacheManager.GetOrAdd($"{RoleServiceGetRolesByMenuIdCacheKey}-{menuId}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>("select RoleID from NavigationRole where NavigationID = @0", menuId);
});
/// <summary>
///
@ -48,17 +67,18 @@ class RoleService : IRole
public bool SaveRolesByGroupId(string? groupId, IEnumerable<string> roleIds)
{
var ret = false;
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
Database.Execute("delete from RoleGroup where GroupID = @0", groupId);
Database.InsertBatch("RoleGroup", roleIds.Select(g => new { RoleID = g, GroupID = groupId }));
Database.CompleteTransaction();
db.BeginTransaction();
db.Execute("delete from RoleGroup where GroupID = @0", groupId);
db.InsertBatch("RoleGroup", roleIds.Select(g => new { RoleID = g, GroupID = groupId }));
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
if (ret)
@ -77,17 +97,18 @@ class RoleService : IRole
public bool SaveRolesByUserId(string? userId, IEnumerable<string> roleIds)
{
var ret = false;
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
Database.Execute("delete from UserRole where UserID = @0", userId);
Database.InsertBatch("UserRole", roleIds.Select(g => new { RoleID = g, UserID = userId }));
Database.CompleteTransaction();
db.BeginTransaction();
db.Execute("delete from UserRole where UserID = @0", userId);
db.InsertBatch("UserRole", roleIds.Select(g => new { RoleID = g, UserID = userId }));
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
if (ret)
@ -100,17 +121,18 @@ class RoleService : IRole
public bool SaveRolesByMenuId(string? menuId, IEnumerable<string> roleIds)
{
var ret = false;
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
Database.Execute("delete from NavigationRole where NavigationID = @0", menuId);
Database.InsertBatch("NavigationRole", roleIds.Select(g => new { RoleID = g, NavigationID = menuId }));
Database.CompleteTransaction();
db.BeginTransaction();
db.Execute("delete from NavigationRole where NavigationID = @0", menuId);
db.InsertBatch("NavigationRole", roleIds.Select(g => new { RoleID = g, NavigationID = menuId }));
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
if (ret)

View File

@ -10,13 +10,12 @@ namespace BootstrapAdmin.DataAccess.PetaPoco.Services;
class TraceService : ITrace
{
private IDatabase Database { get; }
private IDBManager DBManager { get; }
/// <summary>
///
/// </summary>
/// <param name="db"></param>
public TraceService(IDatabase db) => Database = db;
public TraceService(IDBManager db)
{
DBManager = db;
}
/// <summary>
///
@ -24,7 +23,8 @@ class TraceService : ITrace
/// <param name="trace"></param>
public void Log(Trace trace)
{
Database.Insert(trace);
using var db = DBManager.Create();
db.Insert(trace);
}
/// <summary>
@ -39,7 +39,6 @@ class TraceService : ITrace
public (IEnumerable<Trace> Items, int ItemsCount) GetAll(string? searchText, TraceFilter filter, int pageIndex, int pageItems, List<string> sortList)
{
var sql = new Sql();
if (!string.IsNullOrEmpty(searchText))
{
sql.Where("UserName Like @0 or Ip Like @0 or RequestUrl Like @0", $"%{searchText}%");
@ -71,7 +70,8 @@ class TraceService : ITrace
sql.OrderBy("Logtime desc");
}
var data = Database.Page<Trace>(pageIndex, pageItems, sql);
using var db = DBManager.Create();
var data = db.Page<Trace>(pageIndex, pageItems, sql);
return (data.Items, Convert.ToInt32(data.TotalItems));
}
}

View File

@ -12,19 +12,22 @@ namespace BootstrapAdmin.DataAccess.PetaPoco.Services;
class UserService : IUser
{
private IDatabase Database { get; }
private IDBManager DBManager { get; }
/// <summary>
///
/// </summary>
/// <param name="db"></param>
public UserService(IDatabase db) => Database = db;
public UserService(IDBManager db)
{
DBManager = db;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<User> GetAll() => Database.Fetch<User>();
public List<User> GetAll()
{
using var db = DBManager.Create();
return db.Fetch<User>();
}
/// <summary>
///
@ -35,7 +38,8 @@ class UserService : IUser
/// <exception cref="NotImplementedException"></exception>
public bool Authenticate(string userName, string password)
{
var user = Database.SingleOrDefault<User>("select DisplayName, Password, PassSalt from Users where ApprovedTime is not null and UserName = @0", userName);
using var db = DBManager.Create();
var user = db.SingleOrDefault<User>("select DisplayName, Password, PassSalt from Users where ApprovedTime is not null and UserName = @0", userName);
var isAuth = false;
if (user != null && !string.IsNullOrEmpty(user.PassSalt))
@ -47,11 +51,19 @@ class UserService : IUser
private const string UserServiceGetUserByUserNameCacheKey = "UserService-GetUserByUserName";
public User? GetUserByUserName(string? userName) => CacheManager.GetOrAdd($"{UserServiceGetUserByUserNameCacheKey}-{userName}", entry => string.IsNullOrEmpty(userName) ? null : Database.FirstOrDefault<User>("Where UserName = @0", userName));
public User? GetUserByUserName(string? userName) => CacheManager.GetOrAdd($"{UserServiceGetUserByUserNameCacheKey}-{userName}", entry =>
{
using var db = DBManager.Create();
return string.IsNullOrEmpty(userName) ? null : db.FirstOrDefault<User>("Where UserName = @0", userName);
});
private const string UserServiceGetAppsByUserNameCacheKey = "UserService-GetAppsByUserName";
public List<string> GetApps(string userName) => CacheManager.GetOrAdd($"{UserServiceGetAppsByUserNameCacheKey}-{userName}", entry => Database.Fetch<string>($"select d.Code from Dicts d inner join RoleApp ra on d.Code = ra.AppId inner join (select r.Id from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @0 union select r.Id from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {Database.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @0) r on ra.RoleId = r.ID union select Code from Dicts where Category = @1 and exists(select r.ID from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @0 and r.RoleName = @2 union select r.ID from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {Database.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @0 and r.RoleName = @2)", userName, "应用程序", "Administrators"));
public List<string> GetApps(string userName) => CacheManager.GetOrAdd($"{UserServiceGetAppsByUserNameCacheKey}-{userName}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>($"select d.Code from Dicts d inner join RoleApp ra on d.Code = ra.AppId inner join (select r.Id from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @0 union select r.Id from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {db.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @0) r on ra.RoleId = r.ID union select Code from Dicts where Category = @1 and exists(select r.ID from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @0 and r.RoleName = @2 union select r.ID from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {db.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @0 and r.RoleName = @2)", userName, "应用程序", "Administrators");
});
private const string UserServiceGetAppIdByUserNameCacheKey = "UserService-GetAppIdByUserName";
@ -60,7 +72,11 @@ class UserService : IUser
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public string? GetAppIdByUserName(string userName) => CacheManager.GetOrAdd($"{UserServiceGetAppIdByUserNameCacheKey}-{userName}", entry => Database.FirstOrDefault<User>("Where UserName = @0", userName)?.App);
public string? GetAppIdByUserName(string userName) => CacheManager.GetOrAdd($"{UserServiceGetAppIdByUserNameCacheKey}-{userName}", entry =>
{
using var db = DBManager.Create();
return db.FirstOrDefault<User>("Where UserName = @0", userName)?.App;
});
private const string UserServiceGetRolesByUserNameCacheKey = "UserService-GetRolesByUserName";
@ -70,7 +86,11 @@ class UserService : IUser
/// <param name="userName"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public List<string> GetRoles(string userName) => CacheManager.GetOrAdd($"{UserServiceGetRolesByUserNameCacheKey}-{userName}", entry => Database.Fetch<string>($"select r.RoleName from Roles r inner join UserRole ur on r.ID=ur.RoleID inner join Users u on ur.UserID = u.ID and u.UserName = @0 union select r.RoleName from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {Database.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID and u.UserName = @0", userName));
public List<string> GetRoles(string userName) => CacheManager.GetOrAdd($"{UserServiceGetRolesByUserNameCacheKey}-{userName}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>($"select r.RoleName from Roles r inner join UserRole ur on r.ID=ur.RoleID inner join Users u on ur.UserID = u.ID and u.UserName = @0 union select r.RoleName from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {db.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID and u.UserName = @0", userName);
});
private const string UserServiceGetUsersByGroupIdCacheKey = "UserService-GetUsersByGroupId";
@ -78,7 +98,11 @@ class UserService : IUser
///
/// </summary>
/// <param name="groupId"></param>
public List<string> GetUsersByGroupId(string? groupId) => CacheManager.GetOrAdd($"{UserServiceGetUsersByGroupIdCacheKey}-{groupId}", entry => Database.Fetch<string>("select UserID from UserGroup where GroupID = @0", groupId));
public List<string> GetUsersByGroupId(string? groupId) => CacheManager.GetOrAdd($"{UserServiceGetUsersByGroupIdCacheKey}-{groupId}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>("select UserID from UserGroup where GroupID = @0", groupId);
});
/// <summary>
///
@ -90,17 +114,18 @@ class UserService : IUser
public bool SaveUsersByGroupId(string? id, IEnumerable<string> userIds)
{
var ret = false;
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
Database.Execute("delete from UserGroup where GroupId = @0", id);
Database.InsertBatch("UserGroup", userIds.Select(g => new { UserID = g, GroupID = id }));
Database.CompleteTransaction();
db.BeginTransaction();
db.Execute("delete from UserGroup where GroupId = @0", id);
db.InsertBatch("UserGroup", userIds.Select(g => new { UserID = g, GroupID = id }));
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
if (ret)
@ -117,7 +142,11 @@ class UserService : IUser
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public List<string> GetUsersByRoleId(string? roleId) => CacheManager.GetOrAdd($"{UserServiceGetUsersByRoleIdCacheKey}-{roleId}", entry => Database.Fetch<string>("select UserID from UserRole where RoleID = @0", roleId));
public List<string> GetUsersByRoleId(string? roleId) => CacheManager.GetOrAdd($"{UserServiceGetUsersByRoleIdCacheKey}-{roleId}", entry =>
{
using var db = DBManager.Create();
return db.Fetch<string>("select UserID from UserRole where RoleID = @0", roleId);
});
/// <summary>
///
@ -128,17 +157,18 @@ class UserService : IUser
public bool SaveUsersByRoleId(string? roleId, IEnumerable<string> userIds)
{
var ret = false;
using var db = DBManager.Create();
try
{
Database.BeginTransaction();
Database.Execute("delete from UserRole where RoleID = @0", roleId);
Database.InsertBatch("UserRole", userIds.Select(g => new { UserID = g, RoleID = roleId }));
Database.CompleteTransaction();
db.BeginTransaction();
db.Execute("delete from UserRole where RoleID = @0", roleId);
db.InsertBatch("UserRole", userIds.Select(g => new { UserID = g, RoleID = roleId }));
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
if (ret)
@ -157,12 +187,13 @@ class UserService : IUser
public bool ChangePassword(string userName, string password, string newPassword)
{
var ret = false;
using var db = DBManager.Create();
if (Authenticate(userName, password))
{
var passSalt = LgbCryptography.GenerateSalt();
password = LgbCryptography.ComputeHash(newPassword, passSalt);
string sql = "set Password = @0, PassSalt = @1 where UserName = @2";
ret = Database.Update<User>(sql, password, passSalt, userName) == 1;
ret = db.Update<User>(sql, password, passSalt, userName) == 1;
}
return ret;
}
@ -172,7 +203,8 @@ class UserService : IUser
/// </summary>
public bool SaveDisplayName(string userName, string displayName)
{
var ret = Database.Update<User>("set DisplayName = @1 where UserName = @0", userName, displayName) == 1;
using var db = DBManager.Create();
var ret = db.Update<User>("set DisplayName = @1 where UserName = @0", userName, displayName) == 1;
if (ret)
{
CacheManager.Clear();
@ -185,7 +217,8 @@ class UserService : IUser
/// </summary>
public bool SaveTheme(string userName, string theme)
{
var ret = Database.Update<User>("set Css = @1 where UserName = @0", userName, theme) == 1;
using var db = DBManager.Create();
var ret = db.Update<User>("set Css = @1 where UserName = @0", userName, theme) == 1;
if (ret)
{
CacheManager.Clear();
@ -198,7 +231,8 @@ class UserService : IUser
/// </summary>
public bool SaveLogo(string userName, string? logo)
{
var ret = Database.Update<User>("set Icon = @1 where UserName = @0", userName, logo) == 1;
using var db = DBManager.Create();
var ret = db.Update<User>("set Icon = @1 where UserName = @0", userName, logo) == 1;
if (ret)
{
CacheManager.Clear();
@ -217,14 +251,15 @@ class UserService : IUser
public bool TryCreateUserByPhone(string phone, string code, string appId, ICollection<string> roles)
{
var ret = false;
using var db = DBManager.Create();
try
{
var salt = LgbCryptography.GenerateSalt();
var pwd = LgbCryptography.ComputeHash(code, salt);
var user = Database.FirstOrDefault<User>("Where UserName = @0", phone);
var user = db.FirstOrDefault<User>("Where UserName = @0", phone);
if (user == null)
{
Database.BeginTransaction();
db.BeginTransaction();
// 插入用户
user = new User()
{
@ -238,23 +273,23 @@ class UserService : IUser
Password = LgbCryptography.ComputeHash(code, salt),
App = appId
};
Database.Save(user);
db.Save(user);
// Authorization
var roleIds = Database.Fetch<string>("select ID from Roles where RoleName in (@roles)", new { roles });
Database.InsertBatch("UserRole", roleIds.Select(g => new { RoleID = g, UserID = user.Id }));
Database.CompleteTransaction();
var roleIds = db.Fetch<string>("select ID from Roles where RoleName in (@roles)", new { roles });
db.InsertBatch("UserRole", roleIds.Select(g => new { RoleID = g, UserID = user.Id }));
db.CompleteTransaction();
}
else
{
user.PassSalt = salt;
user.Password = pwd;
Database.Update(user);
db.Update(user);
}
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
if (ret)
@ -268,14 +303,15 @@ class UserService : IUser
{
var salt = LgbCryptography.GenerateSalt();
var pwd = LgbCryptography.ComputeHash(password, salt);
var user = Database.FirstOrDefault<User>("Where UserName = @0", userName);
using var db = DBManager.Create();
var user = db.FirstOrDefault<User>("Where UserName = @0", userName);
bool ret;
if (user == null)
{
try
{
// 开始事务
Database.BeginTransaction();
db.BeginTransaction();
user = new User()
{
ApprovedBy = "System",
@ -287,16 +323,16 @@ class UserService : IUser
PassSalt = salt,
Password = pwd
};
Database.Save(user);
db.Save(user);
// 授权 Default 角色
Database.Execute("insert into UserRole (UserID, RoleID) select ID, (select ID from Roles where RoleName = 'Default') RoleId from Users where UserName = @0", userName);
db.Execute("insert into UserRole (UserID, RoleID) select ID, (select ID from Roles where RoleName = 'Default') RoleId from Users where UserName = @0", userName);
// 结束事务
Database.CompleteTransaction();
db.CompleteTransaction();
ret = true;
}
catch (Exception)
{
Database.AbortTransaction();
db.AbortTransaction();
throw;
}
}
@ -305,7 +341,7 @@ class UserService : IUser
user.DisplayName = displayName;
user.PassSalt = salt;
user.Password = pwd;
Database.Update(user);
db.Update(user);
ret = true;
}
if (ret)
@ -317,7 +353,8 @@ class UserService : IUser
public bool SaveApp(string userName, string app)
{
var ret = Database.Update<User>("Set App = @1 Where UserName = @0", userName, app) == 1;
using var db = DBManager.Create();
var ret = db.Update<User>("Set App = @1 Where UserName = @0", userName, app) == 1;
if (ret)
{
CacheManager.Clear();

View File

@ -2,7 +2,7 @@
<Table TItem="TItem" IsBordered="true" IsStriped="true" IsMultipleSelect="IsMultipleSelect" @ref="Instance"
IsPagination="IsPagination" PageItemsSource="PageItemsSource" IsFixedHeader="IsFixedHeader"
IsTree="IsTree" OnTreeExpand="OnTreeExpand!" TreeIcon="fa-chevron-circle-right"
IsTree="IsTree" OnTreeExpand="OnTreeExpand!" TreeNodeConverter="TreeNodeConverter!" TreeIcon="fa-chevron-circle-right"
ShowDefaultButtons="ShowDefaultButtons" ShowAdvancedSearch="ShowAdvancedSearch"
ShowEmpty="ShowEmpty" EmptyText="暂无数据" EmptyImage="images/empty.svg" SortString="@SortString"
OnQueryAsync="OnQueryAsync!" OnDeleteAsync="OnDeleteAsync!" OnSaveAsync="OnSaveAsync!"
@ -10,7 +10,7 @@
ShowToolbar="ShowToolbar" ShowExtendButtons="ShowExtendButtons" ShowAddButton="@AuthorizeButton("add")"
ShowDeleteButton="@AuthorizeButton("del")" ShowEditButton="@AuthorizeButton("edit")"
ShowCardView="true" ShowColumnList="true" ExtendButtonColumnWidth="@ExtendButtonColumnWidth"
CustomerSearchModel="CustomerSearchModel" SelectedRows="SelectedRows"
CustomerSearchModel="CustomerSearchModel" SelectedRows="SelectedRows" ModelEqualityComparer="ModelEqualityComparer!"
ShowEditButtonCallback="ShowEditButtonCallback!" ShowDeleteButtonCallback="ShowDeleteButtonCallback!"
TableToolbarTemplate="TableToolbarTemplate" TableColumns="TableColumns" EditTemplate="EditTemplate!"
CustomerSearchTemplate="CustomerSearchTemplate!" RowButtonTemplate="RowButtonTemplate!">

View File

@ -145,7 +145,13 @@ namespace BootstrapAdmin.Web.Components
///
/// </summary>
[Parameter]
public Func<TItem, Task<IEnumerable<TItem>>>? OnTreeExpand { get; set; }
public Func<TItem, Task<IEnumerable<TableTreeNode<TItem>>>>? OnTreeExpand { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public Func<IEnumerable<TItem>, Task<IEnumerable<TableTreeNode<TItem>>>>? TreeNodeConverter { get; set; }
/// <summary>
///
@ -177,6 +183,12 @@ namespace BootstrapAdmin.Web.Components
[Parameter]
public Func<TItem, bool>? ShowDeleteButtonCallback { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public Func<TItem, TItem, bool>? ModelEqualityComparer { get; set; }
[NotNull]
private Table<TItem>? Instance { get; set; }

View File

@ -30,11 +30,9 @@
<div class="col-12 col-sm-12">
<BootstrapInput @bind-Value="Value.Favicon" placeholder="不可为空2000字以内"></BootstrapInput>
</div>
<div class="col-12 col-sm-12">
<div class="table-modal-footer text-end">
<Button ButtonType="ButtonType.Button" Text="关闭" Icon="fa fa-close" Color="Color.Secondary" OnClick="OnClickClose"></Button>
<Button ButtonType="ButtonType.Submit" Text="保存" Icon="fa fa-save"></Button>
</div>
</div>
</div>
<div class="form-footer">
<Button ButtonType="ButtonType.Button" Text="关闭" Icon="fa fa-close" Color="Color.Secondary" OnClick="OnClickClose"></Button>
<Button ButtonType="ButtonType.Submit" Text="保存" Icon="fa fa-save"></Button>
</div>
</ValidateForm>

View File

@ -60,13 +60,12 @@ public partial class ClientDialog
}
}
private Task OnSaveCleint(EditContext context)
private async Task OnSaveCleint(EditContext context)
{
if (OnSave != null)
{
OnSave(Value);
await OnSave(Value);
}
return Task.CompletedTask;
}
private async Task OnClickClose()

View File

@ -3,8 +3,8 @@
{
var value = DictService.GetClientUrl(item.Value);
<div class="col-12 col-sm-12">
<BootstrapInputGroup>
<BootstrapInputGroupLabel Text="@item.Key"></BootstrapInputGroupLabel>
<BootstrapInputGroup @key="item.Key">
<BootstrapInputGroupLabel DisplayText="@item.Key"></BootstrapInputGroupLabel>
<BootstrapInput Value="value" Readonly="true"></BootstrapInput>
<PopConfirmButton Placement="Placement.Top" Color="Color.Danger" Icon="fa fa-trash-o" ConfirmIcon="fa fa-exclamation-circle text-danger" ConfirmButtonColor="Color.Danger" Text="删除" Content="确定删除当前应用吗?" OnConfirm="() => OnDeleteClient(item.Value)" />
<Button Icon="fa fa-edit" Text="编辑" OnClickWithoutRender="() => OnEditClient(item.Value)" />

View File

@ -73,13 +73,7 @@ namespace Microsoft.Extensions.DependencyInjection
// });
// 增加 PetaPoco 数据服务
services.AddPetaPocoDataAccessServices((provider, builder) =>
{
var configuration = provider.GetRequiredService<IConfiguration>();
var connString = configuration.GetConnectionString("bb");
builder.UsingProvider<SQLiteDatabaseProvider>()
.UsingConnectionString(connString);
});
services.AddPetaPocoDataAccessServices();
return services;
}

View File

@ -1,8 +1,8 @@
@page "/Admin/Menus"
<AdminTable TItem="DataAccess.Models.Navigation"
IsTree="true" OnTreeExpand="OnTreeExpand" ExtendButtonColumnWidth="200"
CustomerSearchModel="SearchModel" OnQueryAsync="OnQueryAsync">
IsTree="true" OnTreeExpand="OnTreeExpand" TreeNodeConverter="TreeNodeConverter" ModelEqualityComparer="ModelEqualityComparer"
ExtendButtonColumnWidth="200" CustomerSearchModel="SearchModel" OnQueryAsync="OnQueryAsync">
<TableToolbarTemplate>
<TableToolbarButton TItem="DataAccess.Models.Navigation" Color="Color.Info" Icon="fa fa-sitemap" Text="分配角色"
IsEnableWhenSelectedOneRow="true" IsShow="@AuthorizeButton("assignRole")"

View File

@ -123,9 +123,30 @@ public partial class Menus
});
}
private Task<IEnumerable<Navigation>> OnTreeExpand(Navigation menu)
private Task<IEnumerable<TableTreeNode<Navigation>>> OnTreeExpand(Navigation menu)
{
var navs = NavigationService.GetAllMenus(AppContext.UserName);
return Task.FromResult(navs.Where(m => m.ParentId == menu.Id).OrderBy(m => m.Order).AsEnumerable());
return Task.FromResult(navs.Where(m => m.ParentId == menu.Id).OrderBy(m => m.Order).AsEnumerable().Select(i => new TableTreeNode<Navigation>(i)));
}
private Task<IEnumerable<TableTreeNode<Navigation>>> TreeNodeConverter(IEnumerable<Navigation> items)
{
var ret = BuildTreeNodes(items, "0");
return Task.FromResult(ret);
IEnumerable<TableTreeNode<Navigation>> BuildTreeNodes(IEnumerable<Navigation> items, string parentId)
{
var navs = NavigationService.GetAllMenus(AppContext.UserName);
var ret = new List<TableTreeNode<Navigation>>();
ret.AddRange(items.Where(i => i.ParentId == parentId).Select((nav, index) => new TableTreeNode<Navigation>(nav)
{
HasChildren = navs.Any(i => i.ParentId == nav.Id),
IsExpand = navs.Any(i => i.ParentId == nav.Id),
Items = BuildTreeNodes(navs.Where(i => i.ParentId == nav.Id), nav.Id)
}));
return ret;
}
}
private bool ModelEqualityComparer(Navigation x, Navigation y) => x.Id == y.Id;
}

View File

@ -8,7 +8,7 @@
}
},
"profiles": {
"BootstrapAdmin.Web": {
"Console": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,

View File

@ -16,59 +16,9 @@
}
},
"SimulateUserName": "",
"AutoGenerateDatabase": true,
"BootstrapAdminAuthenticationOptions": {
"KeyPath": "..\\..\\keys"
},
"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",
@ -157,194 +107,5 @@
"第二层",
"第三层",
"第四层"
],
"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

@ -20,51 +20,9 @@
}
},
"ConnectionStrings": {
"ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa",
"bb": "Data Source=BootstrapAdmin.db;"
"ba": "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,

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.*" />
<PackageReference Include="Longbow.Security.Cryptography" Version="5.2.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.1" />
<PackageReference Include="BootstrapBlazor" Version="6.8.13" />
<PackageReference Include="Longbow.Security.Cryptography" Version="6.0.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.7" />
<PackageReference Include="PetaPoco.Extensions" Version="6.0.0" />
</ItemGroup>

View File

@ -26,56 +26,19 @@ public static class ServiceCollectionExtensions
///
/// </summary>
/// <param name="services"></param>
/// <param name="builder"></param>
/// <returns></returns>
public static IServiceCollection AddPetaPocoDataAccessServices(this IServiceCollection services, Action<IServiceProvider, IDatabaseBuildConfiguration> builder)
public static IServiceCollection AddPetaPocoDataAccessServices(this IServiceCollection services)
{
services.TryAddSingleton<IDatabase>(provider =>
{
var option = DatabaseConfiguration.Build();
builder(provider, option);
option.UsingDefaultMapper<BootstrapAdminConventionMapper>();
var db = new Database(option);
// 增加多数据库支持服务
services.TryAddSingleton<IDBManager, DBManagerService>();
var logger = provider.GetRequiredService<ILogger<Database>>();
db.ExceptionThrown += (sender, e) =>
{
var message = e.Exception.Format(new NameValueCollection()
{
[nameof(db.LastCommand)] = db.LastCommand,
[nameof(db.LastArgs)] = string.Join(",", db.LastArgs)
});
logger.LogError(new EventId(1001, "GlobalException"), e.Exception, message);
};
var env = provider.GetRequiredService<IWebHostEnvironment>();
if (env.IsDevelopment())
{
db.CommandExecuted += (sender, args) =>
{
var parameters = new StringBuilder();
foreach (DbParameter p in args.Command.Parameters)
{
parameters.AppendFormat("{0}: {1} ", p.ParameterName, p.Value);
}
logger.LogInformation(args.Command.CommandText);
logger.LogInformation(parameters.ToString());
};
};
return db;
});
//// 增加数据服务
//services.AddSingleton(typeof(IDataService<>), typeof(DefaultDataService<>));
//// 增加业务服务
//services.AddSingleton<IApp, AppService>();
// 增加业务服务
services.AddSingleton<IDict, DictService>();
//services.AddSingleton<IException, ExceptionService>();
//services.AddSingleton<IGroup, GroupService>();
//services.AddSingleton<ILogin, LoginService>();
services.AddSingleton<INavigation, NavigationService>();
//services.AddSingleton<IRole, RoleService>();
services.AddSingleton<IUser, UserService>();
// 增加示例数据服务
services.AddSingleton<IDummy, DummyService>();
return services;
}
}

View File

@ -0,0 +1,78 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapBlazor.Components;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using PetaPoco;
using PetaPoco.Providers;
using System.Collections.Specialized;
using System.Data.Common;
using System.Text;
namespace BootstrapClient.DataAccess.PetaPoco.Services;
internal class DBManagerService : IDBManager
{
private IConfiguration Configuration { get; set; }
private ILogger<DBManagerService> Logger { get; set; }
private IWebHostEnvironment WebHost { get; set; }
public DBManagerService(IConfiguration configuration, ILogger<DBManagerService> logger, IWebHostEnvironment host)
{
Configuration = configuration;
Logger = logger;
WebHost = host;
}
/// <summary>
/// 创建 IDatabase 实例方法
/// </summary>
/// <param name="connectionName">连接字符串键值</param>
/// <param name="keepAlive"></param>
/// <returns></returns>
public IDatabase Create(string? connectionName = "ba", bool keepAlive = false)
{
var conn = Configuration.GetConnectionString(connectionName) ?? throw new ArgumentNullException(nameof(connectionName));
var option = DatabaseConfiguration.Build();
option.UsingDefaultMapper<BootstrapAdminConventionMapper>();
// connectionstring
option.UsingConnectionString(conn);
// provider
option.UsingProvider<SQLiteDatabaseProvider>();
var db = new Database(option) { KeepConnectionAlive = keepAlive };
db.ExceptionThrown += (sender, e) =>
{
var message = e.Exception.Format(new NameValueCollection()
{
[nameof(db.LastCommand)] = db.LastCommand,
[nameof(db.LastArgs)] = string.Join(",", db.LastArgs)
});
Logger.LogError(new EventId(1001, "GlobalException"), e.Exception, message);
};
if (WebHost.IsDevelopment())
{
db.CommandExecuted += (sender, args) =>
{
var parameters = new StringBuilder();
foreach (DbParameter p in args.Command.Parameters)
{
parameters.AppendFormat("{0}: {1} ", p.ParameterName, p.Value);
}
Logger.LogInformation(args.Command.CommandText);
Logger.LogInformation(parameters.ToString());
};
};
return db;
}
}

View File

@ -10,15 +10,19 @@ namespace BootstrapClient.DataAccess.PetaPoco.Services;
class DictService : IDict
{
private IDatabase Database { get; }
private IDBManager DBManager { get; }
/// <summary>
///
/// </summary>
/// <param name="db"></param>
public DictService(IDatabase db) => Database = db;
public DictService(IDBManager db) => DBManager = db;
public List<Dict> GetAll() => Database.Fetch<Dict>();
public List<Dict> GetAll()
{
using var db = DBManager.Create();
return db.Fetch<Dict>();
}
public bool IsDemo()
{

View File

@ -0,0 +1,36 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapClient.DataAccess.Models;
using BootstrapClient.Web.Core;
using PetaPoco;
namespace BootstrapClient.DataAccess.PetaPoco.Services;
internal class DummyService : IDummy
{
private IDBManager DBManager { get; }
/// <summary>
///
/// </summary>
/// <param name="db"></param>
public DummyService(IDBManager db)
{
DBManager = db;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<DummyEntity> GetAll()
{
return new List<DummyEntity>()
{
new() { Id= "1", Name ="Dummy1" },
new() { Id= "2", Name ="Dummy2" }
};
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using PetaPoco;
namespace BootstrapClient.DataAccess.PetaPoco.Services;
/// <summary>
///
/// </summary>
public interface IDBManager
{
/// <summary>
///
/// </summary>
/// <returns></returns>
IDatabase Create(string? connectionName = "ba", bool keepAlive = false);
}

View File

@ -13,13 +13,13 @@ namespace BootstrapClient.DataAccess.PetaPoco.Services;
/// </summary>
class NavigationService : INavigation
{
private IDatabase Database { get; }
private IDBManager DBManager { get; }
/// <summary>
///
/// </summary>
/// <param name="db"></param>
public NavigationService(IDatabase db) => Database = db;
public NavigationService(IDBManager db) => DBManager = db;
/// <summary>
/// 获得指定用户名可访问的所有菜单集合
@ -28,7 +28,8 @@ class NavigationService : INavigation
/// <returns>未层次化的菜单集合</returns>
public List<Navigation> GetMenus(string userName)
{
var order = Database.Provider.EscapeSqlIdentifier("Order");
return Database.Fetch<Navigation>($"select n.ID, n.ParentId, n.Name, n.{order}, n.Icon, n.Url, n.Category, n.Target, n.IsResource, n.Application from Navigations n inner join (select nr.NavigationID from Users u inner join UserRole ur on ur.UserID = u.ID inner join NavigationRole nr on nr.RoleID = ur.RoleID where u.UserName = @UserName union select nr.NavigationID from Users u inner join UserGroup ug on u.ID = ug.UserID inner join RoleGroup rg on rg.GroupID = ug.GroupID inner join NavigationRole nr on nr.RoleID = rg.RoleID where u.UserName = @UserName union select n.ID from Navigations n where EXISTS (select UserName from Users u inner join UserRole ur on u.ID = ur.UserID inner join Roles r on ur.RoleID = r.ID where u.UserName = @UserName and r.RoleName = 'Administrators')) nav on n.ID = nav.NavigationID Where n.Category = '1' ORDER BY n.Application, n.{order}", new { UserName = userName });
using var db = DBManager.Create ();
var order = db.Provider.EscapeSqlIdentifier("Order");
return db.Fetch<Navigation>($"select n.ID, n.ParentId, n.Name, n.{order}, n.Icon, n.Url, n.Category, n.Target, n.IsResource, n.Application from Navigations n inner join (select nr.NavigationID from Users u inner join UserRole ur on ur.UserID = u.ID inner join NavigationRole nr on nr.RoleID = ur.RoleID where u.UserName = @UserName union select nr.NavigationID from Users u inner join UserGroup ug on u.ID = ug.UserID inner join RoleGroup rg on rg.GroupID = ug.GroupID inner join NavigationRole nr on nr.RoleID = rg.RoleID where u.UserName = @UserName union select n.ID from Navigations n where EXISTS (select UserName from Users u inner join UserRole ur on u.ID = ur.UserID inner join Roles r on ur.RoleID = r.ID where u.UserName = @UserName and r.RoleName = 'Administrators')) nav on n.ID = nav.NavigationID Where n.Category = '1' ORDER BY n.Application, n.{order}", new { UserName = userName });
}
}

View File

@ -10,32 +10,49 @@ namespace BootstrapClient.DataAccess.PetaPoco.Services;
class UserService : IUser
{
private IDatabase Database { get; }
private IDBManager DBManager { get; }
/// <summary>
///
/// </summary>
/// <param name="db"></param>
public UserService(IDatabase db) => Database = db;
public UserService(IDBManager db) => DBManager = db;
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public User? GetUserByUserName(string? userName) => string.IsNullOrEmpty(userName) ? null : Database.FirstOrDefault<User>("Where UserName = @0", userName);
public User? GetUserByUserName(string? userName)
{
User? user = null;
if (!string.IsNullOrEmpty(userName))
{
using var db = DBManager.Create();
user = db.FirstOrDefault<User>("Where UserName = @0", userName);
}
return user;
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public List<string> GetApps(string userName) => Database.Fetch<string>($"select d.Code from Dicts d inner join RoleApp ra on d.Code = ra.AppId inner join (select r.Id from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @0 union select r.Id from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {Database.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @0) r on ra.RoleId = r.ID union select Code from Dicts where Category = @1 and exists(select r.ID from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @0 and r.RoleName = @2 union select r.ID from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {Database.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @0 and r.RoleName = @2)", userName, "应用程序", "Administrators");
public List<string> GetApps(string userName)
{
using var db = DBManager.Create();
return db.Fetch<string>($"select d.Code from Dicts d inner join RoleApp ra on d.Code = ra.AppId inner join (select r.Id from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @0 union select r.Id from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {db.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @0) r on ra.RoleId = r.ID union select Code from Dicts where Category = @1 and exists(select r.ID from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @0 and r.RoleName = @2 union select r.ID from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {db.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @0 and r.RoleName = @2)", userName, "应用程序", "Administrators");
}
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public List<string> GetRoles(string userName) => Database.Fetch<string>($"select r.RoleName from Roles r inner join UserRole ur on r.ID=ur.RoleID inner join Users u on ur.UserID = u.ID and u.UserName = @0 union select r.RoleName from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {Database.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID and u.UserName=@0", userName);
public List<string> GetRoles(string userName)
{
using var db = DBManager.Create();
return db.Fetch<string>($"select r.RoleName from Roles r inner join UserRole ur on r.ID=ur.RoleID inner join Users u on ur.UserID = u.ID and u.UserName = @0 union select r.RoleName from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join {db.Provider.EscapeSqlIdentifier("Groups")} g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID and u.UserName=@0", userName);
}
}

View File

@ -5,8 +5,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="6.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="6.0.7" />
</ItemGroup>
<ItemGroup>

View File

@ -0,0 +1,17 @@
@typeparam TItem
<Table TItem="TItem" IsBordered="true" IsStriped="true" IsMultipleSelect="IsMultipleSelect" @ref="Instance"
IsPagination="IsPagination" PageItemsSource="PageItemsSource" IsFixedHeader="IsFixedHeader"
IsTree="IsTree" OnTreeExpand="OnTreeExpand!" TreeNodeConverter="TreeNodeConverter!" TreeIcon="fa-chevron-circle-right"
ShowDefaultButtons="ShowDefaultButtons" ShowAdvancedSearch="ShowAdvancedSearch"
ShowEmpty="ShowEmpty" EmptyText="暂无数据" EmptyImage="images/empty.svg" SortString="@SortString"
OnQueryAsync="OnQueryAsync!" OnDeleteAsync="OnDeleteAsync!" OnSaveAsync="OnSaveAsync!"
ShowSkeleton="true" ShowLoading="ShowLoading" ShowSearch="ShowSearch"
ShowToolbar="ShowToolbar" ShowExtendButtons="ShowExtendButtons" ShowAddButton="@AuthorizeButton("add")"
ShowDeleteButton="@AuthorizeButton("del")" ShowEditButton="@AuthorizeButton("edit")"
ShowCardView="true" ShowColumnList="true" ExtendButtonColumnWidth="@ExtendButtonColumnWidth"
CustomerSearchModel="CustomerSearchModel" SelectedRows="SelectedRows"
ShowEditButtonCallback="ShowEditButtonCallback!" ShowDeleteButtonCallback="ShowDeleteButtonCallback!"
TableToolbarTemplate="TableToolbarTemplate" TableColumns="TableColumns" EditTemplate="EditTemplate!"
CustomerSearchTemplate="CustomerSearchTemplate!" RowButtonTemplate="RowButtonTemplate!">
</Table>

View File

@ -0,0 +1,222 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using Bootstrap.Security.Blazor;
using BootstrapClient.Web.Shared.Services;
namespace BootstrapClient.Web.Shared.Components
{
/// <summary>
///
/// </summary>
[CascadingTypeParameter(nameof(TItem))]
public partial class AdminTable<TItem> where TItem : class, new()
{
/// <summary>
///
/// </summary>
[Parameter]
public IEnumerable<int>? PageItemsSource { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public int ExtendButtonColumnWidth { get; set; } = 130;
/// <summary>
///
/// </summary>
[Parameter]
public string? SortString { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
[Parameter]
public RenderFragment<TItem>? TableColumns { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public RenderFragment<TItem>? RowButtonTemplate { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public RenderFragment<ITableSearchModel>? CustomerSearchTemplate { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public RenderFragment<TItem>? EditTemplate { get; set; }
/// <summary>
///
/// </summary>
[NotNull]
[Parameter]
public RenderFragment? TableToolbarTemplate { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public bool IsPagination { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public bool IsMultipleSelect { get; set; } = true;
/// <summary>
///
/// </summary>
[Parameter]
public bool IsFixedHeader { get; set; } = true;
/// <summary>
///
/// </summary>
[Parameter]
public bool IsTree { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public bool ShowToolbar { get; set; } = true;
/// <summary>
///
/// </summary>
[Parameter]
public bool ShowEmpty { get; set; } = true;
/// <summary>
///
/// </summary>
[Parameter]
public bool ShowLoading { get; set; } = false;
/// <summary>
///
/// </summary>
[Parameter]
public bool ShowSearch { get; set; } = true;
/// <summary>
///
/// </summary>
[Parameter]
public bool ShowAdvancedSearch { get; set; } = true;
/// <summary>
///
/// </summary>
[Parameter]
public bool ShowDefaultButtons { get; set; } = true;
/// <summary>
///
/// </summary>
[Parameter]
public bool ShowExtendButtons { get; set; } = true;
/// <summary>
///
/// </summary>
[Parameter]
public ITableSearchModel? CustomerSearchModel { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public Func<QueryPageOptions, Task<QueryData<TItem>>>? OnQueryAsync { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public Func<TItem, Task<IEnumerable<TableTreeNode<TItem>>>>? OnTreeExpand { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public Func<IEnumerable<TItem>, Task<IEnumerable<TableTreeNode<TItem>>>>? TreeNodeConverter { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public Func<TItem, ItemChangedType, Task<bool>>? OnSaveAsync { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public Func<IEnumerable<TItem>, Task<bool>>? OnDeleteAsync { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public List<TItem>? SelectedRows { get; set; } = new List<TItem>();
/// <summary>
///
/// </summary>
[Parameter]
public Func<TItem, bool>? ShowEditButtonCallback { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
public Func<TItem, bool>? ShowDeleteButtonCallback { get; set; }
[NotNull]
private Table<TItem>? Instance { get; set; }
/// <summary>
///
/// </summary>
/// <param name="v"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public ValueTask ToggleLoading(bool v) => Instance.ToggleLoading(v);
/// <summary>
///
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public Task QueryAsync() => Instance.QueryAsync();
[Inject]
[NotNull]
private IBootstrapAdminService? AdminService { get; set; }
[Inject]
[NotNull]
private NavigationManager? NavigationManager { get; set; }
[Inject]
[NotNull]
private BootstrapAppContext? AppContext { get; set; }
private bool AuthorizeButton(string operate)
{
var url = NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
return AdminService.AuhorizingBlock(AppContext.UserName, url, operate);
}
}
}

View File

@ -0,0 +1,9 @@
@using BootstrapClient.Web.Shared.Components
@page "/dummy"
<AdminTable TItem="BootstrapClient.DataAccess.Models.DummyEntity" OnQueryAsync="OnQueryAsync">
<TableColumns>
<TableColumn @bind-Field="context.Id"></TableColumn>
<TableColumn @bind-Field="context.Name"></TableColumn>
</TableColumns>
</AdminTable>

View File

@ -0,0 +1,25 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapClient.DataAccess.Models;
using BootstrapClient.Web.Core;
namespace BootstrapClient.Web.Shared.Pages;
public partial class Dummy
{
[Inject]
[NotNull]
private IDummy? DummyService { get; set; }
private Task<QueryData<DummyEntity>> OnQueryAsync(QueryPageOptions options)
{
var items = DummyService.GetAll();
var ret = new QueryData<DummyEntity>()
{
Items = items
};
return Task.FromResult(ret);
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapClient.DataAccess.Models;
namespace BootstrapClient.Web.Core;
/// <summary>
/// 数据服务示例接口
/// </summary>
public interface IDummy
{
/// <summary>
/// 获得 全部数据
/// </summary>
/// <returns></returns>
List<DummyEntity> GetAll();
}

View File

@ -0,0 +1,21 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
namespace BootstrapClient.DataAccess.Models;
/// <summary>
/// 数据库实体类
/// </summary>
public class DummyEntity
{
/// <summary>
/// 获得/设置 Id
/// </summary>
public string? Id { get; set; }
/// <summary>
/// 获得/设置 Name
/// </summary>
public string? Name { get; set; }
}

View File

@ -33,13 +33,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddScoped<BootstrapAppContext>();
// 增加 PetaPoco 数据服务
services.AddPetaPocoDataAccessServices((provider, builder) =>
{
var configuration = provider.GetRequiredService<IConfiguration>();
var connString = configuration.GetConnectionString("ba");
builder.UsingProvider<SQLiteDatabaseProvider>()
.UsingConnectionString(connString);
});
services.AddPetaPocoDataAccessServices();
return services;
}

View File

@ -15,7 +15,7 @@
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Bootstrap.Client.Blazor": {
"Client": {
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,

View File

@ -12,34 +12,5 @@
"BootstrapAdminAuthenticationOptions": {
"AuthHost": "http://localhost:5210",
"KeyPath": "..\\..\\keys"
},
"DB": [
{
"Enabled": false
},
{
"Enabled": true,
"ProviderName": "Sqlite",
"ConnectionStrings": {
"bb": "..\\..\\admin\\BootstrapAdmin.Web\\BootstrapAdmin.db;",
"client": "Data Source=Client.db;"
}
},
{
"Enabled": false,
"ProviderName": "MySql",
"ConnectionStrings": {
"ba": "Server=localhost;Database=BootstrapAdmin;Uid=root;Pwd=argo@163.com;SslMode=none;"
}
},
{
"Enabled": false,
"Widget": "Bootstrap.Client.DataAccess.MongoDB",
"ProviderName": "MongoDB",
"ConnectionStrings": {
"ba": "mongodb://localhost:27017/BootstrapAdmin",
"client": "mongodb://localhost:27017/BootstrapClient"
}
}
]
}
}

View File

@ -18,33 +18,5 @@
},
"BootstrapBlazorOptions": {
"DefaultCultureInfo": "zh-CN"
},
"DB": [
{
"Enabled": false
},
{
"Enabled": true,
"ProviderName": "Sqlite",
"ConnectionStrings": {
"ba": "Data Source=..\\..\\admin\\BootstrapAdmin.Web\\BootstrapAdmin.db;",
"client": "Data Source=Client.db;"
}
},
{
"Enabled": false,
"ProviderName": "MySql",
"ConnectionStrings": {
"ba": "Server=localhost;Database=BootstrapAdmin;Uid=argozhang;Pwd=argo@163.com;SslMode=none;"
}
},
{
"Enabled": false,
"Widget": "Bootstrap.Client.DataAccess.MongoDB",
"ProviderName": "MongoDB",
"ConnectionStrings": {
"ba": "mongodb://localhost:27017/BootstrapAdmin"
}
}
]
}
}

View File

@ -9,12 +9,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.2.9-beta07" />
<PackageReference Include="Exceptionless.AspNetCore" Version="4.6.2" />
<PackageReference Include="Longbow.Logging" Version="5.2.0" />
<PackageReference Include="BootstrapBlazor" Version="6.8.13" />
<PackageReference Include="Exceptionless.AspNetCore" Version="4.8.0" />
<PackageReference Include="Longbow.Logging" Version="6.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
<PackageReference Include="Sentry.AspNetCore" Version="3.10.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
<PackageReference Include="Sentry.AspNetCore" Version="3.19.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>

View File

@ -23,7 +23,8 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="services"></param>
public static IServiceCollection AddBootstrapAdminBackgroundTask(this IServiceCollection services)
{
services.AddTaskServices(builder => builder.AddFileStorage());
//services.AddTaskServices(builder => builder.AddFileStorage());
services.AddTaskServices();
services.AddHostedService<BootstrapAdminBackgroundServices>();
return services;
}

View File

@ -2,7 +2,7 @@
<ItemGroup>
<PackageReference Include="Bootstrap.Security" Version="5.2.0" />
<PackageReference Include="MongoDB.Driver" Version="2.13.2" />
<PackageReference Include="MongoDB.Driver" Version="2.17.0" />
</ItemGroup>
<ItemGroup>

View File

@ -2,23 +2,23 @@
<ItemGroup>
<PackageReference Include="Bootstrap.Security.DataAccess" Version="5.2.0" />
<PackageReference Include="Bootstrap.Security.Mvc" Version="5.2.0" />
<PackageReference Include="Bootstrap.Security.Mvc" Version="6.0.0" />
<PackageReference Include="Longbow" Version="5.2.0" />
<PackageReference Include="Longbow.AlipayAuth" Version="5.2.0" />
<PackageReference Include="Longbow.Cache" Version="5.2.0" />
<PackageReference Include="Longbow.ComponentModel" Version="5.2.0" />
<PackageReference Include="Longbow.ComponentModel" Version="6.0.0" />
<PackageReference Include="Longbow.Data" Version="5.2.0" />
<PackageReference Include="Longbow.GiteeAuth" Version="5.2.0" />
<PackageReference Include="Longbow.GitHubAuth" Version="5.2.0" />
<PackageReference Include="Longbow.OAuth" Version="5.2.0" />
<PackageReference Include="Longbow.PetaPoco" Version="5.0.1" />
<PackageReference Include="Longbow.Security.Cryptography" Version="5.2.0" />
<PackageReference Include="Longbow.Tasks" Version="5.1.0" />
<PackageReference Include="Longbow.Security.Cryptography" Version="6.0.0" />
<PackageReference Include="Longbow.Tasks" Version="5.2.1" />
<PackageReference Include="Longbow.TencentAuth" Version="5.2.0" />
<PackageReference Include="Longbow.Web" Version="5.2.1" />
<PackageReference Include="Longbow.WeChatAuth" Version="5.2.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.11" />
<PackageReference Include="PetaPoco.Extensions" Version="5.2.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.7" />
<PackageReference Include="PetaPoco.Extensions" Version="6.0.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.3" />
</ItemGroup>

View File

@ -4,6 +4,7 @@
using Longbow.Cache;
using Longbow.Web.Mvc;
using Microsoft.Extensions.Logging;
using PetaPoco;
using System;
using System.Collections.Generic;
@ -25,13 +26,21 @@ namespace Bootstrap.DataAccess
/// <summary>
///
/// </summary>
/// <param name="provider"></param>
/// <param name="eventId"></param>
/// <param name="ex"></param>
/// <param name="additionalInfo"></param>
/// <returns></returns>
public static void Log(Exception ex, NameValueCollection additionalInfo)
public static void Log(IServiceProvider provider, EventId eventId, Exception? ex, NameValueCollection additionalInfo)
{
var ret = DbContextManager.Create<Exceptions>()?.Log(ex, additionalInfo) ?? false;
if (ret) CacheManager.Clear(RetrieveExceptionsDataKey);
if (ex != null)
{
var ret = DbContextManager.Create<Exceptions>()?.Log(ex, additionalInfo) ?? false;
if (ret)
{
CacheManager.Clear(RetrieveExceptionsDataKey);
}
}
}
/// <summary>

View File

@ -35,30 +35,40 @@ namespace Bootstrap.DataAccess
/// <returns></returns>
public static bool Save(BootstrapMenu p)
{
// 不允许保存系统菜单与前台演示系统的默认菜单
var ret = false;
if (DictHelper.RetrieveSystemModel())
{
if (p.Category == "0") return true;
// 查找原有数据比对是否为系统菜单与演示菜单
if (!string.IsNullOrEmpty(p.Id))
// 不允许保存系统菜单与前台演示系统的默认菜单
if (p.Category == "0")
{
// 系统菜单
ret = true;
}
else if (!string.IsNullOrEmpty(p.Id))
{
// 查找原有数据比对是否为系统菜单与演示菜单
var menus = RetrieveAllMenus("Admin");
#pragma warning disable CS8602 // 取消引用可能出现的空引用。
var menu = menus.FirstOrDefault(m => m.Id.Equals(p.Id, System.StringComparison.OrdinalIgnoreCase));
#pragma warning restore CS8602 // 取消引用可能出现的空引用。
if (menu != null && menu.Category == "0") return true;
// 演示系统
var appMenus = BootstrapAppContext.Configuration.GetSection("AppMenus").Get<ICollection<string>>();
if (appMenus.Any(m => m.Equals(menu?.Name, StringComparison.OrdinalIgnoreCase))) return true;
var menu = menus.FirstOrDefault(m => m.Id?.Equals(p.Id, System.StringComparison.OrdinalIgnoreCase) ?? false);
if (menu != null && menu.Category == "0")
{
// 系统菜单
ret = true;
}
else if (BootstrapAppContext.Configuration != null)
{
var appMenus = BootstrapAppContext.Configuration.GetSection("AppMenus").Get<ICollection<string>>();
if (appMenus.Any(m => m.Equals(menu?.Name, StringComparison.OrdinalIgnoreCase)))
{
ret = true;
}
}
}
}
var ret = DbContextManager.Create<Menu>()?.Save(p) ?? false;
if (ret) CacheCleanUtility.ClearCache(menuIds: string.IsNullOrEmpty(p.Id) ? new List<string>() : new List<string>() { p.Id });
else
{
ret = DbContextManager.Create<Menu>()?.Save(p) ?? false;
if (ret) CacheCleanUtility.ClearCache(menuIds: string.IsNullOrEmpty(p.Id) ? new List<string>() : new List<string>() { p.Id });
}
return ret;
}
@ -69,23 +79,38 @@ namespace Bootstrap.DataAccess
/// <returns></returns>
public static bool Delete(IEnumerable<string> value)
{
var ret = false;
if (DictHelper.RetrieveSystemModel())
{
// 不允许删除系统菜单与前台演示系统的默认菜单
var systemMenus = RetrieveAllMenus("Admin").Where(m => m.Category == "0");
value = value.Where(v => !systemMenus.Any(m => m.Id == v));
if (!value.Any()) return true;
// 演示系统
var appMenus = BootstrapAppContext.Configuration.GetSection("AppMenus").Get<ICollection<string>>();
var appIds = RetrieveAllMenus("Admin").Where(m => appMenus.Any(app => m.Name.Equals(app, System.StringComparison.OrdinalIgnoreCase))).Select(m => m.Id);
#pragma warning disable CS8602 // 取消引用可能出现的空引用。
value = value.Where(m => !appIds.Any(app => app.Equals(m, StringComparison.OrdinalIgnoreCase)));
#pragma warning restore CS8602 // 取消引用可能出现的空引用。
if (!value.Any()) return true;
if (!value.Any())
{
ret = true;
}
else if (BootstrapAppContext.Configuration != null)
{
// 演示系统
var appMenus = BootstrapAppContext.Configuration.GetSection("AppMenus").Get<ICollection<string>>();
var appIds = RetrieveAllMenus("Admin")
.Where(m => appMenus.Any(app => m.Name.Equals(app, System.StringComparison.OrdinalIgnoreCase)))
.Select(m => m.Id);
value = value.Where(m => !appIds.Any(app => app?.Equals(m, StringComparison.OrdinalIgnoreCase) ?? false));
if (!value.Any())
{
ret = true;
}
}
}
else
{
ret = DbContextManager.Create<Menu>()?.Delete(value) ?? false;
if (ret)
{
CacheCleanUtility.ClearCache(menuIds: value);
}
}
var ret = DbContextManager.Create<Menu>()?.Delete(value) ?? false;
if (ret) CacheCleanUtility.ClearCache(menuIds: value);
return ret;
}
@ -101,7 +126,7 @@ namespace Bootstrap.DataAccess
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public static IEnumerable<string> RetrieveMenusByRoleId(string roleId) => CacheManager.GetOrAdd($"{RetrieveMenusByRoleIdDataKey}-{roleId}", k => DbContextManager.Create<Menu>()?.RetrieveMenusByRoleId(roleId), RetrieveMenusByRoleIdDataKey) ?? new string[0];
public static IEnumerable<string> RetrieveMenusByRoleId(string roleId) => CacheManager.GetOrAdd($"{RetrieveMenusByRoleIdDataKey}-{roleId}", k => DbContextManager.Create<Menu>()?.RetrieveMenusByRoleId(roleId), RetrieveMenusByRoleIdDataKey) ?? Array.Empty<string>();
/// <summary>
/// 保存指定角色的所有菜单
@ -125,7 +150,7 @@ namespace Bootstrap.DataAccess
/// <returns></returns>
public static IEnumerable<BootstrapMenu> RetrieveAppMenus(string? appId, string? userName, string? activeUrl)
{
if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(userName)) return new BootstrapMenu[0];
if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(userName)) return Array.Empty<BootstrapMenu>();
var menus = RetrieveAllMenus(userName).Where(m => m.Category == "1" && m.IsResource == 0);
menus = menus.Where(m => m.Application.Equals(appId, StringComparison.OrdinalIgnoreCase));
@ -162,7 +187,11 @@ namespace Bootstrap.DataAccess
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public static IEnumerable<BootstrapMenu> RetrieveAllMenus(string? userName) => string.IsNullOrEmpty(userName) ? new BootstrapMenu[0] : CacheManager.GetOrAdd($"{RetrieveMenusAll}-{userName}", key => DbContextManager.Create<Menu>()?.RetrieveAllMenus(userName), RetrieveMenusAll) ?? Array.Empty<BootstrapMenu>();
public static IEnumerable<BootstrapMenu> RetrieveAllMenus(string? userName) => string.IsNullOrEmpty(userName)
? Array.Empty<BootstrapMenu>()
: CacheManager.GetOrAdd($"{RetrieveMenusAll}-{userName}", key => DbContextManager.Create<Menu>()
?.RetrieveAllMenus(userName), RetrieveMenusAll)
?? Array.Empty<BootstrapMenu>();
/// <summary>
/// 通过当前用户名与指定菜单路径获取此菜单下所有授权按钮集合 (userName, url, auths) => bool

View File

@ -1,3 +1,3 @@
<lgb>
<token>FP7PPYuq1IxBnd8cHAFQbr73FxUGxIUVotbCDEU49T5WJASIg3kEeZErdwxZVDjOHUOXIy7mQmfWKdKxLNSYRcsf2qlqNTkxzkjKnPMyPC6nU2pxPqjgaMj+9ktgnr34KUUbq4Of/XbSln+PY3BoHXP+FC8lJ39op/sJOi5LzqIA</token>
<token>3/Ld1RBfVsDzesgUamNUo3gDGd1oiImeiCTEGpybeGKk+DIC+Q4ExWvxKjYfh31howpH7L5L41hVoybFT68unJXWG9uowxA2YhlE44ujnNS7sIBzMFT/SNzqzY5mga+ajvgna48mR3kVIa5dfUh+5TGc1W5QmfVsbcm/g40ApqAA</token>
</lgb>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="2.13.2" />
<PackageReference Include="MongoDB.Driver" Version="2.17.0" />
</ItemGroup>
<ItemGroup>

View File

@ -2,12 +2,12 @@
<ItemGroup>
<PackageReference Include="Bootstrap.Security.DataAccess" Version="5.2.0" />
<PackageReference Include="Bootstrap.Security.Mvc" Version="5.2.0" />
<PackageReference Include="Bootstrap.Security.Mvc" Version="6.0.0" />
<PackageReference Include="Longbow" Version="5.2.0" />
<PackageReference Include="Longbow.Cache" Version="5.2.0" />
<PackageReference Include="Longbow.ComponentModel" Version="5.2.0" />
<PackageReference Include="Longbow.ComponentModel" Version="6.0.0" />
<PackageReference Include="Longbow.Data" Version="5.2.0" />
<PackageReference Include="Longbow.Security.Cryptography" Version="5.2.0" />
<PackageReference Include="Longbow.Security.Cryptography" Version="6.0.0" />
<PackageReference Include="Longbow.Web" Version="5.2.1" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.3" />
</ItemGroup>

View File

@ -5,9 +5,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="6.2.7-beta02" />
<PackageReference Include="Longbow.Logging" Version="5.2.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.11" />
<PackageReference Include="BootstrapBlazor" Version="6.8.13" />
<PackageReference Include="Longbow.Logging" Version="6.0.2" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.7" />
</ItemGroup>
<ItemGroup>

View File

@ -8,8 +8,8 @@
<Target Name="PostBuildTest" AfterTargets="PostBuildEvent">
<Message Text="Copy db file -> $(TargetDir)" Importance="high" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)..\src\admin\Bootstrap.Admin\BootstrapAdmin.db" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)../src/admin/Bootstrap.Admin/BootstrapAdmin.db" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)..\src\mvc\admin\Bootstrap.Admin\BootstrapAdmin.db" SkipUnchangedFiles="true" />
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)../src/mvc/admin/Bootstrap.Admin/BootstrapAdmin.db" SkipUnchangedFiles="true" />
</Target>
</Project>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable>
<DebugType>Full</DebugType>
</PropertyGroup>
@ -13,16 +13,16 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="2.7.0">
<PackageReference Include="coverlet.msbuild" Version="3.1.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.11" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="MySql.Data" Version="8.0.27" />
<PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.7" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="MySql.Data" Version="8.0.29" />
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>