⚓ 项目简介
FastAdminAPI是一个可以快速开发的OA系统项目,适用于中小型规模快速使用,基于.net6和AspNetCore进行开发。该项目包含部门,岗位,用户,员工,角色权限,数据权限,通用审批,事件总线,服务间调用,定时任务等功能,能够快速开发并部署使用。
🌏 目录
🚀 快速开始
本项目启动需要以下环境,请先配置环境:
MySQLRedis.NET6Microsoft Visual Studio 2022
修改appsettings.Development.json文件
{
"Database.ConnectionString": "数据库连接字符串",
"Redis.ConnectionString": "Redis连接字符串",
"Redis.DbNum": 0, #Redis库编号
"Login.IPAddress.WhiteList": "", #IP白名单
"Common.Applications.DefaultApprover": 1, #通用审批 默认审批人
"FastAdminAPI.Core.Url": "http://localhost:9000" #多服务用于配置RefitClient
}点击vs2022运行,将会启动swagger文档。
🏗️ 项目结构
FastAdminAPI.Business/ 通用业务类库 FastAdminAPI.CAP/ 开源项目CAP类库(基于dotnetcore/CAP项目开发及配置) FastAdminAPI.Common/ 通用工具类库 FastAdminAPI.Core/ 核心项目(可按该模板创建多个不同的微服务项目) FastAdminAPI.Email/ 邮件收发类库(基于jstedfast/MailKit开源项目) FastAdminAPI.EventBus/ 事件总线项目(基于dotnetcore/CAP开源项目) FastAdminAPI.Framework/ ORM类库(基于DotNetNext/SqlSugar开源项目) FastAdminAPI.NPOI/ NPOI类库(基于nissl-lab/npoi开源项目) FastAdminAPI.Network/ 网络请求类库(基于reactiveui/refit开源项目) FastAdminAPI.Tasks/ 定时任务项目(基于HangfireIO/Hangfire开源项目) FastAdminAPI.sln 解决方案
🥩 项目内容
核心项目,包含部门、岗位、员工、角色权限等功能,可以做到开箱即用。当然如果和现实情况不符,可进行再次开发。
在业务复杂的情况下,可以根据该项目结构进行复刻,建立多个不同的微服务进行业务拆分。
本项目除了引用其他类库外,自身已包含所有业务相关代码,无其他依赖,结构简单,上手非常容易。
Controllers/ Controller层-数据返回 IServices/ 服务层接口 Models/ dto模型层-数据传输及ORM配置 Properties/ 项目启动配置 Services/ 服务层-业务数据操作
Program.cs文件中的配置都有相应的注释,方便学习。
FastAdminAPI.Common
通用工具类库,包含很多实用工具。
结构
Attributes/ 各类特性类 BASE/ 返回统一参数,通用参数等 Cryptos/ 加解密 Datetime/ 时间帮助类 Enums/ 通用枚举 JsonTree/ json树结构转换 Logs/ 日志相关 QRCode/ 二维码生成工具 Redis/ Redis工具类 SerialNumber/ 编号/序列号生成器 Utilities/ 实用工具
FastAdminAPI.Configuration
结构
Authentications/ jwt校验 BASE/ 全局参数 Extensions/ 通用配置 Filters/ 全局过滤 Middlewares/ 通用中间件 Swagger/ Swagger配置
配置
配置Model规则验证和全局异常捕获
//配置 Model规则有效性验证 和 全局异常捕获 builder.Services.AddControllers(c => { //配置Model规则有效性验证 c.Filters.Add<ModelValidationAttribute>(); //配置全局异常捕获 c.Filters.Add(typeof(GlobalExceptionsFilter)); });
配置service层
// 服务层注入 将所有Service文件注入 builder.Services.AddAllServices();
配置响应压缩
//接口响应压缩 builder.Services.AddCompressResponse(); //WebApplication app = builder.Build()构建后进行配置 app.UseResponseCompression();
Swagger配置
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwagger(serviceName, AppContext.BaseDirectory); //WebApplication app = builder.Build()构建后进行配置 app.UseSwagger(); app.UseSwaggerUI(c => { c.Configure(serviceName); });
Jwt配置
//jwt配置 builder.Services.AddJwtAuthentication(); //WebApplication app = builder.Build()构建后进行配置 app.UseAuthentication(); app.UseJwtTokenAuth();
FastAdminAPI.Framework
ORM框架,基于DotNetNext/SqlSugar开源项目进行开发,sqlsugar的用法直接看官方文档即可。另外引入了SqlSugar.Attributes类库,只需要配置DTO模型,即可自动拼接SQL并映射查询条件及结果,非常方便。下面的扩展也是基于这个类库做的进一步封装。
结构
Database/ 数据库SQL文件 Entities/ 数据库实体类 Extensions/ ORM扩展
本项目类库增加了一些扩展,可以更加快速的进行业务开发。
ORM扩展
普通查询
[DbDefaultOrderBy("t_Name", DbSortWay.DESC)] //[DbDefaultOrderBy("t.t_Name", DbSortWay.DESC)] public class Search : DbQueryBaseModel { //[DbTableAlias("t")] //表别名,多表关联使用,单表需要查询时指定表别名 [DbQueryField("t_Name")] //字段名 [DbQueryOperator(DbOperator.Like)] //操作符, Like查询 public string Name { get; set; } //[DbTableAlias("t")] //表别名,多表关联使用,单表需要查询时指定表别名 [DbQueryField("t_CodeId")] //字段名 [DbQueryOperator(DbOperator.In)] //操作符,IN查询 public List<long> CodeIds { get; set; } } public class Result { //[DbTableAlias("t")] //表别名,多表关联使用,单表需要查询时指定表别名 [DbQueryField("t_Id")] //字段名 public long Id { get; set; } //[DbTableAlias("t")] //表别名,多表关联使用,单表需要查询时指定表别名 [DbQueryField("t_Name")] //字段名 public string Name { get; set; } //子查询,如果指定了表别名,可以使用表别名,否则直接写表名 //[DbSubQuery("(SELECT name FROM Table_Name2 WHERE t.t_Id = Id)")] [DbSubQuery("(SELECT name FROM Table_Name2 WHERE Table_Name.t_Id = Id)")] public string OtherName { get; set; } }
- 查询方法
//自动包装映射 await _dbContext.Queryable<Table_Name>().ToListResultAsync(search, new Result()); //自动包装映射,指定表别名 await _dbContext.Queryable<Table_Name>("t").ToListResultAsync(search, new Result());
上述生成的SQL如下:
- 正常查询
SELECT t_Id as Id, t_Name as Name, (SELECT name FROM Table_Name2 WHERE Table_Name.t_Id = Id) AS OtherName FROM Table_Name WHERE t_Name LIKE '%@Name%' AND t_CodeId IN (@CodeIds) ORDER BY t_Name DESC;
- 指定表别名查询
SELECT t.t_Id as Id, t.t_Name as Name, (SELECT name FROM Table_Name2 WHERE t.t_Id = Id) AS OtherName FROM Table_Name t WHERE t.t_Name LIKE '%@Name%' AND t.t_CodeId IN (@CodeIds) ORDER BY t.t_Name DESC;
分组查询
- 创建查询的查询条件类
[DbDefaultOrderBy("CountNums", DbSortWay.DESC)] public class Search { [DbQueryField("t_GroupCode")] //字段名 [DbQueryOperator(DbOperator.Like)] //操作符, Like查询 public long GroupCode { get; set; } [DbQueryField("t_GroupName")] //字段名 [DbQueryOperator(DbOperator.Like)] //操作符, Like查询 public string GroupName { get; set; } }
- 创建查询的结果类
[DbHaving("CountNums > 0")] public class Result { [DbQueryField("t_GroupCode")] //字段名 [DbGroupBy("t_GroupCode")] //分组 public long GroupCode { get; set; } [DbQueryField("t_GroupName")] //字段名 [DbGroupBy("t_GroupName")] //分组 public string GroupName { get; set; } [DbSubQuery("Count(t_CodeId)")] public string CountNums { get; set; } }
- 查询方法
//自动包装映射 await _dbContext.Queryable<Table_Name>().ToListResultAsync(search, new Result());
- 查询SQL
SELECT t_GroupCode as GroupCode, t_GroupName as t_GroupName, (Count(t_CodeId)) AS CountNums FROM Table_Name GROUP BY t_GroupCode,t_GroupName HAVING CountNums > 0 WHERE t_GroupCode LIKE '%@Name%' AND t_GroupName LIKE '%@GroupName%' ORDER BY CountNums DESC;
结果转换
以上查询方法返回结果为 统一返回结果(ResponseModel),如需将结果转换回List<T>类型,可以使用下面的方法:
var result = await _dbContext.Queryable<Table_Name>().ToAutoBoxResultAsync(search, new Result()); if (result?.Code == ResponseCode.Success) { //转换为List<T> var list = result.ToConvertData<List<Result>>(); }
新增
await _dbContext.InsertResultAsync<AddModel, Table_Name>(model)
public class AddModel : DbOperationBaseModel { [DbOperationField("t_Name")] public string Name { get; set; } [DbOperationField("t_Address")] public string Address { get; set; } }
上述生成的SQL如下:
INSERT INTO Table_Name (t_Name, t_Address) VALUES (@Name, @Address);
编辑
await _dbContext.UpdateResultAsync<EditModel, Table_Name>(model);
public class EditModel : DbOperationBaseModel { [DbOperationField("t_Id", true)] //true代表更新条件 public long? Id { get; set; } [DbOperationField("t_Name")] public string Name { get; set; } [DbOperationField("t_Address")] public string Address { get; set; } }
上述生成的SQL如下:
UPDATE Table_Name SET t_Name = @Name, t_Address = @Address WHERE t_Id = @Id;
软删除
await _dbContext.SoftDeleteAsync<DelModel, Table_Name>(model);
public class DelModel : DbOperationBaseModel { [DbOperationField("t_Id", true)] //true代表更新条件 public long? Id { get; set; } [DbOperationField("t_IsValid")] public int IsValid { get; set; } }
上述生成的SQL如下:
UPDATE Table_Name SET t_Name = @Name, t_IsValid = @IsValid WHERE t_Id = @Id;
事务
await _dbContext.TransactionAsync(async () => { //需要执行的sql });
执行结果转换
将SqlSugar的返回结果转换为 统一返回结果(ResponseModel)
await _dbContext.Updateable(entity).ExecuteAsync();
FastAdminAPI.Business
该类库包含一些通用的业务,例如:数据权限,通用审批等,多服务皆可引用该项目,减少重复代码,并降低修改代码带来的问题。
结构
Common/ 公用类 Extensions/ 扩展配置文件 IServices/ 接口 Models/ dto模型 PrivateFunc/ 接口实现的私有方法 Services/ 接口实现层
配置
引用该类库,需要依赖注入,相关依赖注入的配置如下:
//注入数据权限业务服务 builder.Services.AddDataPermissionService(); //注入通用审批业务服务 builder.Services.AddApplicationService(); //注入通用区域业务服务 builder.Services.AddRegionService();
如果想要全部注入,可以这样进行配置:
//注入所有业务服务 builder.Services.AddBusinessServices();
FastAdminAPI.CAP
该类库是基于dotnetcore/CAP开源项目进行开发的,将配置简单化,直接可以开始使用。该类库使用MySQL进行持久化存储,使用Redis进行消息的发布及消费。
- 仅使用功能
builder.Services.AddEventBus(configuration);
- 需要个性化配置
builder.Services.AddCap(opt => { opt.ConfigureCAP(configuration); opt.UseDashboard(config => { config.PathMatch = ""; }); });
需要说明的是,如果要编写 订阅 或 发布 时,需要指定 订阅 的名称,订阅的名称放在FastAdminAPI.CAP/Subscribes目录下,进行统一管理。
CAP的配置放在appsettings.json文件中,可以按需求修改。
FastAdminAPI.Email
邮件相关的类库,基于jstedfast/MailKit开源项目开发。
FastAdminAPI.NPOI
Excel相关类库,基于nissl-lab/npoi开源项目开发。
- 如果仅仅是简单的使用Excel导入和导出,可以使用
FastAdminAPI.Common中的MiniExcel,该功能是引入了mini-software/MiniExcel开源项目,更加高效快捷,无需引入FastAdminAPI.NPOI类库 - 比较复杂的Excel操作可以引用
FastAdminAPI.NPOI进行更多的操作。
FastAdminAPI.Network
网络请求类库,基于reactiveui/refit开源项目进行开发,进行了统一的配置。
配置
//配置refit,并依赖注入 builder.Services.AddRefitClients(configuration);
使用
调用外部接口只需要像调用本地方法一样使用。
public interface IEmailApi { /// <summary> /// 发送Smtp邮件 /// </summary> /// <param name="model"></param> /// <returns></returns> [Post("/api/EmailApi/SendSmtpEmail")] Task SendSmtpEmail([Body] SendSmtpEmailModel model); } public class Test { //依赖注入 private readonly IEmailApi _emailApi; public Test(IEmailApi emailApi) { _emailApi = emailApi; } public async Task SendEmail(model) { //直接使用 await emailApi.SendSmtpEmail(model); } }
FastAdminAPI.EventBus
事件总线,基于dotnetcore/CAP开源项目进行开发,启动后会展示CAP.Dashboard,该事件总线使用MySQL进行持久化存储,使用Redis进行消息的发布及消费。当前项目主要用于消费业务数据。
CAP的配置放在appsettings.json文件中,可以按需求修改。
FastAdminAPI.Schedules
定时任务,基于HangfireIO/Hangfire开源项目进行开发,依赖于Redis。简化了相关配置。
Dashboard
- 修改
dashboard登录账号和密码,可以修改Program.cs文件。
new BasicAuthAuthorizationUser { Login = "fastadminapi", PasswordClear = "123456" }
配置
- 定时任务只需要继承
BaseScheduleJob.cs基类即可,要配置定时任务执行的周期,可以在appsettings.json中进行配置。
"ScheduleJob": [ { "IsEnable": false, "JobName": "example", "Frequency": "minutes/hours/daily/weekly/monthly/yearly", "Minute": "minutes/dailyweekly", "Hour": "hours/daily/weekly/monthly", "Day": "monthly/yearly", "DayOfWeek": "weekly", "Month": "yearly", "Description": "description" } ]
只需要根据不同的定时任务,配置不同的配置即可,配置类为ScheduleJobOptions
🍾 感谢
以下是该项目用到的部分开源项目:
- DotNetNext/SqlSugar
- HangfireIO/Hangfire
- dotnetcore/CAP
- reactiveui/refit
- mini-software/MiniExcel
- nissl-lab/npoi
- jstedfast/MailKit
感谢所有开源项目的贡献,好的项目需要大家共同维护和分享。
💛 Sponsor
感谢JetBrains对本项目的支持。
