515fceeb
“wangming”
框架初始化
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
# 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`
|
515fceeb
“wangming”
框架初始化
|
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
|
> 💡 **提示**:
> - 首次启动会自动创建数据库表(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<AbpAspNetCoreMvcOptions>(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<Guid>, 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<Guid>
{
public string Title { get; set; }
public string Content { get; set; }
public DateTime CreationTime { get; set; }
}
}
// NewsGetListOutputDto.cs - 列表输出 DTO
public class NewsGetListOutputDto : EntityDto<Guid>
{
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<NewsAggregateRoot, Guid> _repository;
public NewsService(ISqlSugarRepository<NewsAggregateRoot, Guid> repository)
: base(repository)
{
_repository = repository;
}
// 自定义查询逻辑(可选)
public override async Task<PagedResultDto<NewsGetListOutputDto>> GetListAsync(NewsGetListInputVo input)
{
RefAsync<int> 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<NewsGetListOutputDto>(
total,
await MapToGetListOutputDtosAsync(entities)
);
}
}
}
```
#### 5. 注册模块和动态 API
在 `Yi.Abp.Web/YiAbpWebModule.cs` 中:
```csharp
// 1. 添加模块依赖
[DependsOn(
typeof(YourModuleApplicationModule), // 添加你的模块
// ... 其他依赖
)]
// 2. 注册动态 API
PreConfigure<AbpAspNetCoreMvcOptions>(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)
|