# Yi 框架 --- ## 📖 简介 **Yi Framework**(意框架)是一个基于 **.NET 8 + ABP.vNext + SqlSugar** 的 DDD 领域驱动设计后端开源框架。 ### 核心理念 - **简单易用**:面向用户的快速开发框架,新人友好 - **源码开放**:框架以源码形式提供,不打包,方便二开和学习 - **模块化设计**:基于 ABP.vNext 模块化架构,按需引用 - **开箱即用**:内置权限管理、多租户、CRUD 等常用功能 ### 技术栈 **后端** - .NET 8.0 - ABP.vNext(动态 API、模块化、依赖注入) - SqlSugar(ORM) - JWT 鉴权 - Serilog 日志 - Mapster 对象映射 **前端** - Vue 3.2 - Vben Admin(企业级中后台前端解决方案) --- ## 🚀 快速开始 ### 环境要求 - **.NET SDK 8.0** 或更高版本 - **Visual Studio 2022** 或 **VS Code** - **Node.js 20.10+**(前端开发需要) - **数据库**:SQLite(默认)/ MySQL / SQL Server / PostgreSQL / Oracle ### 第一步:克隆项目 ```bash git clone https://gitee.com/ccnetcore/Yi.git cd Yi ``` ### 第二步:配置数据库 编辑 `Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.json`: ```json { "DbConnOptions": { "Url": "server=localhost;port=3306;database=yi_db;uid=root;pwd=123456;CharSet=utf8mb4;", "DbType": "Mysql", "EnabledCodeFirst": true, // 是否通过代码优先创建数据库表结构 "EnabledDbSeed": true, // 是否启用数据库种子数据(初始化数据) "EnabledSqlLog": true, // 是否启用SQL日志记录 "EnabledSaasMultiTenancy": false, // 是否启用多租户 "EnabledConcurrencyException": false // 是否启用并发异常处理 } } ``` **支持的数据库类型**: - `Sqlite`(默认,无需配置) - `Mysql` - `Sqlserver` - `PostgreSQL` - `Oracle` ### 第三步:启动后端 1. 使用 Visual Studio 打开 `Yi.Abp.Net8/Yi.Abp.sln` 2. 设置启动项目为 `Yi.Abp.Web` 3. 按 `F5` 启动项目 启动成功后,浏览器会自动打开 Swagger 文档:`http://localhost:19001/swagger` **默认管理员账号**:`admin` / `123456` > 💡 **提示**: > - 首次启动会自动创建数据库表(CodeFirst) > - 会自动初始化种子数据(用户、角色等) > - 接口会自动分组,点击右上角的分组名称查看不同模块的接口 ### 第四步:启动前端(可选) ```bash cd Yi.Vben5.Vue3 pnpm install pnpm dev:antd ``` 前端地址:`http://localhost:18000` --- ## 📁 项目结构 ``` Yi/ ├── Yi.Abp.Net8/ # 后端项目 │ ├── framework/ # 框架核心代码(基础设施) │ │ ├── Yi.Framework.SqlSugarCore/ # SqlSugar ORM 封装 │ │ ├── Yi.Framework.Ddd.Application/ # DDD 应用层基类 │ │ └── ... │ ├── module/ # 业务模块目录(所有业务代码都在这里) │ │ ├── rbac/ # 权限管理模块(内置) │ │ ├── tenant-management/# 租户管理模块(内置) │ │ ├── antis-erp/ # 示例业务模块 │ │ └── your-module/ # 你的业务模块(在这里创建) │ └── src/ # 框架启动项目 │ └── Yi.Abp.Web/ # Web 层(启动项目,仅配置) ├── Yi.Vben5.Vue3/ # 前端项目 └── Yi.Doc.Md/ # 框架文档 ``` ### 模块结构(每个业务模块都包含以下分层) ``` your-module/ ├── YourModule.Domain.Shared/ # 领域共享层(枚举、常量) ├── YourModule.Domain/ # 领域层(实体、领域服务) ├── YourModule.Application.Contracts/ # 应用抽象层(接口、DTO) ├── YourModule.Application/ # 应用层(服务实现) └── YourModule.SqlSugarCore/ # 基础设施层(数据库上下文) ``` ### 分层架构(DDD) ``` ┌─────────────────────────────────┐ │ Web 层(Yi.Abp.Web) │ ← 启动项目、中间件配置 ├─────────────────────────────────┤ │ 应用层(Application) │ ← 业务逻辑、服务实现 ├─────────────────────────────────┤ │ 应用抽象层(Application.Contracts)│ ← 接口定义、DTO ├─────────────────────────────────┤ │ 领域层(Domain) │ ← 实体、领域服务 ├─────────────────────────────────┤ │ 领域共享层(Domain.Shared) │ ← 枚举、常量、共享 DTO ├─────────────────────────────────┤ │ 基础设施层(SqlSugarCore) │ ← ORM、仓储实现 └─────────────────────────────────┘ ``` > 💡 **重要**: > - **所有业务代码都应该放在 `module` 目录下创建自己的模块** > - `src` 目录只用于框架启动配置,不存放业务代码 > - 每个模块都是独立的,可以按需引用 --- ## 🎯 核心功能 ### 1. 动态 API 框架基于 ABP.vNext,自动将应用服务转换为 RESTful API,无需手写 Controller。 **示例**: ```csharp // 在 Application 层创建服务 public class NewsService : YiCrudAppService<...> { } // 自动生成 API: // GET /api/app/news - 查询列表 // GET /api/app/news/{id} - 查询详情 // POST /api/app/news - 创建 // PUT /api/app/news/{id} - 更新 // DELETE /api/app/news/{id} - 删除 ``` ### 2. CRUD 快速开发 继承 `YiCrudAppService` 即可自动获得完整的增删改查功能。 ### 3. 权限管理(RBAC) 内置完整的权限管理系统: - 用户管理 - 角色管理 - 菜单管理 - 部门管理 - 岗位管理 - 字典管理 - 操作日志 - 登录日志 ### 4. 多租户支持 支持 SaaS 多租户架构,可配置是否启用。 ### 5. 模块化架构 采用 ABP.vNext 模块化设计,功能模块化,按需引用。 --- ## 💻 开发指南 ### 创建自己的业务模块 **重要**:所有业务代码都应该在 `module` 目录下创建自己的模块,而不是放在 `src` 目录。 #### 步骤一:创建模块目录结构 在 `Yi.Abp.Net8/module/` 目录下创建你的模块文件夹,例如:`your-module/` 模块应包含以下项目(参考 `antis-erp` 模块): - `YourModule.Domain.Shared` - 领域共享层 - `YourModule.Domain` - 领域层 - `YourModule.Application.Contracts` - 应用抽象层 - `YourModule.Application` - 应用层 - `YourModule.SqlSugarCore` - 基础设施层 #### 步骤二:创建模块文件 每个项目都需要一个 `Module` 类,例如: - `YourModuleDomainSharedModule.cs` - `YourModuleDomainModule.cs` - `YourModuleApplicationContractsModule.cs` - `YourModuleApplicationModule.cs` - `YourModuleSqlSugarCoreModule.cs` #### 步骤三:注册模块依赖 在 `Yi.Abp.Web/YiAbpWebModule.cs` 中注册你的模块: ```csharp [DependsOn( typeof(YourModuleApplicationModule), // 添加你的应用模块 // ... 其他依赖 )] public class YiAbpWebModule : AbpModule { // 注册动态 API PreConfigure(options => { options.ConventionalControllers.Create( typeof(YourModuleApplicationModule).Assembly, options => options.RemoteServiceName = "你的模块名称" ); }); } ``` ### 创建一个完整的 CRUD 功能 以创建"新闻管理"功能为例(在 `your-module` 模块中): #### 1. 创建实体(Domain 层) 在 `YourModule.Domain/Entities/` 创建: ```csharp using SqlSugar; using Volo.Abp.Auditing; using Volo.Abp.Domain.Entities; using Yi.Framework.Core.Data; namespace YourModule.Domain.Entities { [SugarTable("News")] public class NewsAggregateRoot : AggregateRoot, ISoftDelete, IAuditedObject, IOrderNum, IState { [SugarColumn(IsPrimaryKey = true)] public override Guid Id { get; protected set; } public bool IsDeleted { get; set; } public DateTime CreationTime { get; set; } = DateTime.Now; public Guid? CreatorId { get; set; } public Guid? LastModifierId { get; set; } public DateTime? LastModificationTime { get; set; } public int OrderNum { get; set; } = 0; public bool State { get; set; } = true; [SugarColumn(ColumnName = "Title")] public string Title { get; set; } = string.Empty; [SugarColumn(ColumnName = "Content", ColumnDataType = "text")] public string Content { get; set; } = string.Empty; } } ``` #### 2. 创建 DTO(Application.Contracts 层) 在 `YourModule.Application.Contracts/Dtos/News/` 创建: ```csharp // NewsGetOutputDto.cs - 详情输出 DTO using Volo.Abp.Application.Dtos; namespace YourModule.Application.Contracts.Dtos.News { public class NewsGetOutputDto : EntityDto { public string Title { get; set; } public string Content { get; set; } public DateTime CreationTime { get; set; } } } // NewsGetListOutputDto.cs - 列表输出 DTO public class NewsGetListOutputDto : EntityDto { public string Title { get; set; } public DateTime CreationTime { get; set; } } // NewsGetListInputVo.cs - 查询参数 using Yi.Framework.Ddd.Application.Contracts; public class NewsGetListInputVo : PagedAllResultRequestDto { public string? Title { get; set; } } // NewsCreateInputVo.cs - 创建输入 namespace YourModule.Application.Contracts.Dtos.News { public class NewsCreateInputVo { public string Title { get; set; } public string Content { get; set; } } } // NewsUpdateInputVo.cs - 更新输入 public class NewsUpdateInputVo { public string Title { get; set; } public string Content { get; set; } } ``` #### 3. 创建服务接口(Application.Contracts 层) 在 `YourModule.Application.Contracts/IServices/` 创建: ```csharp using Yi.Framework.Ddd.Application.Contracts; using YourModule.Application.Contracts.Dtos.News; namespace YourModule.Application.Contracts.IServices { public interface INewsService : IYiCrudAppService< NewsGetOutputDto, NewsGetListOutputDto, Guid, NewsGetListInputVo, NewsCreateInputVo, NewsUpdateInputVo> { } } ``` #### 4. 实现服务(Application 层) 在 `YourModule.Application/Services/` 创建: ```csharp using SqlSugar; using Volo.Abp.Application.Dtos; using Yi.Framework.Ddd.Application; using Yi.Framework.SqlSugarCore.Abstractions; using YourModule.Application.Contracts.Dtos.News; using YourModule.Application.Contracts.IServices; using YourModule.Domain.Entities; namespace YourModule.Application.Services { public class NewsService : YiCrudAppService< NewsAggregateRoot, NewsGetOutputDto, NewsGetListOutputDto, Guid, NewsGetListInputVo, NewsCreateInputVo, NewsUpdateInputVo>, INewsService { private ISqlSugarRepository _repository; public NewsService(ISqlSugarRepository repository) : base(repository) { _repository = repository; } // 自定义查询逻辑(可选) public override async Task> GetListAsync(NewsGetListInputVo input) { RefAsync total = 0; var entities = await _repository._DbQueryable .WhereIF(!string.IsNullOrEmpty(input.Title), x => x.Title.Contains(input.Title!)) .OrderByDescending(x => x.CreationTime) .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); return new PagedResultDto( total, await MapToGetListOutputDtosAsync(entities) ); } } } ``` #### 5. 注册模块和动态 API 在 `Yi.Abp.Web/YiAbpWebModule.cs` 中: ```csharp // 1. 添加模块依赖 [DependsOn( typeof(YourModuleApplicationModule), // 添加你的模块 // ... 其他依赖 )] // 2. 注册动态 API PreConfigure(options => { options.ConventionalControllers.Create( typeof(YourModuleApplicationModule).Assembly, options => options.RemoteServiceName = "你的模块名称" ); }); ``` #### 6. 完成! 启动项目后,自动生成以下 API: - `GET /api/app/news` - 分页查询 - `GET /api/app/news/{id}` - 查询详情 - `POST /api/app/news` - 创建 - `PUT /api/app/news/{id}` - 更新 - `DELETE /api/app/news/{id}` - 删除 数据库表会在首次启动时自动创建(CodeFirst)。 --- ## ⚙️ 配置说明 ### 数据库配置 ```json { "DbConnOptions": { "Url": "数据库连接字符串", "DbType": "Mysql", // 数据库类型 "EnabledCodeFirst": true, // 是否自动创建表 "EnabledDbSeed": true, // 是否初始化种子数据 "EnabledSqlLog": true, // 是否记录SQL日志 "EnabledSaasMultiTenancy": false, // 是否启用多租户 "EnabledConcurrencyException": false // 是否启用乐观锁 } } ``` ### JWT 配置 ```json { "JwtOptions": { "Issuer": "https://ccnetcore.com", "Audience": "https://ccnetcore.com", "SecurityKey": "你的密钥", "ExpiresMinuteTime": 86400 // Token 过期时间(分钟) } } ``` ### Redis 配置(可选) ```json { "Redis": { "IsEnabled": false, "Configuration": "127.0.0.1:6379,password=123,defaultDatabase=13", "JobDb": 13 } } ``` ### 权限管理配置 ```json { "RbacOptions": { "AdminPassword": "123456", // 默认管理员密码 "EnableCaptcha": false, // 是否启用验证码 "EnableRegister": false, // 是否允许注册 "EnableDataBaseBackup": false // 是否启用数据库备份 } } ``` --- ## 📚 更多文档 - [框架快速开始教程](https://ccnetcore.com/article/aaa00329-7f35-d3fe-d258-3a0f8380b742) - [框架功能模块教程](https://ccnetcore.com/article/8c464ab3-8ba5-2761-a4b0-3a0f83a9f312) - [实战演练开发教程](https://ccnetcore.com/article/e89c9593-f337-ada7-d108-3a0f83ae48e6) - [社区导航大全](https://ccnetcore.com/article/aaa00329-7f35-d3fe-d258-3a0f8380b742/fb8c871b-41fc-21bc-474f-3a154498f42b) --- ## 🎁 内置模块 - ✅ **RBAC 权限管理系统** - 完整的用户权限管理 - ✅ **租户管理模块** - 多租户支持 - ✅ **审计日志模块** - 操作日志记录 - ✅ **设置管理模块** - 系统配置管理 --- ## 🌟 特性 - ✅ **开箱即用**:默认 SQLite,无需配置即可运行 - ✅ **CodeFirst**:自动创建数据库表结构 - ✅ **种子数据**:自动初始化基础数据 - ✅ **动态 API**:无需手写 Controller - ✅ **CRUD 基类**:快速开发增删改查 - ✅ **权限控制**:内置完整的权限管理 - ✅ **多租户**:支持 SaaS 架构 - ✅ **模块化**:功能模块化,按需引用 - ✅ **源码开放**:框架源码直接提供,方便学习和二开 --- ## 🔧 常见问题 ### Q: 如何切换数据库? A: 修改 `appsettings.json` 中的 `DbConnOptions` 配置,设置 `DbType` 和 `Url`。 ### Q: 如何禁用 CodeFirst 自动建表? A: 设置 `EnabledCodeFirst: false`,然后手动执行 SQL 脚本创建表。 ### Q: 如何添加新的业务模块? A: **所有业务代码都应该在 `module` 目录下创建自己的模块**。参考 `antis-erp` 模块的结构,创建包含 Domain.Shared、Domain、Application.Contracts、Application、SqlSugarCore 五个项目的模块,然后在 `YiAbpWebModule.cs` 中注册模块依赖和动态 API。 ### Q: 如何自定义 API 路由? A: 在服务方法上使用 `[Route("your-route")]` 特性。 ### Q: 如何启用多租户? A: 设置 `EnabledSaasMultiTenancy: true`,并在 Swagger 中使用 `__tenant` 参数指定租户。 --- ## 📞 联系我们 - **官网**:[ccnetcore.com](https://ccnetcore.com) - **演示地址**:[data.ccnetcore.com:2000](https://data.ccnetcore.com:2000)(账号:admin / 密码:123456) - **QQ 群**:981136525(官方五群) - **微信**:添加 `chengzilaoge520`(备注:拉群) --- ## 📄 许可证 本项目采用 [MIT](LICENSE) 许可证。 --- ## 🙏 致谢 感谢以下开源项目: - [ABP Framework](https://github.com/abpframework/abp) - [SqlSugar](https://www.donet5.com/) - [Vben Admin](https://github.com/vbenjs/vben-admin-thin-next) ---
**⭐ 如果这个项目对你有帮助,请给个 Star ⭐** Made with ❤️ by [Yi Framework Team](https://ccnetcore.com)