|
|
# Admin.NET 后端使用指南
|
|
|
|
|
|
## 1. 文档定位
|
|
|
|
|
|
本文是当前脚手架 `Admin.NET` 的后端使用指南,只聚焦 `Admin.NET/` 目录下的后端模块,不展开前端 `Web/` 的页面实现细节。
|
|
|
|
|
|
文档目标不是重复 README,而是把当前仓库里已经落地的后端能力、配置入口、开发方式、扩展边界、常见注意事项整理成可直接用于二开和交接的“后台手册”。
|
|
|
|
|
|
本文写法参考若依文档的组织方式,采用“功能说明 + 配置说明 + 使用方式 + 开发建议 + 注意事项”的结构,便于长期维护和按章节查阅。
|
|
|
|
|
|
## 2. 适用范围
|
|
|
|
|
|
- 适用于当前仓库 `C:\D\WORK\NewP\Admin.NET-v2`
|
|
|
- 适用于当前后端脚手架形态:`Furion + SqlSugar + 动态 API + 统一返回 + 多租户 + 插件化`
|
|
|
- 适用于基于 `Admin.NET.Core` 继续扩展 `MES/WMS/QMS/DMS/EMS/ERP` 业务模块的研发场景
|
|
|
|
|
|
## 3. 技术基线
|
|
|
|
|
|
### 3.1 运行时
|
|
|
|
|
|
- 后端核心项目当前为 `net8.0;net10.0` 双目标
|
|
|
- 宿主入口:`Admin.NET.Web.Entry`
|
|
|
- 启动装配:`Admin.NET.Web.Core`
|
|
|
- 基础设施核心:`Admin.NET.Core`
|
|
|
- 示例应用层:`Admin.NET.Application`
|
|
|
|
|
|
### 3.2 核心框架
|
|
|
|
|
|
- Web 装配:Furion
|
|
|
- 数据访问:SqlSugar
|
|
|
- 接口暴露:`IDynamicApiController`
|
|
|
- 统一返回:`AdminResultProvider`
|
|
|
- 统一鉴权:JWT + Signature + OAuth
|
|
|
- 任务调度:Furion Schedule
|
|
|
- 事件总线:Furion EventBus
|
|
|
- 缓存:Memory / Redis
|
|
|
- 即时通讯:SignalR
|
|
|
- 对外集成:声明式 HTTP / HttpClient / 插件
|
|
|
|
|
|
### 3.3 当前应用层默认引用插件
|
|
|
|
|
|
当前 `Admin.NET.Application.csproj` 默认引用:
|
|
|
|
|
|
- `Admin.NET.Plugin.ApprovalFlow`
|
|
|
- `Admin.NET.Plugin.DingTalk`
|
|
|
- `Admin.NET.Plugin.GoView`
|
|
|
- `Admin.NET.Plugin.HwPortal`
|
|
|
|
|
|
存在但当前未默认引用:
|
|
|
|
|
|
- `Admin.NET.Plugin.WorkWeixin`
|
|
|
- `Admin.NET.Plugin.K3Cloud`
|
|
|
- `Admin.NET.Plugin.ReZero`
|
|
|
|
|
|
## 4. 后端目录说明
|
|
|
|
|
|
### 4.1 目录结构
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Entry`
|
|
|
- 最薄宿主入口
|
|
|
- 负责 `Serve.Run` 启动和 Kestrel 基础限制
|
|
|
- `Admin.NET/Admin.NET.Web.Core`
|
|
|
- 后端总装配层
|
|
|
- 负责注册数据库、缓存、鉴权、日志、OSS、限流、SignalR、Swagger、任务调度等
|
|
|
- `Admin.NET/Admin.NET.Core`
|
|
|
- 基础设施与系统公共服务中心
|
|
|
- 包含 Entity、SqlSugar、Cache、Auth、Tenant、File、Template、Message、Logging、EventBus、SignalR 等
|
|
|
- `Admin.NET/Admin.NET.Application`
|
|
|
- 示例业务层与开放接口示例
|
|
|
- 包含 `Configuration` 与 `OpenApi`
|
|
|
- `Admin.NET/Plugins`
|
|
|
- 插件式扩展目录
|
|
|
|
|
|
### 4.2 推荐阅读顺序
|
|
|
|
|
|
建议阅读后端代码时固定按以下顺序建立上下文:
|
|
|
|
|
|
1. `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
2. `Admin.NET/Admin.NET.Web.Core/ProjectOptions.cs`
|
|
|
3. `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs`
|
|
|
4. `Admin.NET/Admin.NET.Core/Utils/AdminResultProvider.cs`
|
|
|
5. `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs`
|
|
|
6. `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs`
|
|
|
7. `Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs`
|
|
|
8. `Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs`
|
|
|
9. `Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs`
|
|
|
10. 对应模块的 `Service/*` 或 `Plugins/*`
|
|
|
|
|
|
## 5. 启动流程总览
|
|
|
|
|
|
### 5.1 宿主启动
|
|
|
|
|
|
`Admin.NET.Web.Entry/Program.cs` 通过 `Serve.Run(RunOptions.Default.AddWebComponent<WebComponent>())` 启动应用。
|
|
|
|
|
|
宿主层主要负责:
|
|
|
|
|
|
- 配置日志过滤
|
|
|
- 配置 Kestrel 超时与请求体大小
|
|
|
- 不承载具体业务能力注册
|
|
|
|
|
|
### 5.2 服务注册阶段
|
|
|
|
|
|
真正的服务注册发生在 `Admin.NET.Web.Core/Startup.cs`:
|
|
|
|
|
|
- `AddProjectOptions()`
|
|
|
- `AddCache()`
|
|
|
- `AddSqlSugar()`
|
|
|
- `AddJwt<JwtHandler>()`
|
|
|
- `AddSignatureAuthentication(...)`
|
|
|
- `AddCorsAccessor()`
|
|
|
- `AddHttpRemote()`
|
|
|
- `AddTaskQueue()`
|
|
|
- `AddSchedule(...)`
|
|
|
- `AddEventBus(...)`
|
|
|
- `AddOAuth()`
|
|
|
- `AddElasticSearchClients()`
|
|
|
- `AddImageSharp()`
|
|
|
- `AddOSSService(...)`
|
|
|
- `AddViewEngine()`
|
|
|
- `AddSignalR(...)`
|
|
|
- `AddLoggingSetup()`
|
|
|
- `AddCaptcha()`
|
|
|
|
|
|
### 5.3 中间件阶段
|
|
|
|
|
|
中间件链主要包括:
|
|
|
|
|
|
- 响应压缩
|
|
|
- 反向代理头处理
|
|
|
- 异常处理
|
|
|
- 静态文件
|
|
|
- OAuth Cookie 策略
|
|
|
- 统一状态码拦截
|
|
|
- 多语言
|
|
|
- 路由
|
|
|
- 跨域
|
|
|
- 认证授权
|
|
|
- 限流
|
|
|
- 任务看板
|
|
|
- Swagger / Scalar
|
|
|
- SignalR Hub
|
|
|
- MVC 路由
|
|
|
|
|
|
### 5.4 开发建议
|
|
|
|
|
|
- 不要把基础设施能力注册分散到业务服务类里
|
|
|
- 涉及新增全局能力时,优先补在 `Startup.cs` 和 `ProjectOptions.cs`
|
|
|
- 涉及插件能力时,优先放入插件自己的 `Startup.cs`
|
|
|
|
|
|
## 6. 零基础快速入门
|
|
|
|
|
|
这一节不讲抽象概念,只讲一个刚接手项目的人,如何从 0 到 1 把后端跑起来。
|
|
|
|
|
|
### 6.1 第一步:先改数据库配置
|
|
|
|
|
|
找到:
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Database.json`
|
|
|
|
|
|
最小可运行配置通常先用本地 `Sqlite`,例如:
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"DbConnection": {
|
|
|
"EnableConsoleSql": false,
|
|
|
"ConnectionConfigs": [
|
|
|
{
|
|
|
"DbType": "Sqlite",
|
|
|
"ConnectionString": "DataSource=./Admin.NET.db",
|
|
|
"DbSettings": {
|
|
|
"EnableInitDb": true,
|
|
|
"EnableInitView": true,
|
|
|
"EnableDiffLog": false,
|
|
|
"EnableUnderLine": false,
|
|
|
"EnableConnStringEncrypt": false
|
|
|
},
|
|
|
"TableSettings": {
|
|
|
"EnableInitTable": true,
|
|
|
"EnableIncreTable": false
|
|
|
},
|
|
|
"SeedSettings": {
|
|
|
"EnableInitSeed": true,
|
|
|
"EnableIncreSeed": false
|
|
|
}
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
如果你只是本地熟悉项目,先不要切多数据库、日志库、租户独立库,先把主库跑起来。
|
|
|
|
|
|
### 6.2 第二步:先跑后端
|
|
|
|
|
|
在项目根目录执行:
|
|
|
|
|
|
```powershell
|
|
|
dotnet restore Admin.NET\Admin.NET.sln
|
|
|
dotnet build Admin.NET\Admin.NET.sln -c Debug
|
|
|
dotnet run --project Admin.NET\Admin.NET.Web.Entry
|
|
|
```
|
|
|
|
|
|
如果数据库配置和初始化开关无误,第一次启动会自动建库、建表、建视图、写种子。
|
|
|
|
|
|
### 6.3 第三步:打开接口文档
|
|
|
|
|
|
启动成功后,优先看这两个入口:
|
|
|
|
|
|
- Swagger
|
|
|
- Scalar
|
|
|
|
|
|
在本项目中,文档能力由:
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Swagger.json`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
|
|
|
统一控制。
|
|
|
|
|
|
如果你只是想确认后端是否跑通,先看 Swagger 能否正常打开,再测试一个匿名接口或登录接口。
|
|
|
|
|
|
### 6.4 第四步:理解一个接口是怎么跑通的
|
|
|
|
|
|
推荐直接看:
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Application/OpenApi/DemoOpenApi.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs`
|
|
|
|
|
|
这是最快理解“动态 API + 统一认证 + 统一返回”的入口。
|
|
|
|
|
|
### 6.5 第五步:新增一个最小业务模块
|
|
|
|
|
|
最小业务模块通常至少需要四样东西:
|
|
|
|
|
|
1. 实体
|
|
|
2. Service
|
|
|
3. 菜单/权限
|
|
|
4. 页面或接口调试入口
|
|
|
|
|
|
最小实体示例:
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Entity/ExampleMaterial.cs
|
|
|
[SugarTable("sys_example_material", "示例物料")]
|
|
|
public class ExampleMaterial : EntityBaseTenantOrgDel
|
|
|
{
|
|
|
[SugarColumn(ColumnDescription = "物料编码", Length = 64)]
|
|
|
public string MaterialCode { get; set; }
|
|
|
|
|
|
[SugarColumn(ColumnDescription = "物料名称", Length = 128)]
|
|
|
public string MaterialName { get; set; }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
最小服务示例:
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleMaterialService.cs
|
|
|
[ApiDescriptionSettings("示例模块", Name = "ExampleMaterial", Order = 100)]
|
|
|
public class ExampleMaterialService : IDynamicApiController, ITransient
|
|
|
{
|
|
|
private readonly SqlSugarRepository<ExampleMaterial> _rep;
|
|
|
|
|
|
public ExampleMaterialService(SqlSugarRepository<ExampleMaterial> rep)
|
|
|
{
|
|
|
_rep = rep;
|
|
|
}
|
|
|
|
|
|
[HttpGet("page")]
|
|
|
public Task<SqlSugarPagedList<ExampleMaterial>> Page([FromQuery] BasePageInput input)
|
|
|
{
|
|
|
return _rep.AsQueryable()
|
|
|
.OrderBy(x => x.CreateTime, OrderByType.Desc)
|
|
|
.ToPagedListAsync(input.Page, input.PageSize);
|
|
|
}
|
|
|
|
|
|
[HttpPost("add")]
|
|
|
public Task<bool> Add([FromBody] ExampleMaterial input)
|
|
|
{
|
|
|
return _rep.InsertAsync(input);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
这样你就已经具备了一个最小可调试业务模块。
|
|
|
|
|
|
### 6.6 第六步:再考虑菜单和权限
|
|
|
|
|
|
很多新人会在“接口已经能调通”后忘记权限体系,结果前端页面上按钮、菜单、权限控制全部不通。
|
|
|
|
|
|
当前项目权限控制的关键认知是:
|
|
|
|
|
|
- 菜单和按钮权限本质上绑定到 `SysMenu.Permission`
|
|
|
- `JwtHandler` 会按请求路由去匹配按钮权限
|
|
|
- 所以你的接口命名和菜单权限命名要保持一致的规则
|
|
|
|
|
|
最小认知示例:
|
|
|
|
|
|
```text
|
|
|
接口路由:/api/exampleMaterial/page
|
|
|
对应按钮权限:exampleMaterial:page
|
|
|
```
|
|
|
|
|
|
如果接口存在,但当前用户没有这个按钮权限,就会被 `JwtHandler` 拦截。
|
|
|
|
|
|
### 6.7 第七步:再上代码生成器
|
|
|
|
|
|
建议先手写跑通一个最小模块,再去用代码生成器。
|
|
|
|
|
|
原因是很多新人一开始直接用生成器,但不知道生成出来的:
|
|
|
|
|
|
- 实体该放哪里
|
|
|
- DTO 为什么这样命名
|
|
|
- 菜单按钮为什么这么生成
|
|
|
- 接口权限为什么是这套规则
|
|
|
|
|
|
先理解后再生成,后续二次收敛会轻松很多。
|
|
|
|
|
|
## 7. 新建业务模块完整示例
|
|
|
|
|
|
这一节给出一个更接近实际开发的“物料主数据”最小链路,适合做培训和交接时演示。
|
|
|
|
|
|
### 7.1 场景目标
|
|
|
|
|
|
目标是新增一个“物料主数据”模块,至少具备:
|
|
|
|
|
|
- 物料分页查询
|
|
|
- 新增物料
|
|
|
- 编辑物料
|
|
|
- 删除物料
|
|
|
- 菜单权限可控
|
|
|
|
|
|
### 7.2 第一步:新增实体
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Entity/ExampleMaterial.cs
|
|
|
[SugarTable("sys_example_material", "示例物料")]
|
|
|
public class ExampleMaterial : EntityBaseTenantOrgDel
|
|
|
{
|
|
|
[SugarColumn(ColumnDescription = "物料编码", Length = 64)]
|
|
|
public string MaterialCode { get; set; }
|
|
|
|
|
|
[SugarColumn(ColumnDescription = "物料名称", Length = 128)]
|
|
|
public string MaterialName { get; set; }
|
|
|
|
|
|
[SugarColumn(ColumnDescription = "状态")]
|
|
|
public int Status { get; set; }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 7.3 第二步:新增 DTO
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/Dto/ExampleMaterialInput.cs
|
|
|
public class ExampleMaterialInput : BasePageInput
|
|
|
{
|
|
|
public string Keyword { get; set; }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 7.4 第三步:新增 Service
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleMaterialService.cs
|
|
|
[ApiDescriptionSettings("示例模块", Name = "ExampleMaterial", Order = 100)]
|
|
|
public class ExampleMaterialService : IDynamicApiController, ITransient
|
|
|
{
|
|
|
private readonly SqlSugarRepository<ExampleMaterial> _rep;
|
|
|
|
|
|
public ExampleMaterialService(SqlSugarRepository<ExampleMaterial> rep)
|
|
|
{
|
|
|
_rep = rep;
|
|
|
}
|
|
|
|
|
|
[HttpGet("page")]
|
|
|
public Task<SqlSugarPagedList<ExampleMaterial>> Page([FromQuery] ExampleMaterialInput input)
|
|
|
{
|
|
|
return _rep.AsQueryable()
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), x => x.MaterialCode.Contains(input.Keyword) || x.MaterialName.Contains(input.Keyword))
|
|
|
.OrderBy(x => x.CreateTime, OrderByType.Desc)
|
|
|
.ToPagedListAsync(input.Page, input.PageSize);
|
|
|
}
|
|
|
|
|
|
[HttpPost("add")]
|
|
|
public Task<bool> Add([FromBody] ExampleMaterial input)
|
|
|
{
|
|
|
return _rep.InsertAsync(input);
|
|
|
}
|
|
|
|
|
|
[HttpPost("update")]
|
|
|
public Task<bool> Update([FromBody] ExampleMaterial input)
|
|
|
{
|
|
|
return _rep.UpdateAsync(input);
|
|
|
}
|
|
|
|
|
|
[HttpPost("delete")]
|
|
|
public Task<bool> Delete([FromBody] BaseIdInput input)
|
|
|
{
|
|
|
return _rep.DeleteAsync(x => x.Id == input.Id);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 7.5 第四步:配置菜单和按钮权限
|
|
|
|
|
|
如果你是手工建模块,而不是用代码生成器,就必须自己配置菜单和按钮权限。
|
|
|
|
|
|
最少要保证下面几个权限名和接口路由规则一致:
|
|
|
|
|
|
- `exampleMaterial:page`
|
|
|
- `exampleMaterial:add`
|
|
|
- `exampleMaterial:update`
|
|
|
- `exampleMaterial:delete`
|
|
|
|
|
|
否则即使接口开发完成,页面和权限体系也无法正常协同。
|
|
|
|
|
|
### 7.6 第五步:调试接口
|
|
|
|
|
|
用 Swagger 先验证:
|
|
|
|
|
|
1. `page` 是否能返回分页结果
|
|
|
2. `add` 后审计字段、租户字段是否自动写入
|
|
|
3. `delete` 是否按软删除逻辑生效
|
|
|
|
|
|
### 7.7 第六步:再决定是否切回代码生成器
|
|
|
|
|
|
如果这个流程你已经理解了,再去使用代码生成器,你就知道:
|
|
|
|
|
|
- 为什么生成出来的 Service 是那种结构
|
|
|
- 为什么 DTO 要分输入输出
|
|
|
- 为什么菜单按钮权限会按固定规则生成
|
|
|
- 为什么有些通用字段不建议自己再写
|
|
|
|
|
|
### 7.8 新手常见错误
|
|
|
|
|
|
- 只建实体,不建 DTO,后面接口难维护
|
|
|
- 直接用实体做所有出入参,导致字段污染
|
|
|
- 忘了配置菜单权限,页面一进来就 403
|
|
|
- 没注意租户基类,数据串租户
|
|
|
- 为了快直接 `ClearFilter()`,后面权限全失真
|
|
|
|
|
|
### 7.9 建议培训顺序
|
|
|
|
|
|
如果你要带新人,建议按下面顺序培训:
|
|
|
|
|
|
1. 先让他跑通登录和 Swagger
|
|
|
2. 再让他看一个现成 Service
|
|
|
3. 再让他手写一个最小模块
|
|
|
4. 最后再让他用代码生成器
|
|
|
|
|
|
这样效果比“先教生成器”要好很多
|
|
|
|
|
|
---
|
|
|
|
|
|
# 第一章 框架简介
|
|
|
|
|
|
## 1.1 功能说明
|
|
|
|
|
|
Admin.NET 当前后端脚手架的核心特征是:
|
|
|
|
|
|
- 以 `Furion` 作为应用启动、动态 API、统一返回、鉴权、调度、事件总线的基础框架
|
|
|
- 以 `SqlSugar` 作为 ORM 与多库多租户封装核心
|
|
|
- 以 `IDynamicApiController` 作为默认接口暴露方式
|
|
|
- 以 `Admin.NET.Core` 作为长期复用的基础设施中心
|
|
|
- 以插件方式扩展外部集成或独立业务能力
|
|
|
|
|
|
这意味着后端开发不是传统的“Controller + Service + Mapper”裸三层模式,而是“统一基础设施 + 业务服务动态暴露 + 系统能力门面复用”的模式。
|
|
|
|
|
|
## 1.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/ProjectOptions.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/AdminResultProvider.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs`
|
|
|
|
|
|
## 1.3 当前脚手架特征
|
|
|
|
|
|
- 默认启用全局鉴权
|
|
|
- 默认支持多租户
|
|
|
- 默认支持代码生成
|
|
|
- 默认支持文件上传下载
|
|
|
- 默认支持模板渲染
|
|
|
- 默认支持日志记录
|
|
|
- 默认支持任务调度看板
|
|
|
- 默认支持 Swagger / Scalar
|
|
|
- 默认支持开放接口签名鉴权
|
|
|
|
|
|
## 1.4 开发建议
|
|
|
|
|
|
- 把 `Admin.NET.Core` 视为“平台基础设施层”,不要在里面堆积强业务逻辑
|
|
|
- 业务模块优先新建独立应用层或插件层
|
|
|
- 复用现有封装优先级高于自行新建通用组件
|
|
|
|
|
|
## 1.5 注意事项
|
|
|
|
|
|
- README 中提到的功能并不等于全部都已经形成完整的后端开箱即用链路
|
|
|
- 后端实际能力边界必须以代码实现为准,而不是以宣传文案为准
|
|
|
|
|
|
# 第二章 开发流程
|
|
|
|
|
|
## 2.1 开发思路
|
|
|
|
|
|
建议的开发流程如下:
|
|
|
|
|
|
1. 阅读 `Startup`、`ProjectOptions`、`SqlSugarSetup`
|
|
|
2. 确认功能是否已有系统服务可复用
|
|
|
3. 补配置文件与 Options 绑定
|
|
|
4. 建实体并选择合适基类
|
|
|
5. 建服务并实现 `IDynamicApiController`
|
|
|
6. 复用 `SqlSugarRepository<T>`、`SysCacheService` 等门面
|
|
|
7. 补日志、权限、租户、导入导出等周边能力
|
|
|
8. 编译验证与必要测试
|
|
|
|
|
|
## 2.2 常用命令
|
|
|
|
|
|
```powershell
|
|
|
dotnet restore Admin.NET\Admin.NET.sln
|
|
|
dotnet build Admin.NET\Admin.NET.sln -c Debug
|
|
|
dotnet run --project Admin.NET\Admin.NET.Web.Entry
|
|
|
dotnet test Admin.NET\Admin.NET.Test\Admin.NET.Test.csproj
|
|
|
```
|
|
|
|
|
|
## 2.3 新增业务模块推荐路径
|
|
|
|
|
|
推荐优先在独立应用层或插件层新增:
|
|
|
|
|
|
- 实体
|
|
|
- DTO
|
|
|
- Service
|
|
|
- 配置文件
|
|
|
- 种子数据
|
|
|
|
|
|
不建议直接修改平台核心,除非:
|
|
|
|
|
|
- 现有基础设施确实缺少扩展点
|
|
|
- 修改后具备明显的通用复用价值
|
|
|
- 不会破坏租户、权限、日志、缓存主链路
|
|
|
|
|
|
## 2.4 典型开发步骤
|
|
|
|
|
|
### 2.4.1 新增配置
|
|
|
|
|
|
- 在 `Admin.NET.Application/Configuration` 增加 json
|
|
|
- 在 `ProjectOptions.cs` 增加 `AddConfigurableOptions<T>()`
|
|
|
- 补对应 `Option/*.cs`
|
|
|
|
|
|
### 2.4.2 新增实体
|
|
|
|
|
|
- 放到 `Admin.NET.Core/Entity` 或业务项目实体目录
|
|
|
- 标注 `SugarTable`
|
|
|
- 继承合适的实体基类
|
|
|
|
|
|
### 2.4.3 新增服务
|
|
|
|
|
|
- 放到 `Service/*`
|
|
|
- 默认实现 `IDynamicApiController`
|
|
|
- 通过 `ApiDescriptionSettings` 配置分组、顺序与说明
|
|
|
|
|
|
### 2.4.4 新增外部集成
|
|
|
|
|
|
- 优先走插件目录
|
|
|
- 优先走声明式 HTTP
|
|
|
- 优先放配置、DTO、Proxy、Service 成体系目录
|
|
|
|
|
|
## 2.5 注意事项
|
|
|
|
|
|
- 避免在业务代码中直接访问裸配置节点字符串
|
|
|
- 避免绕过统一返回、统一缓存、统一仓储
|
|
|
- 避免硬编码状态流转、阈值、审批规则
|
|
|
|
|
|
# 第三章 数据库配置
|
|
|
|
|
|
## 3.1 功能说明
|
|
|
|
|
|
当前项目数据库能力由 `SqlSugarSetup` 统一接入,支持:
|
|
|
|
|
|
- 多连接
|
|
|
- 主从读写
|
|
|
- 日志库
|
|
|
- 独立租户库
|
|
|
- 自动建库建表
|
|
|
- 自动建视图
|
|
|
- 自动种子初始化
|
|
|
- 全局过滤器
|
|
|
- 审计字段自动赋值
|
|
|
- 慢 SQL / 错误 SQL / 差异日志
|
|
|
|
|
|
## 3.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Database.json`
|
|
|
- `Admin.NET/Admin.NET.Core/Option/DbConnectionOptions.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs`
|
|
|
|
|
|
## 3.3 配置说明
|
|
|
|
|
|
主配置节点:`DbConnection`
|
|
|
|
|
|
重点配置项:
|
|
|
|
|
|
- `EnableConsoleSql`
|
|
|
- `ConnectionConfigs`
|
|
|
- `DbSettings.EnableInitDb`
|
|
|
- `DbSettings.EnableInitView`
|
|
|
- `DbSettings.EnableDiffLog`
|
|
|
- `DbSettings.EnableUnderLine`
|
|
|
- `DbSettings.EnableConnStringEncrypt`
|
|
|
- `TableSettings.EnableInitTable`
|
|
|
- `TableSettings.EnableIncreTable`
|
|
|
- `SeedSettings.EnableInitSeed`
|
|
|
- `SeedSettings.EnableIncreSeed`
|
|
|
|
|
|
## 3.4 使用方式
|
|
|
|
|
|
### 3.4.1 默认库
|
|
|
|
|
|
`ConnectionConfigs` 第一项默认作为主库使用,若 `ConfigId` 未显式配置,会在 `PostConfigure` 中自动补为主库 ID。
|
|
|
|
|
|
### 3.4.2 日志库
|
|
|
|
|
|
可配置固定日志库连接,用于写入日志与差异记录。
|
|
|
|
|
|
### 3.4.3 租户库
|
|
|
|
|
|
租户数据库隔离时,会通过 `SysTenantService.GetTenantDbConnectionScope()` 动态创建连接。
|
|
|
|
|
|
## 3.5 开发建议
|
|
|
|
|
|
- 开发环境可打开表初始化与种子初始化
|
|
|
- 生产环境建议关闭自动初始化
|
|
|
- 多业务库时,统一放入 `ConnectionConfigs` 管理
|
|
|
- 数据库连接串加密统一走国密工具,不要自行发明一套加解密逻辑
|
|
|
|
|
|
## 3.6 注意事项
|
|
|
|
|
|
- 配置类属性实际使用的是 `EnableConnStringEncrypt`
|
|
|
- 示例配置文件中写成 `EnableConnEncrypt`,启用前应以代码属性为准修正
|
|
|
- 涉及表结构同步前,应先确认视图是否会阻塞表更新
|
|
|
|
|
|
# 第四章 实体基类
|
|
|
|
|
|
## 4.1 功能说明
|
|
|
|
|
|
实体基类决定了当前业务对象是否具备:
|
|
|
|
|
|
- 主键
|
|
|
- 审计字段
|
|
|
- 软删除
|
|
|
- 机构过滤
|
|
|
- 租户过滤
|
|
|
|
|
|
当前脚手架已经把大部分系统字段封装进基类,不建议重复定义。
|
|
|
|
|
|
## 4.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Entity/EntityBase.cs`
|
|
|
|
|
|
## 4.3 基类说明
|
|
|
|
|
|
### 4.3.1 通用基类
|
|
|
|
|
|
- `EntityBaseId`
|
|
|
- `EntityBase`
|
|
|
- `EntityBaseDel`
|
|
|
|
|
|
### 4.3.2 数据权限基类
|
|
|
|
|
|
- `EntityBaseOrg`
|
|
|
- `EntityBaseOrgDel`
|
|
|
|
|
|
### 4.3.3 多租户基类
|
|
|
|
|
|
- `EntityBaseTenant`
|
|
|
- `EntityBaseTenantDel`
|
|
|
- `EntityBaseTenantId`
|
|
|
- `EntityBaseTenantOrg`
|
|
|
- `EntityBaseTenantOrgDel`
|
|
|
|
|
|
## 4.4 使用方式
|
|
|
|
|
|
- 普通系统表:继承 `EntityBase` 或 `EntityBaseDel`
|
|
|
- 需要按机构做数据权限:继承 `EntityBaseOrg` 或 `EntityBaseOrgDel`
|
|
|
- 需要多租户隔离:继承 `EntityBaseTenant*`
|
|
|
|
|
|
## 4.5 开发建议
|
|
|
|
|
|
- 主键统一使用雪花 ID
|
|
|
- 租户字段统一走基类,不手动重复定义
|
|
|
- 软删表统一继承 `*Del`,避免一部分表软删、一部分表硬删导致行为不一致
|
|
|
|
|
|
## 4.6 注意事项
|
|
|
|
|
|
- 继承不同基类会直接影响全局过滤器生效方式
|
|
|
- 选错基类,后续租户或数据权限会出现隐蔽问题
|
|
|
|
|
|
# 第五章 缓存管理
|
|
|
|
|
|
## 5.1 功能说明
|
|
|
|
|
|
缓存是当前脚手架的基础门面能力之一,支持:
|
|
|
|
|
|
- Memory / Redis 切换
|
|
|
- 前缀管理
|
|
|
- 分布式锁
|
|
|
- Hash 结构
|
|
|
- 查询缓存桥接
|
|
|
- 缓存穿透防护式读取
|
|
|
|
|
|
## 5.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Cache/CacheSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Cache/SqlSugarCache.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Cache.json`
|
|
|
|
|
|
## 5.3 配置说明
|
|
|
|
|
|
主配置节点:`Cache`
|
|
|
|
|
|
重点配置项:
|
|
|
|
|
|
- `Prefix`
|
|
|
- `CacheType`
|
|
|
- `Redis.Configuration`
|
|
|
- `Redis.MaxMessageSize`
|
|
|
- `Redis.AutoDetect`
|
|
|
|
|
|
集群配置节点:`Cluster`
|
|
|
|
|
|
重点配置项:
|
|
|
|
|
|
- `Enabled`
|
|
|
- `SignalR.RedisConfiguration`
|
|
|
- `DataProtecteKey`
|
|
|
- `IsSentinel`
|
|
|
|
|
|
## 5.4 使用方式
|
|
|
|
|
|
### 5.4.1 基础读写
|
|
|
|
|
|
日常缓存统一通过 `SysCacheService.Set/Get/GetOrAdd`。
|
|
|
|
|
|
### 5.4.2 分布式锁
|
|
|
|
|
|
通过 `BeginCacheLock()` 获取锁,适合防重复提交、幂等控制、缓存重建等场景。
|
|
|
|
|
|
### 5.4.3 前缀清理
|
|
|
|
|
|
通过 `RemoveByPrefixKey()` 做批量清理,适合菜单、权限、配置、租户等缓存失效。
|
|
|
|
|
|
## 5.5 常见场景
|
|
|
|
|
|
- 登录失败次数
|
|
|
- Token 黑名单
|
|
|
- 开放接口 nonce
|
|
|
- 用户按钮权限
|
|
|
- 角色数据范围
|
|
|
- 多租户连接缓存
|
|
|
|
|
|
## 5.6 开发建议
|
|
|
|
|
|
- 统一使用 `CacheConst`
|
|
|
- 缓存 Key 命名要体现模块、对象、主键、作用域
|
|
|
- 业务模块不要直接耦合具体 Redis 类型操作
|
|
|
|
|
|
## 5.7 注意事项
|
|
|
|
|
|
- 内存缓存只适合单节点或开发场景
|
|
|
- 多节点部署且涉及在线用户、Token 黑名单、限流、SignalR 时应优先启用 Redis
|
|
|
|
|
|
# 第六章 导入导出
|
|
|
|
|
|
## 6.1 功能说明
|
|
|
|
|
|
当前脚手架已形成较完整的 Excel 导入导出基础能力,支持:
|
|
|
|
|
|
- Excel 模板导出
|
|
|
- Excel 数据导出
|
|
|
- Excel 导入
|
|
|
- 字典值转换
|
|
|
- 导入错误标记
|
|
|
- 下拉模板列
|
|
|
- 轻量级 MiniExcel 导入导出
|
|
|
|
|
|
## 6.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/CommonUtil.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/ExcelHelper.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/MiniExcelUtil.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/BaseImportInput.cs`
|
|
|
|
|
|
## 6.3 现有技术实现
|
|
|
|
|
|
- `Magicodes.IE`
|
|
|
- `EPPlus`
|
|
|
- `MiniExcel`
|
|
|
|
|
|
## 6.4 使用方式
|
|
|
|
|
|
### 6.4.1 导入模板
|
|
|
|
|
|
导入 DTO 继承 `BaseImportInput`,并通过 `ImporterHeader` / `ExporterHeader` 控制列行为。
|
|
|
|
|
|
### 6.4.2 导入校验
|
|
|
|
|
|
使用 `ExcelHelper.ImportData<IN,T>()`,可在导入后对数据做业务校验,并将错误信息回写到导出文件中。
|
|
|
|
|
|
### 6.4.3 字典转换
|
|
|
|
|
|
使用现有字典特性和 `CommonUtil` 中的导入导出映射,不要自己维护文本值与编码值转换逻辑。
|
|
|
|
|
|
## 6.5 开发建议
|
|
|
|
|
|
- 导入模板与业务表分离,避免直接暴露实体
|
|
|
- 错误信息统一进入 `Error` 字段
|
|
|
- 大批量导入建议加异步处理与日志记录
|
|
|
|
|
|
## 6.6 注意事项
|
|
|
|
|
|
- 导入文件应复用上传服务处理,不要绕过文件统一能力
|
|
|
- 字段顺序与列名变化后,应同步更新模板与导入 DTO
|
|
|
|
|
|
# 第七章 上传下载
|
|
|
|
|
|
## 7.1 功能说明
|
|
|
|
|
|
当前脚手架的文件能力统一由 `SysFileService` 承载,支持:
|
|
|
|
|
|
- 单文件上传
|
|
|
- 多文件上传
|
|
|
- Base64 上传
|
|
|
- 文件下载
|
|
|
- 文件预览
|
|
|
- Base64 下载
|
|
|
- 头像上传
|
|
|
- 电子签名上传
|
|
|
- 文件与业务主键绑定
|
|
|
|
|
|
## 7.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/File/FileProvider/DefaultFileProvider.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/File/FileProvider/MultiOSSFileProvider.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/File/FileProvider/OSSFileProvider.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/File/FileProvider/SSHFileProvider.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Upload.json`
|
|
|
|
|
|
## 7.3 配置说明
|
|
|
|
|
|
主配置节点:
|
|
|
|
|
|
- `Upload`
|
|
|
- `OSSProvider`
|
|
|
- `SSHProvider`
|
|
|
- `MultiOSS`
|
|
|
|
|
|
重点配置项:
|
|
|
|
|
|
- `Upload.Path`
|
|
|
- `Upload.MaxSize`
|
|
|
- `Upload.ContentType`
|
|
|
- `Upload.EnableMd5`
|
|
|
- `OSSProvider.Enabled`
|
|
|
- `OSSProvider.Provider`
|
|
|
- `MultiOSS.Enabled`
|
|
|
|
|
|
## 7.4 使用方式
|
|
|
|
|
|
### 7.4.1 普通业务文件
|
|
|
|
|
|
直接调用 `UploadFile()` 或 `UploadFiles()`。
|
|
|
|
|
|
### 7.4.2 图片类附件
|
|
|
|
|
|
可通过 `UploadAvatar()`、`UploadSignature()` 进行用户头像和签名文件处理。
|
|
|
|
|
|
### 7.4.3 业务实体关联文件
|
|
|
|
|
|
通过:
|
|
|
|
|
|
- `UpdateFileByDataId()`
|
|
|
- `DeleteFileByDataId()`
|
|
|
|
|
|
实现文件和业务主键绑定与清理。
|
|
|
|
|
|
## 7.5 开发建议
|
|
|
|
|
|
- 附件统一保存到 `SysFile`
|
|
|
- 不在业务表中直接存物理路径
|
|
|
- 需要多存储时优先使用 MultiOSS,而不是手写多套上传逻辑
|
|
|
|
|
|
## 7.6 注意事项
|
|
|
|
|
|
- 当前校验是基于 ContentType 与后缀,不是完整的内容安全扫描
|
|
|
- 高安全场景建议叠加病毒扫描、MIME 深度校验和访问鉴权控制
|
|
|
|
|
|
# 第八章 模板打印
|
|
|
|
|
|
## 8.1 功能说明
|
|
|
|
|
|
当前脚手架关于“模板打印”已具备两层底座:
|
|
|
|
|
|
- 打印模板管理
|
|
|
- 通用模板渲染
|
|
|
|
|
|
适合构建:
|
|
|
|
|
|
- 消息模板
|
|
|
- 标签模板
|
|
|
- 工票模板
|
|
|
- 通知模板
|
|
|
- 业务文本渲染模板
|
|
|
|
|
|
## 8.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Print/SysPrintService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Template/SysTemplateService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Entity/SysPrint.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Entity/SysTemplate.cs`
|
|
|
|
|
|
## 8.3 使用方式
|
|
|
|
|
|
### 8.3.1 打印模板管理
|
|
|
|
|
|
通过 `SysPrintService` 管理打印模板的增删改查和分页查询。
|
|
|
|
|
|
### 8.3.2 通用模板渲染
|
|
|
|
|
|
通过 `SysTemplateService.Render()` 或 `RenderByCode()` 渲染模板内容,底层依赖 `IViewEngine`。
|
|
|
|
|
|
### 8.3.3 模板预览
|
|
|
|
|
|
通过 `ProView()` 对模板内容进行预览。
|
|
|
|
|
|
## 8.4 当前边界
|
|
|
|
|
|
当前已确认的能力更偏:
|
|
|
|
|
|
- 模板管理
|
|
|
- 模板文本渲染
|
|
|
- 打印模板元数据管理
|
|
|
|
|
|
当前未确认存在统一的:
|
|
|
|
|
|
- 服务端 PDF 输出中心
|
|
|
- 打印任务队列
|
|
|
- 打印机路由管理
|
|
|
- 标签批量套打总控
|
|
|
|
|
|
## 8.5 开发建议
|
|
|
|
|
|
- 业务变化频繁的打印内容优先用模板存储,不要写死在代码里
|
|
|
- 模板编码统一由业务常量管理
|
|
|
- 打印数据组装放业务服务,模板渲染放模板服务
|
|
|
|
|
|
## 8.6 注意事项
|
|
|
|
|
|
- 模板层适合“渲染”,不适合承载复杂业务判断
|
|
|
- 真正复杂的打印排版仍建议在独立打印模块中继续扩展
|
|
|
|
|
|
# 第九章 统一认证
|
|
|
|
|
|
## 9.1 功能说明
|
|
|
|
|
|
当前脚手架认证体系包含三条链路:
|
|
|
|
|
|
- JWT 认证
|
|
|
- Signature 开放接口签名认证
|
|
|
- OAuth 第三方登录认证
|
|
|
|
|
|
## 9.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SignatureAuth/SignatureAuthenticationHandler.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/OAuth/OAuthSetup.cs`
|
|
|
|
|
|
## 9.3 使用方式
|
|
|
|
|
|
### 9.3.1 JWT 认证
|
|
|
|
|
|
默认全局开启,未显式标记匿名的接口均需鉴权。
|
|
|
|
|
|
### 9.3.2 Signature 认证
|
|
|
|
|
|
用于开放接口,对外部系统通过 `accessKey/accessSecret + timestamp + nonce + sign` 做签名认证。
|
|
|
|
|
|
### 9.3.3 OAuth
|
|
|
|
|
|
当前默认接入:
|
|
|
|
|
|
- Weixin
|
|
|
- Gitee
|
|
|
|
|
|
## 9.4 当前能力
|
|
|
|
|
|
`SysAuthService` 已实现:
|
|
|
|
|
|
- 账号密码登录
|
|
|
- 手机验证码登录
|
|
|
- 用户注册
|
|
|
- 获取验证码
|
|
|
- 退出登录
|
|
|
- 获取当前登录信息
|
|
|
- 刷新 Token
|
|
|
- Swagger 登录
|
|
|
|
|
|
## 9.5 开发建议
|
|
|
|
|
|
- 管理后台接口走 JWT
|
|
|
- 对外系统接口走 Signature
|
|
|
- 三方登录场景走 OAuth,不混用 JWT 登录入口
|
|
|
|
|
|
## 9.6 注意事项
|
|
|
|
|
|
- 全局鉴权开启后,开放接口需显式走对应认证方案
|
|
|
- 不要把对外开放接口直接暴露成后台 JWT 接口
|
|
|
|
|
|
# 第十章 数据权限
|
|
|
|
|
|
## 10.1 功能说明
|
|
|
|
|
|
当前项目的数据权限由 SqlSugar 全局过滤器统一实现,不要求每个服务手写权限 where 条件。
|
|
|
|
|
|
## 10.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Enum/DataScopeEnum.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Entity/IEntityFilter.cs`
|
|
|
|
|
|
## 10.3 当前实现内容
|
|
|
|
|
|
- 软删除过滤
|
|
|
- 租户过滤
|
|
|
- 机构过滤
|
|
|
- 仅本人数据过滤
|
|
|
- 自定义实体过滤
|
|
|
|
|
|
## 10.4 使用方式
|
|
|
|
|
|
### 10.4.1 默认行为
|
|
|
|
|
|
只要实体继承了相应基类或实现了相应过滤接口,就会在查询时自动生效。
|
|
|
|
|
|
### 10.4.2 自定义过滤器
|
|
|
|
|
|
可以实现 `IEntityFilter`,通过 `AddEntityFilter()` 增加自定义条件。
|
|
|
|
|
|
### 10.4.3 缓存清理
|
|
|
|
|
|
角色、机构、用户权限变化后,需要清理相关缓存,否则数据范围可能延迟生效。
|
|
|
|
|
|
## 10.5 开发建议
|
|
|
|
|
|
- 业务查询先考虑是否被过滤器影响
|
|
|
- 不是所有跨租户、跨组织查询都应该 `ClearFilter()`
|
|
|
- 必须绕过过滤器时,要明确记录用途和权限边界
|
|
|
|
|
|
## 10.6 注意事项
|
|
|
|
|
|
- 查询结果“不全”时,优先排查过滤器
|
|
|
- 超管与普通用户的过滤行为不同
|
|
|
|
|
|
# 第十一章 即时通讯
|
|
|
|
|
|
## 11.1 功能说明
|
|
|
|
|
|
当前项目使用 SignalR 承载即时通讯与实时通知能力,适合:
|
|
|
|
|
|
- 在线用户
|
|
|
- 系统通知
|
|
|
- 实时消息推送
|
|
|
- 看板状态刷新
|
|
|
|
|
|
## 11.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/SignalR/SignalRSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Hub/OnlineUserHub.cs`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
|
|
|
## 11.3 使用方式
|
|
|
|
|
|
### 11.3.1 单机模式
|
|
|
|
|
|
默认直接注册 SignalR 即可运行。
|
|
|
|
|
|
### 11.3.2 集群模式
|
|
|
|
|
|
启用 Redis 缓存并开启 `Cluster.Enabled=true` 后,可使用 Redis Backplane 实现跨节点广播。
|
|
|
|
|
|
## 11.4 开发建议
|
|
|
|
|
|
- 即时消息只承载通知,不承载重业务事务
|
|
|
- 重要消息应同时落业务表或消息表,不要只依赖内存推送
|
|
|
|
|
|
## 11.5 注意事项
|
|
|
|
|
|
- 多节点部署时,单机 SignalR 无法跨节点广播
|
|
|
- 类名与程序集名可能影响 Redis Channel 路由隔离
|
|
|
|
|
|
# 第十二章 图片压缩
|
|
|
|
|
|
## 12.1 功能说明
|
|
|
|
|
|
当前项目已接入 ImageSharp 中间件,具备图片处理底座,但尚未形成统一的上传即压缩、缩略图生成、质量策略中心。
|
|
|
|
|
|
## 12.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs`
|
|
|
|
|
|
## 12.3 当前状态
|
|
|
|
|
|
当前已接入:
|
|
|
|
|
|
- `services.AddImageSharp()`
|
|
|
- `app.UseImageSharp()`
|
|
|
|
|
|
当前未确认统一存在:
|
|
|
|
|
|
- 上传后自动压缩
|
|
|
- 多尺寸缩略图生成
|
|
|
- 图片质量分级输出
|
|
|
- 图片 EXIF 清理
|
|
|
|
|
|
## 12.4 开发建议
|
|
|
|
|
|
- 若业务需要现场拍照压缩,建议扩展 `SysFileService` 或具体 `FileProvider`
|
|
|
- 压缩策略应可配置,不应写死分辨率、质量参数
|
|
|
|
|
|
## 12.5 注意事项
|
|
|
|
|
|
- 本章节当前属于“有底座、无统一业务实现”
|
|
|
- 后续扩展时应保持和现有文件存储体系一致
|
|
|
|
|
|
# 第十三章 接口限流
|
|
|
|
|
|
## 13.1 功能说明
|
|
|
|
|
|
当前项目已接入 `AspNetCoreRateLimit`,支持:
|
|
|
|
|
|
- IP 限流
|
|
|
- ClientId 限流
|
|
|
- 黑白名单
|
|
|
- 自定义超限返回值
|
|
|
|
|
|
## 13.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Option/RateLimitOptions.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Limit.json`
|
|
|
|
|
|
## 13.3 使用方式
|
|
|
|
|
|
### 13.3.1 IP 限流
|
|
|
|
|
|
通过 `IpRateLimiting` 配置全局或接口级访问频率。
|
|
|
|
|
|
### 13.3.2 客户端限流
|
|
|
|
|
|
通过 `ClientRateLimiting` 基于客户端标识做限流。
|
|
|
|
|
|
## 13.4 开发建议
|
|
|
|
|
|
- 登录、短信发送、开放接口、设备接入接口应单独限流
|
|
|
- 生产环境建议把通用限流规则按实际流量收紧
|
|
|
|
|
|
## 13.5 注意事项
|
|
|
|
|
|
- 示例规则阈值较高,不能直接作为生产值
|
|
|
- 处于反向代理后方时应正确配置真实 IP 头
|
|
|
|
|
|
# 第十四章 国密信创
|
|
|
|
|
|
## 14.1 功能说明
|
|
|
|
|
|
当前项目明确支持国密相关能力,已接入:
|
|
|
|
|
|
- SM2
|
|
|
- SM4
|
|
|
- MD5
|
|
|
|
|
|
其中认证链路默认已按国密模式适配。
|
|
|
|
|
|
## 14.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/CryptogramUtil.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Option/CryptogramOptions.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/App.json`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs`
|
|
|
|
|
|
## 14.3 使用方式
|
|
|
|
|
|
### 14.3.1 登录密码传输
|
|
|
|
|
|
前端密码可使用 SM2 加密传输,后端在 `VerifyPassword()` 中解密校验。
|
|
|
|
|
|
### 14.3.2 连接串加密
|
|
|
|
|
|
数据库连接串可通过配置开关启用加密读取。
|
|
|
|
|
|
### 14.3.3 通用加解密
|
|
|
|
|
|
业务如需统一加解密,可复用 `CryptogramUtil`。
|
|
|
|
|
|
## 14.4 开发建议
|
|
|
|
|
|
- 密钥统一配置,不要散落在代码中
|
|
|
- 新系统上线前应同步更新公私钥
|
|
|
- 如涉及等保、密评,应配套补充日志、访问控制、密钥管理制度
|
|
|
|
|
|
## 14.5 注意事项
|
|
|
|
|
|
- 修改公私钥后,前后端必须同步
|
|
|
- 历史数据如使用旧算法,需要评估平滑迁移策略
|
|
|
|
|
|
# 第十五章 邮件发送
|
|
|
|
|
|
## 15.1 功能说明
|
|
|
|
|
|
邮件发送能力由 `SysEmailService` 提供,当前基于 SMTP 实现。
|
|
|
|
|
|
## 15.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Message/SysEmailService.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Email.json`
|
|
|
|
|
|
## 15.3 配置说明
|
|
|
|
|
|
主配置节点:`Email`
|
|
|
|
|
|
重点配置项:
|
|
|
|
|
|
- `Host`
|
|
|
- `Port`
|
|
|
- `EnableSsl`
|
|
|
- `DefaultFromEmail`
|
|
|
- `DefaultToEmail`
|
|
|
- `UserName`
|
|
|
- `Password`
|
|
|
|
|
|
## 15.4 使用方式
|
|
|
|
|
|
通过 `SendEmail(content, title, toEmail)` 直接发送邮件。
|
|
|
|
|
|
## 15.5 开发建议
|
|
|
|
|
|
- 业务邮件内容优先结合模板服务渲染
|
|
|
- 告警邮件建议通过事件总线异步发送
|
|
|
|
|
|
## 15.6 注意事项
|
|
|
|
|
|
- 当前实现更适合基础通知与告警,不是完整营销邮件平台
|
|
|
- 大批量邮件场景应引入异步队列和发送状态管理
|
|
|
|
|
|
# 第十六章 短信发送
|
|
|
|
|
|
## 16.1 功能说明
|
|
|
|
|
|
当前短信能力支持:
|
|
|
|
|
|
- 阿里云短信
|
|
|
- 腾讯云短信
|
|
|
- 自定义短信 HTTP 接口
|
|
|
|
|
|
并支持验证码缓存与校验。
|
|
|
|
|
|
## 16.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Message/SysSmsService.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/SMS.json`
|
|
|
|
|
|
## 16.3 使用方式
|
|
|
|
|
|
### 16.3.1 验证码发送
|
|
|
|
|
|
通过 `SendSms()` 发送验证码类短信。
|
|
|
|
|
|
### 16.3.2 验证码校验
|
|
|
|
|
|
通过 `VerifyCode()` 校验缓存中的验证码。
|
|
|
|
|
|
### 16.3.3 模板短信
|
|
|
|
|
|
阿里云模板短信可通过 `AliyunSendSmsTemplate()` 发送。
|
|
|
|
|
|
## 16.4 开发建议
|
|
|
|
|
|
- 验证码短信应叠加限流与防刷
|
|
|
- 模板 ID、签名、过期时间统一在配置中维护
|
|
|
|
|
|
## 16.5 注意事项
|
|
|
|
|
|
- 自定义短信接口成功标识依赖配置项 `SuccessFlag`
|
|
|
- 自定义短信接口如果不规范,容易出现成功失败判断误差
|
|
|
|
|
|
# 第十七章 微信对接
|
|
|
|
|
|
## 17.1 功能说明
|
|
|
|
|
|
当前主项目内置的是微信公众号 / 小程序 / 微信支付相关能力。
|
|
|
|
|
|
## 17.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Wechat.json`
|
|
|
|
|
|
## 17.3 当前能力
|
|
|
|
|
|
- 公众号 OAuth2 授权 URL 生成
|
|
|
- 通过 code 获取 OpenId
|
|
|
- 微信用户入库
|
|
|
- OpenId 登录
|
|
|
- JSSDK 签名参数生成
|
|
|
- 模板消息查询、发送、删除
|
|
|
- 微信支付配置承载
|
|
|
|
|
|
## 17.4 开发建议
|
|
|
|
|
|
- C 端公众号、小程序统一复用现有服务
|
|
|
- 企业微信请走 `WorkWeixin` 插件,不混在 `SysWechatService` 中
|
|
|
|
|
|
## 17.5 注意事项
|
|
|
|
|
|
- 微信支付配置涉及证书、回调地址与密钥,生产环境应走安全配置管理
|
|
|
- OpenId 登录只适合明确的微信用户体系,不适合通用后台账号体系
|
|
|
|
|
|
# 第十八章 多租户 SAAS
|
|
|
|
|
|
## 18.1 功能说明
|
|
|
|
|
|
多租户是当前脚手架核心能力之一,支持:
|
|
|
|
|
|
- 同库租户隔离
|
|
|
- 独立库租户隔离
|
|
|
- 租户切换
|
|
|
- 租户初始化
|
|
|
- 租户菜单授权
|
|
|
- 租户管理员初始化
|
|
|
|
|
|
## 18.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs`
|
|
|
|
|
|
## 18.3 使用方式
|
|
|
|
|
|
### 18.3.1 隔离模式
|
|
|
|
|
|
- `TenantTypeEnum.Id`
|
|
|
- `TenantTypeEnum.Db`
|
|
|
|
|
|
### 18.3.2 租户连接切换
|
|
|
|
|
|
由 `SqlSugarRepository<T>` 在构造阶段自动判断。
|
|
|
|
|
|
### 18.3.3 租户初始化
|
|
|
|
|
|
新增租户后会自动初始化:
|
|
|
|
|
|
- 机构
|
|
|
- 默认角色
|
|
|
- 岗位
|
|
|
- 管理员账号
|
|
|
- 菜单授权
|
|
|
|
|
|
## 18.4 开发建议
|
|
|
|
|
|
- 所有业务表在建模初期就要决定是否租户隔离
|
|
|
- 涉及租户扩容、迁移、归档时,应基于当前连接模型扩展,不要重造租户访问层
|
|
|
|
|
|
## 18.5 注意事项
|
|
|
|
|
|
- 租户切换和登录租户不是同一个概念,需关注 Claim 与实体里的 `TenantId`
|
|
|
- 数据权限和租户过滤同时存在时,查询结果可能叠加收缩
|
|
|
|
|
|
# 第十九章 远程请求
|
|
|
|
|
|
## 19.1 功能说明
|
|
|
|
|
|
当前项目统一远程调用能力已经接入,推荐优先走声明式 HTTP。
|
|
|
|
|
|
## 19.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/Startup.cs`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/Service/IDingTalkApi.cs`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.WorkWeixin/Proxy/*`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.K3Cloud/Startup.cs`
|
|
|
|
|
|
## 19.3 使用方式
|
|
|
|
|
|
### 19.3.1 声明式 HTTP
|
|
|
|
|
|
适用于:
|
|
|
|
|
|
- DingTalk
|
|
|
- WorkWeixin
|
|
|
|
|
|
### 19.3.2 命名 HttpClient
|
|
|
|
|
|
适用于:
|
|
|
|
|
|
- K3Cloud
|
|
|
|
|
|
## 19.4 开发建议
|
|
|
|
|
|
- 新增三方对接优先使用声明式接口
|
|
|
- 将配置、DTO、代理、服务放在同一模块内
|
|
|
- 对外部接口返回结果统一包装
|
|
|
|
|
|
## 19.5 注意事项
|
|
|
|
|
|
- `WorkWeixin` 当前插件虽然提供了代理接口,但默认应用层未引用,启用前需补项目引用
|
|
|
- 自定义 `HttpClient` 不应在业务代码中到处散落
|
|
|
|
|
|
# 第二十章 消息队列
|
|
|
|
|
|
## 20.1 功能说明
|
|
|
|
|
|
当前项目的消息能力主要通过 EventBus 承载,已支持:
|
|
|
|
|
|
- 内存事件源
|
|
|
- Redis 事件源
|
|
|
- 失败重试
|
|
|
- 失败回调
|
|
|
- 事件监视器
|
|
|
|
|
|
## 20.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/EventBus/AppEventSubscriber.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/EventBus/RetryEventHandlerExecutor.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/EventBus/RabbitMQEventSourceStore.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/EventBus.json`
|
|
|
|
|
|
## 20.3 当前状态
|
|
|
|
|
|
- 内存事件总线可直接用
|
|
|
- Redis 事件源在缓存启用 Redis 时可自动接入
|
|
|
- RabbitMQ 存储器已有代码,但默认未在 `Startup` 中打开
|
|
|
|
|
|
## 20.4 使用方式
|
|
|
|
|
|
- 发布事件:通过 `IEventPublisher`
|
|
|
- 订阅事件:通过 `IEventSubscriber`
|
|
|
- 异常告警、登录事件、日志扩展都可以走事件化解耦
|
|
|
|
|
|
## 20.5 开发建议
|
|
|
|
|
|
- 适合将非主事务动作改为异步事件
|
|
|
- 业务事件命名应稳定,避免后期难以追踪
|
|
|
|
|
|
## 20.6 注意事项
|
|
|
|
|
|
- 当前更偏事件驱动底座,不是完整企业级 MQ 平台
|
|
|
- 需要严格投递确认、死信队列、消费组管理时,应在现有基础上继续封装
|
|
|
|
|
|
# 第二十一章 定时任务
|
|
|
|
|
|
## 21.1 功能说明
|
|
|
|
|
|
当前项目有两类时间相关能力:
|
|
|
|
|
|
- 框架级定时任务
|
|
|
- 业务级日程管理
|
|
|
|
|
|
## 21.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Job/DynamicJobCompiler.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Schedule/SysScheduleService.cs`
|
|
|
|
|
|
## 21.3 使用方式
|
|
|
|
|
|
### 21.3.1 框架级定时任务
|
|
|
|
|
|
通过 `AddSchedule(...)` 注册,支持:
|
|
|
|
|
|
- 持久化
|
|
|
- 监控
|
|
|
- 调度看板
|
|
|
- 动态作业编译
|
|
|
|
|
|
### 21.3.2 业务日程
|
|
|
|
|
|
通过 `SysScheduleService` 管理个人或业务日程。
|
|
|
|
|
|
## 21.4 开发建议
|
|
|
|
|
|
- 系统级同步、统计、清理任务走调度器
|
|
|
- 个人提醒、业务跟进走日程服务
|
|
|
|
|
|
## 21.5 注意事项
|
|
|
|
|
|
- 两类能力不要混用
|
|
|
- 动态作业代码需做好来源控制与安全约束
|
|
|
|
|
|
# 第二十二章 令牌 Token
|
|
|
|
|
|
## 22.1 功能说明
|
|
|
|
|
|
Token 体系由 `SysAuthService + JwtHandler` 统一控制,包含:
|
|
|
|
|
|
- AccessToken
|
|
|
- RefreshToken
|
|
|
- Token 黑名单
|
|
|
- 自动续期
|
|
|
|
|
|
## 22.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs`
|
|
|
|
|
|
## 22.3 使用方式
|
|
|
|
|
|
### 22.3.1 登录签发
|
|
|
|
|
|
`CreateToken()` 统一生成 AccessToken 与 RefreshToken。
|
|
|
|
|
|
### 22.3.2 自动续期
|
|
|
|
|
|
`JwtHandler` 在认证管线中自动处理。
|
|
|
|
|
|
### 22.3.3 退出失效
|
|
|
|
|
|
`Logout()` 将旧 Token 写入黑名单缓存。
|
|
|
|
|
|
## 22.4 开发建议
|
|
|
|
|
|
- Token 生命周期与业务安全等级匹配
|
|
|
- 统一在响应头传递 Token
|
|
|
|
|
|
## 22.5 注意事项
|
|
|
|
|
|
- 黑名单依赖缓存,单机模式下跨节点无共享
|
|
|
- 不建议业务层自行生成或解析 JWT
|
|
|
|
|
|
# 第二十三章 日志记录
|
|
|
|
|
|
## 23.1 功能说明
|
|
|
|
|
|
当前日志体系支持:
|
|
|
|
|
|
- 控制台日志
|
|
|
- 文件日志
|
|
|
- 数据库日志
|
|
|
- ES 日志
|
|
|
- 访问日志
|
|
|
- 操作日志
|
|
|
- 异常日志
|
|
|
- 差异日志
|
|
|
- 慢 SQL / 错误 SQL
|
|
|
|
|
|
## 23.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Logging/LoggingSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Logging/DatabaseLoggingWriter.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Logging/ElasticSearchLoggingWriter.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Log/*`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Logging.json`
|
|
|
|
|
|
## 23.3 使用方式
|
|
|
|
|
|
- 全局日志由框架自动接入
|
|
|
- 业务日志可通过系统日志服务查询
|
|
|
- SQL 日志由 SqlSugar AOP 自动挂接
|
|
|
|
|
|
## 23.4 开发建议
|
|
|
|
|
|
- 关键业务动作记录操作日志
|
|
|
- 重要数据变更考虑开启差异日志
|
|
|
- 批量处理任务避免全量打印大量明细日志
|
|
|
|
|
|
## 23.5 注意事项
|
|
|
|
|
|
- 全局监控日志开启会有性能成本
|
|
|
- ES 日志需确认存储生命周期与索引策略
|
|
|
|
|
|
# 第二十四章 代码生成
|
|
|
|
|
|
## 24.1 功能说明
|
|
|
|
|
|
代码生成是当前脚手架成熟度较高的能力,支持:
|
|
|
|
|
|
- 表导入
|
|
|
- 字段同步
|
|
|
- 代码预览
|
|
|
- 本地生成
|
|
|
- ZIP 打包
|
|
|
- 菜单按钮自动生成
|
|
|
- 前后端联动生成
|
|
|
|
|
|
## 24.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/CodeGenUtil.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/CodeGen.json`
|
|
|
|
|
|
## 24.3 使用方式
|
|
|
|
|
|
### 24.3.1 基础流程
|
|
|
|
|
|
1. 导入表结构
|
|
|
2. 编辑生成配置
|
|
|
3. 同步字段
|
|
|
4. 预览模板
|
|
|
5. 生成本地代码或 ZIP
|
|
|
|
|
|
### 24.3.2 生成范围
|
|
|
|
|
|
- 后端 Service / DTO
|
|
|
- 前端页面
|
|
|
- API 文件
|
|
|
- 菜单与按钮权限
|
|
|
|
|
|
## 24.4 开发建议
|
|
|
|
|
|
- 代码生成适合标准 CRUD
|
|
|
- 复杂业务流程不要强压模板层
|
|
|
- 生成后的代码应进入业务应用层继续手工收敛
|
|
|
|
|
|
## 24.5 注意事项
|
|
|
|
|
|
- 表字段变更后要及时同步生成配置
|
|
|
- 命名空间、页面路径、菜单路径要在生成前确认清楚
|
|
|
|
|
|
# 第二十五章 可视化大屏
|
|
|
|
|
|
## 25.1 功能说明
|
|
|
|
|
|
当前大屏能力由 `GoView` 插件提供,已经具备基础后端支撑。
|
|
|
|
|
|
## 25.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.GoView/Startup.cs`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.GoView/Service/GoViewPro/GoViewProService.cs`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.GoView/Util/GoViewResultProvider.cs`
|
|
|
|
|
|
## 25.3 当前能力
|
|
|
|
|
|
- 大屏项目管理
|
|
|
- 大屏内容保存
|
|
|
- 发布状态管理
|
|
|
- 预览图上传
|
|
|
- 背景图上传
|
|
|
- 独立返回模型
|
|
|
|
|
|
## 25.4 开发建议
|
|
|
|
|
|
- 大屏数据聚合逻辑放业务服务
|
|
|
- 大屏插件负责项目管理和内容持久化
|
|
|
- 生产、设备、能源、质量等指标查询建议由独立接口层聚合输出
|
|
|
|
|
|
## 25.5 注意事项
|
|
|
|
|
|
- 当前插件默认已引用,可直接启用
|
|
|
- 图片数据目前可直接保存在插件实体中,后续如需统一对象存储,可再向 `SysFileService` 收敛
|
|
|
|
|
|
# 第二十六章 OpenAPI
|
|
|
|
|
|
## 26.1 功能说明
|
|
|
|
|
|
当前项目的 OpenAPI 包含两部分:
|
|
|
|
|
|
- 内部接口文档
|
|
|
- 对外开放接口
|
|
|
|
|
|
## 26.2 关键文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Swagger.json`
|
|
|
- `Admin.NET/Admin.NET.Application/OpenApi/DemoOpenApi.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/OpenAccess/SysOpenAccessService.cs`
|
|
|
|
|
|
## 26.3 当前能力
|
|
|
|
|
|
### 26.3.1 内部接口文档
|
|
|
|
|
|
- Swagger
|
|
|
- Scalar
|
|
|
- 接口分组
|
|
|
- Swagger 登录
|
|
|
|
|
|
### 26.3.2 对外开放接口
|
|
|
|
|
|
- AccessKey / AccessSecret 管理
|
|
|
- HMAC-SHA256 签名
|
|
|
- 时间戳校验
|
|
|
- nonce 防重放
|
|
|
- 认证成功后 Claim 注入
|
|
|
|
|
|
## 26.4 使用方式
|
|
|
|
|
|
### 26.4.1 内部接口
|
|
|
|
|
|
通过 Swagger / Scalar 调试和查看文档。
|
|
|
|
|
|
### 26.4.2 对外接口
|
|
|
|
|
|
通过 Signature 认证方案暴露接口。
|
|
|
|
|
|
示例接口:`DemoOpenApi`
|
|
|
|
|
|
## 26.5 开发建议
|
|
|
|
|
|
- 对外系统接口使用独立开放身份
|
|
|
- 结合限流、日志、租户绑定一起设计
|
|
|
- 外部系统不要直接使用后台 JWT
|
|
|
|
|
|
## 26.6 注意事项
|
|
|
|
|
|
- 开放接口默认也要考虑多租户与数据权限问题
|
|
|
- 签名算法、时间偏差、nonce 过期时间应与对接方提前约定
|
|
|
|
|
|
---
|
|
|
|
|
|
## 附录一:常用配置清单
|
|
|
|
|
|
当前后端高频配置文件位于 `Admin.NET/Admin.NET.Application/Configuration/`:
|
|
|
|
|
|
- `App.json`
|
|
|
- `Database.json`
|
|
|
- `Cache.json`
|
|
|
- `Upload.json`
|
|
|
- `Email.json`
|
|
|
- `SMS.json`
|
|
|
- `Wechat.json`
|
|
|
- `OAuth.json`
|
|
|
- `EventBus.json`
|
|
|
- `Logging.json`
|
|
|
- `CodeGen.json`
|
|
|
- `Swagger.json`
|
|
|
- `Limit.json`
|
|
|
|
|
|
## 附录二:推荐二开约束
|
|
|
|
|
|
### A. 分层约束
|
|
|
|
|
|
- 平台基础设施放 `Admin.NET.Core`
|
|
|
- 业务应用服务放应用层或插件层
|
|
|
- 第三方集成优先插件化
|
|
|
|
|
|
### B. 复用约束
|
|
|
|
|
|
优先复用:
|
|
|
|
|
|
- `SqlSugarRepository<T>`
|
|
|
- `SysCacheService`
|
|
|
- `SysAuthService`
|
|
|
- `SysTenantService`
|
|
|
- `SysFileService`
|
|
|
- `SysTemplateService`
|
|
|
- `AdminResultProvider`
|
|
|
|
|
|
### C. 安全约束
|
|
|
|
|
|
- 不硬编码连接串、密钥、账号、审批规则
|
|
|
- 不直接信任请求输入的排序、过滤、路径、文件类型
|
|
|
- 对开放接口、短信、登录、上传统一加限流与日志
|
|
|
|
|
|
### D. 可配置约束
|
|
|
|
|
|
- 状态流转、审批、阈值、公式优先配置化
|
|
|
- 多变规则优先落表、字典或 JSON 规则,而不是堆 if-else
|
|
|
|
|
|
## 附录三:当前脚手架能力结论
|
|
|
|
|
|
### 已形成较完整后端底座的能力
|
|
|
|
|
|
- 框架启动装配
|
|
|
- 数据库与多租户
|
|
|
- 统一鉴权
|
|
|
- Token
|
|
|
- 缓存
|
|
|
- 文件
|
|
|
- 模板
|
|
|
- 短信
|
|
|
- 邮件
|
|
|
- 日志
|
|
|
- 限流
|
|
|
- 代码生成
|
|
|
- 可视化大屏
|
|
|
- OpenAPI
|
|
|
|
|
|
### 已有底座但通常还需继续业务化封装的能力
|
|
|
|
|
|
- 图片压缩
|
|
|
- 服务端打印编排
|
|
|
- 企业级消息队列治理
|
|
|
- 复杂设备接入编排
|
|
|
- 复杂第三方集成编排
|
|
|
|
|
|
## 附录四:后续建议
|
|
|
|
|
|
如果你准备继续把这套脚手架用于制造业项目,建议下一步按业务域继续拆文档:
|
|
|
|
|
|
1. `MES` 生产执行模块设计指南
|
|
|
2. `WMS` 库存与条码模块设计指南
|
|
|
3. `QMS` 质量与检验模块设计指南
|
|
|
4. `DMS` 设备与点检模块设计指南
|
|
|
5. `EMS` 能源采集与统计模块设计指南
|
|
|
|
|
|
这样可以把“脚手架手册”和“业务域手册”彻底分开,后续维护成本更低。
|
|
|
|
|
|
## 附录五:26章深度补充
|
|
|
|
|
|
### 1. 框架简介补充
|
|
|
|
|
|
#### 1.1 统一技术路线
|
|
|
|
|
|
当前脚手架不是传统意义上“只给一套目录结构”的空框架,而是已经把平台常见基础能力做了统一门面和统一入口:
|
|
|
|
|
|
- 数据库统一入口:`SqlSugarSetup` + `SqlSugarRepository<T>`
|
|
|
- 缓存统一入口:`SysCacheService`
|
|
|
- 鉴权统一入口:`SysAuthService` + `JwtHandler`
|
|
|
- 租户统一入口:`SysTenantService`
|
|
|
- 文件统一入口:`SysFileService`
|
|
|
- 模板统一入口:`SysTemplateService`
|
|
|
- 日志统一入口:`LoggingSetup` + `SysLog*Service`
|
|
|
- OpenAPI 统一入口:`SysOpenAccessService`
|
|
|
|
|
|
实际意义是:后续二开时,不应该把这些能力再拆成第二套公共层,否则维护成本会快速失控。
|
|
|
|
|
|
#### 1.2 与传统 MVC 项目的差异
|
|
|
|
|
|
和常见 ASP.NET Core 三层结构相比,本项目有几个关键差异:
|
|
|
|
|
|
- 很多服务直接实现 `IDynamicApiController`,无需单独建 Controller
|
|
|
- 返回值默认统一包装,不建议业务方法自己构造自定义响应对象
|
|
|
- 数据权限、租户过滤、软删除过滤由 ORM 全局挂载,不建议每个查询手写
|
|
|
- 配置通过 Options 绑定,不建议业务层直接到处 `GetSection("xxx")`
|
|
|
- 插件不是样例性质,而是正式扩展模式
|
|
|
|
|
|
#### 1.3 适合的项目类型
|
|
|
|
|
|
这套后端脚手架比较适合:
|
|
|
|
|
|
- 多组织、多角色、多菜单权限的后台系统
|
|
|
- 存在租户隔离诉求的 SaaS 系统
|
|
|
- 需要代码生成加速标准 CRUD 的管理系统
|
|
|
- 需要文件、模板、消息、日志、调度等平台能力的中大型业务系统
|
|
|
- 制造业场景下需要长期演进的平台化项目
|
|
|
|
|
|
不太适合:
|
|
|
|
|
|
- 极致轻量、极少模块、无权限体系的简单单页接口服务
|
|
|
- 强调极致低延迟的纯网关型服务
|
|
|
- 完全事件驱动且几乎无后台管理页面的系统
|
|
|
|
|
|
### 2. 开发流程补充
|
|
|
|
|
|
#### 2.1 建议的二开顺序
|
|
|
|
|
|
如果你要在当前脚手架上开发一个新业务模块,建议按这个顺序做:
|
|
|
|
|
|
1. 先确认该模块是否需要租户隔离
|
|
|
2. 再确认该模块是否存在组织数据权限
|
|
|
3. 再确认是否要纳入代码生成
|
|
|
4. 再定义实体、枚举、字典、状态机和规则配置
|
|
|
5. 最后再写服务、接口、导入导出和联动消息
|
|
|
|
|
|
这样做的原因是:一旦实体基类、权限边界、租户模型选错,后面返工成本很高。
|
|
|
|
|
|
#### 2.2 一个标准模块的最小落地清单
|
|
|
|
|
|
一个标准后端业务模块建议至少包含:
|
|
|
|
|
|
- 实体类
|
|
|
- 输入 DTO / 输出 DTO
|
|
|
- Service
|
|
|
- 必要枚举
|
|
|
- 必要字典配置
|
|
|
- 菜单权限
|
|
|
- 日志埋点
|
|
|
- 导入导出能力
|
|
|
- 单元测试或集成验证清单
|
|
|
|
|
|
#### 2.3 制造业项目的额外建议
|
|
|
|
|
|
对于 `MES/WMS/QMS/DMS/EMS` 场景,建议在开发流程里固定加上三项:
|
|
|
|
|
|
- 状态定义表或字典表设计
|
|
|
- 设备、工单、批次、库位等主数据边界确认
|
|
|
- 追溯字段和操作日志字段确认
|
|
|
|
|
|
原因是这些模块后期最容易因为“状态硬编码”和“追溯字段缺失”导致无法扩展。
|
|
|
|
|
|
### 3. 数据库配置补充
|
|
|
|
|
|
#### 3.1 `SqlSugarSetup` 的实际职责
|
|
|
|
|
|
`SqlSugarSetup` 不只是“注册 ORM”,它实际上承担了数据库基础设施的大部分核心动作:
|
|
|
|
|
|
- 注册雪花 ID
|
|
|
- 处理多数据库连接配置
|
|
|
- 初始化 `SqlSugarScope`
|
|
|
- 为每个连接挂 AOP
|
|
|
- 统一执行审计字段自动赋值
|
|
|
- 统一处理软删过滤
|
|
|
- 统一处理租户过滤
|
|
|
- 统一处理数据权限过滤
|
|
|
- 统一处理 SQL 错误与超时日志
|
|
|
- 初始化库、表、视图、种子
|
|
|
|
|
|
换句话说,数据库行为的很多“默认规则”不是散落在业务里,而是集中在这里。
|
|
|
|
|
|
#### 3.2 库表初始化建议
|
|
|
|
|
|
当前脚手架支持自动建表、自动建视图、自动种子。建议按环境控制:
|
|
|
|
|
|
- 本地开发环境:可开启表和种子初始化
|
|
|
- 测试环境:仅在结构变更时短期开启
|
|
|
- 生产环境:默认关闭,改用正式发布脚本
|
|
|
|
|
|
如果长期在生产环境开启:
|
|
|
|
|
|
- 可能因误改实体导致结构被自动同步
|
|
|
- 可能在高并发启动时造成视图/表锁问题
|
|
|
- 可能因种子更新影响线上数据
|
|
|
|
|
|
#### 3.3 数据库类型与信创兼容
|
|
|
|
|
|
代码已经兼容多种数据库类型,配置层面对国产数据库也预留了能力,例如:
|
|
|
|
|
|
- PostgreSQL
|
|
|
- Oracle
|
|
|
- SqlServer
|
|
|
- MySql
|
|
|
- Sqlite
|
|
|
- Kdbndp
|
|
|
- Dm
|
|
|
|
|
|
如果要真正落地信创,需要额外补以下验证:
|
|
|
|
|
|
- 字段类型映射验证
|
|
|
- 视图初始化语法兼容验证
|
|
|
- 差异日志和分页 SQL 验证
|
|
|
- 索引策略验证
|
|
|
- 连接串与驱动兼容验证
|
|
|
|
|
|
### 4. 实体基类补充
|
|
|
|
|
|
#### 4.1 为什么必须优先选对基类
|
|
|
|
|
|
本项目的实体基类不是简单字段复用,而是直接参与下面几类行为:
|
|
|
|
|
|
- 审计字段自动赋值
|
|
|
- 逻辑删除过滤
|
|
|
- 租户过滤
|
|
|
- 机构过滤
|
|
|
- 所属人过滤
|
|
|
|
|
|
如果基类选错,会出现下面几类典型问题:
|
|
|
|
|
|
- 业务数据没有自动带上 `TenantId`
|
|
|
- 软删记录被误查出来
|
|
|
- 组织数据权限不生效
|
|
|
- 审计字段为空
|
|
|
|
|
|
#### 4.2 建模建议
|
|
|
|
|
|
针对制造业系统,建议按对象类型选择基类:
|
|
|
|
|
|
- 平台基础表:`EntityBase` / `EntityBaseDel`
|
|
|
- 组织敏感业务表:`EntityBaseOrg` / `EntityBaseOrgDel`
|
|
|
- 租户业务主表:`EntityBaseTenant` / `EntityBaseTenantDel`
|
|
|
- 既要租户又要机构:`EntityBaseTenantOrg` / `EntityBaseTenantOrgDel`
|
|
|
|
|
|
例如:
|
|
|
|
|
|
- 工单、批次、质检单、出入库单:通常建议走租户业务基类
|
|
|
- 组织维度统计表、岗位权限表:通常建议走带机构基类
|
|
|
|
|
|
#### 4.3 实体层扩展原则
|
|
|
|
|
|
业务实体扩展时建议:
|
|
|
|
|
|
- 状态字段用枚举 + 字典组合,不只用裸字符串
|
|
|
- 金额、数量、重量统一考虑精度
|
|
|
- 追溯字段如批次、工序、设备、库位要在设计初期补齐
|
|
|
|
|
|
### 5. 缓存管理补充
|
|
|
|
|
|
#### 5.1 `SysCacheService` 的实际定位
|
|
|
|
|
|
`SysCacheService` 不是简单包装 Redis,而是平台缓存访问门面。它封装的价值包括:
|
|
|
|
|
|
- 屏蔽 Memory / Redis 差异
|
|
|
- 统一缓存前缀
|
|
|
- 统一锁模型
|
|
|
- 统一 Hash 操作
|
|
|
- 统一缓存穿透防护式读取
|
|
|
|
|
|
因此业务代码应依赖这个门面,而不是依赖具体缓存实现。
|
|
|
|
|
|
#### 5.2 典型缓存键分类建议
|
|
|
|
|
|
建议按以下结构设计缓存 Key:
|
|
|
|
|
|
- 系统参数类:`config:*`
|
|
|
- 权限类:`menu:*`、`role:*`、`button:*`
|
|
|
- 用户会话类:`token:*`、`blacklist:*`
|
|
|
- 防重复类:`nonce:*`、`lock:*`
|
|
|
- 业务快照类:`biz:模块:主键`
|
|
|
|
|
|
#### 5.3 多节点场景注意点
|
|
|
|
|
|
以下能力如果部署为多节点,强烈建议切到 Redis:
|
|
|
|
|
|
- Token 黑名单
|
|
|
- 登录失败次数
|
|
|
- 开放接口 nonce
|
|
|
- SignalR Backplane
|
|
|
- 任务状态共享
|
|
|
- 设备或消息中心的实时状态缓存
|
|
|
|
|
|
#### 5.4 不推荐的做法
|
|
|
|
|
|
- 在业务代码中使用 `Cache.Default` 作为默认缓存入口
|
|
|
- 手动拼接不规范缓存键
|
|
|
- 不设置过期时间就缓存高频波动业务数据
|
|
|
- 用缓存替代正式主数据存储
|
|
|
|
|
|
### 6. 导入导出补充
|
|
|
|
|
|
#### 6.1 导入设计建议
|
|
|
|
|
|
对于导入功能,建议始终分三层:
|
|
|
|
|
|
1. 模板层:列头、格式、必填项
|
|
|
2. 解析层:Excel 到 DTO
|
|
|
3. 入库层:DTO 到实体,再做业务校验
|
|
|
|
|
|
不要把所有校验都写进 Excel 解析回调里,否则后续复用性很差。
|
|
|
|
|
|
#### 6.2 导入常见错误分类
|
|
|
|
|
|
建议把导入错误区分为:
|
|
|
|
|
|
- 模板错误
|
|
|
- 格式错误
|
|
|
- 字典值错误
|
|
|
- 主数据不存在
|
|
|
- 业务规则冲突
|
|
|
- 重复数据
|
|
|
|
|
|
当前脚手架已经能较好承载:
|
|
|
|
|
|
- 模板错误
|
|
|
- 行级字段错误
|
|
|
- 错误信息回写
|
|
|
|
|
|
后续可继续扩展:
|
|
|
|
|
|
- 唯一性校验明细
|
|
|
- 错误分级
|
|
|
- 导入任务批次号
|
|
|
|
|
|
#### 6.3 导出设计建议
|
|
|
|
|
|
导出时建议不要直接导实体,优先导专用输出 DTO,原因是:
|
|
|
|
|
|
- 可控制字段范围
|
|
|
- 可控制字典值转换
|
|
|
- 可规避敏感字段误导出
|
|
|
- 可避免导航属性或多余字段污染
|
|
|
|
|
|
### 7. 上传下载补充
|
|
|
|
|
|
#### 7.1 文件体系的角色分工
|
|
|
|
|
|
当前文件体系可理解为三层:
|
|
|
|
|
|
- 文件元数据层:`SysFile`
|
|
|
- 文件服务层:`SysFileService`
|
|
|
- 存储适配层:`ICustomFileProvider` 及其实现
|
|
|
|
|
|
这样设计的好处是:业务只关心文件逻辑,不关心底层到底是本地、OSS 还是 SSH。
|
|
|
|
|
|
#### 7.2 `SysFileProviderService` 的意义
|
|
|
|
|
|
当前脚手架除了统一上传服务,还增加了 `SysFileProviderService` 作为多存储提供者配置中心,具备:
|
|
|
|
|
|
- 提供者列表管理
|
|
|
- 默认提供者切换
|
|
|
- 提供者缓存
|
|
|
- 存储桶管理
|
|
|
- 配置合法性校验
|
|
|
|
|
|
这说明文件体系已经开始朝“平台级文件中心”演进,不只是单纯上传接口。
|
|
|
|
|
|
#### 7.3 制造业项目常见文件场景
|
|
|
|
|
|
你们后续很可能会遇到:
|
|
|
|
|
|
- 质检附件
|
|
|
- 设备巡检照片
|
|
|
- 不合格品图片
|
|
|
- 工艺文件
|
|
|
- 作业指导书
|
|
|
- 标签或单据模板
|
|
|
- 批量导入文件
|
|
|
|
|
|
这些都建议统一走 `SysFileService`,不要每个模块各自存磁盘路径。
|
|
|
|
|
|
### 8. 模板打印补充
|
|
|
|
|
|
#### 8.1 `SysPrintService` 与 `SysTemplateService` 的差异
|
|
|
|
|
|
二者不要混淆:
|
|
|
|
|
|
- `SysPrintService` 更偏“打印模板对象管理”
|
|
|
- `SysTemplateService` 更偏“通用文本/内容模板渲染”
|
|
|
|
|
|
如果做标签打印、工票打印、发料单打印,通常是:
|
|
|
|
|
|
1. `SysPrintService` 存模板定义
|
|
|
2. 业务服务组装打印数据
|
|
|
3. `SysTemplateService` 负责动态渲染
|
|
|
4. 最终输出给前端打印控件或后端文件服务
|
|
|
|
|
|
#### 8.2 复杂打印建议
|
|
|
|
|
|
如果后续你们要支持:
|
|
|
|
|
|
- 标签模板版本管理
|
|
|
- 多纸张尺寸
|
|
|
- 多打印机路由
|
|
|
- 打印失败重试
|
|
|
- 批量套打任务
|
|
|
|
|
|
建议在现有模板能力上单独再封装一个 `PrintModule`,而不是把所有逻辑堆在 `SysPrintService`。
|
|
|
|
|
|
### 9. 统一认证补充
|
|
|
|
|
|
#### 9.1 登录链路
|
|
|
|
|
|
一个标准后台登录请求大致经过:
|
|
|
|
|
|
1. 验证码校验
|
|
|
2. 登录失败次数校验
|
|
|
3. 用户与租户获取
|
|
|
4. 密码或域登录校验
|
|
|
5. 生成 AccessToken / RefreshToken
|
|
|
6. 设置响应头
|
|
|
7. 更新用户最后登录信息
|
|
|
8. 发布登录事件
|
|
|
|
|
|
这条链路已经基本完整,后续新增登录方式时应尽量保持这一套主线不变。
|
|
|
|
|
|
#### 9.2 `JwtHandler` 的价值
|
|
|
|
|
|
`JwtHandler` 不只是鉴权,还承担:
|
|
|
|
|
|
- 黑名单校验
|
|
|
- 自动刷新 Token
|
|
|
- 路由按钮权限判断
|
|
|
|
|
|
这意味着权限不是“登录成功就算结束”,而是在每次请求阶段继续判定。
|
|
|
|
|
|
#### 9.3 开放接口认证建议
|
|
|
|
|
|
开放接口建议固定遵循:
|
|
|
|
|
|
- 给每个外部系统单独发一组 `accessKey/accessSecret`
|
|
|
- 绑定具体用户和租户
|
|
|
- 配套限流
|
|
|
- 配套日志
|
|
|
- 配套 nonce 防重放
|
|
|
|
|
|
不要多个系统共用一套开放凭据,否则审计和追责会非常麻烦。
|
|
|
|
|
|
### 10. 数据权限补充
|
|
|
|
|
|
#### 10.1 过滤器真正的执行位置
|
|
|
|
|
|
当前数据权限不是在 Controller 或 Service 里做,而是在 SqlSugar 查询执行前统一挂入。
|
|
|
|
|
|
所以出现权限问题时,排查顺序建议是:
|
|
|
|
|
|
1. 是否继承了正确实体基类
|
|
|
2. 当前登录用户角色数据范围是什么
|
|
|
3. 当前请求头 TenantId 是什么
|
|
|
4. 当前 Claim TenantId / UserId / OrgId 是什么
|
|
|
5. 查询是否调用了 `ClearFilter()`
|
|
|
|
|
|
#### 10.2 常见误区
|
|
|
|
|
|
- 以为查不到数据是 SQL 有问题,实际上是过滤器生效
|
|
|
- 以为租户过滤和机构过滤只能选一个,实际上是会叠加
|
|
|
- 以为超管一定无过滤,实际上软删过滤可配置是否忽略
|
|
|
|
|
|
### 11. 即时通讯补充
|
|
|
|
|
|
#### 11.1 在线用户的实际用途
|
|
|
|
|
|
SignalR 当前不只是聊天能力,更适合做:
|
|
|
|
|
|
- 在线状态监控
|
|
|
- 实时公告
|
|
|
- 审批/待办提醒
|
|
|
- 设备告警推送
|
|
|
- 长流程业务节点反馈
|
|
|
|
|
|
#### 11.2 业务使用建议
|
|
|
|
|
|
即时通讯适合作为“通知层”,不适合作为“最终状态层”。
|
|
|
|
|
|
例如:
|
|
|
|
|
|
- 设备告警消息可以实时推送
|
|
|
- 但设备告警状态仍应落数据库
|
|
|
|
|
|
这样即使连接中断,也不会丢失关键业务状态。
|
|
|
|
|
|
### 12. 图片压缩补充
|
|
|
|
|
|
#### 12.1 为什么当前只能说“有底座”
|
|
|
|
|
|
因为当前看到的是:
|
|
|
|
|
|
- 注册了 ImageSharp
|
|
|
- 启用了 ImageSharp 中间件
|
|
|
|
|
|
但没有看到在 `SysFileService` 中统一定义:
|
|
|
|
|
|
- 压缩比例
|
|
|
- 是否生成缩略图
|
|
|
- 是否保留原图
|
|
|
- 图片质量参数
|
|
|
- 不同业务目录的不同策略
|
|
|
|
|
|
所以当前不能把它描述成“完整图片压缩模块”。
|
|
|
|
|
|
#### 12.2 建议的扩展方向
|
|
|
|
|
|
后续如果你要落地这一章,建议新增:
|
|
|
|
|
|
- 图片处理配置表或配置项
|
|
|
- 上传后处理管线
|
|
|
- 缩略图命名规范
|
|
|
- 原图保留策略
|
|
|
- 图像水印策略
|
|
|
|
|
|
### 13. 接口限流补充
|
|
|
|
|
|
#### 13.1 限流落点建议
|
|
|
|
|
|
建议把限流对象分成三类:
|
|
|
|
|
|
- 后台用户接口
|
|
|
- 开放接口
|
|
|
- 高风险接口
|
|
|
|
|
|
高风险接口包括:
|
|
|
|
|
|
- 登录
|
|
|
- 获取验证码
|
|
|
- 短信发送
|
|
|
- 文件上传
|
|
|
- 开放接口签名入口
|
|
|
- 对外数据上报入口
|
|
|
|
|
|
#### 13.2 与网关限流的关系
|
|
|
|
|
|
如果后续前面还有网关或 API 管理层:
|
|
|
|
|
|
- 网关负责粗粒度限流
|
|
|
- 后端负责业务粒度限流
|
|
|
|
|
|
不要完全依赖网关,也不要在后端做得过重导致配置难维护。
|
|
|
|
|
|
### 14. 国密信创补充
|
|
|
|
|
|
#### 14.1 当前国密链路已落地的点
|
|
|
|
|
|
从代码看,当前国密并非只停留在工具类:
|
|
|
|
|
|
- 登录密码传输已在认证服务中落地
|
|
|
- 连接串加密能力已在数据库配置中预留
|
|
|
- `App.json` 已有默认 `CryptoType`
|
|
|
- `CryptogramUtil` 已覆盖多个算法
|
|
|
|
|
|
这说明国密能力已经融入主链路,不是单独的实验性工具。
|
|
|
|
|
|
#### 14.2 后续信创项目建议
|
|
|
|
|
|
若用于正式信创项目,建议补齐:
|
|
|
|
|
|
- 密钥轮换方案
|
|
|
- 证书管理方案
|
|
|
- 加密失败日志与告警
|
|
|
- 国产数据库性能验证报告
|
|
|
- 国产服务器部署基线
|
|
|
|
|
|
### 15. 邮件发送补充
|
|
|
|
|
|
#### 15.1 邮件能力的典型用法
|
|
|
|
|
|
当前邮件服务适合做:
|
|
|
|
|
|
- 系统异常告警
|
|
|
- 审批提醒
|
|
|
- 定时报表发送
|
|
|
- 注册或找回相关通知
|
|
|
|
|
|
不适合直接拿来做:
|
|
|
|
|
|
- 大规模营销邮件
|
|
|
- 邮件追踪统计平台
|
|
|
- 多模板 A/B 测试平台
|
|
|
|
|
|
#### 15.2 与模板服务联动
|
|
|
|
|
|
比较推荐的方式是:
|
|
|
|
|
|
1. 业务数据组装
|
|
|
2. 调 `SysTemplateService.RenderByCode()`
|
|
|
3. 调 `SysEmailService.SendEmail()`
|
|
|
|
|
|
这样可以把文案与逻辑分开维护。
|
|
|
|
|
|
### 16. 短信发送补充
|
|
|
|
|
|
#### 16.1 验证码链路建议
|
|
|
|
|
|
当前验证码短信功能具备基本闭环,但生产建议再加:
|
|
|
|
|
|
- 发送频率限制
|
|
|
- 每日发送上限
|
|
|
- 图形验证码前置
|
|
|
- 号码黑名单
|
|
|
- 渠道异常告警
|
|
|
|
|
|
#### 16.2 多短信通道建议
|
|
|
|
|
|
当前已支持阿里、腾讯、自定义接口。后续如果要做主备通道,建议增加:
|
|
|
|
|
|
- 通道优先级
|
|
|
- 故障切换策略
|
|
|
- 通道发送日志
|
|
|
- 成本统计
|
|
|
|
|
|
### 17. 微信对接补充
|
|
|
|
|
|
#### 17.1 公众号、小程序、企业微信要分层理解
|
|
|
|
|
|
当前代码中实际是三套概念:
|
|
|
|
|
|
- `SysWechatService`:公众号 / 小程序用户能力
|
|
|
- `SysWechatPayService`:微信支付能力
|
|
|
- `WorkWeixin` 插件:企业微信能力
|
|
|
|
|
|
这三者不要在文档和设计里混为一谈。
|
|
|
|
|
|
#### 17.2 微信支付现有能力
|
|
|
|
|
|
`SysWechatPayService` 当前已经具备:
|
|
|
|
|
|
- JSAPI 下单
|
|
|
- Native 下单
|
|
|
- 服务商模式下单
|
|
|
- 本地支付单查询
|
|
|
- 微信侧支付单查询
|
|
|
- 退款申请
|
|
|
- 退款查询
|
|
|
- 支付回调
|
|
|
- 退款回调
|
|
|
|
|
|
这说明本章不仅有“微信用户对接”,其实还覆盖了支付链路。
|
|
|
|
|
|
### 18. 多租户 SAAS 补充
|
|
|
|
|
|
#### 18.1 租户新增后的默认初始化内容
|
|
|
|
|
|
当前新增租户后会自动初始化:
|
|
|
|
|
|
- 机构
|
|
|
- 默认角色
|
|
|
- 岗位
|
|
|
- 管理员账号
|
|
|
- 菜单授权
|
|
|
|
|
|
这套初始化逻辑对 SaaS 项目非常关键,因为它保证租户开通后能直接登录和使用,而不需要人工一步步初始化基础权限。
|
|
|
|
|
|
#### 18.2 租户库模式的关键风险点
|
|
|
|
|
|
如果选择独立库隔离,需要额外关注:
|
|
|
|
|
|
- 租户连接串安全
|
|
|
- 租户库建库耗时
|
|
|
- 多租户连接池数量
|
|
|
- 租户迁移与归档
|
|
|
- 库级备份恢复策略
|
|
|
|
|
|
### 19. 远程请求补充
|
|
|
|
|
|
#### 19.1 当前项目里的三类对外集成方式
|
|
|
|
|
|
可以把现有集成方式分成三类:
|
|
|
|
|
|
- Furion 声明式 HTTP:如 DingTalk、WorkWeixin
|
|
|
- 命名 `HttpClient`:如 K3Cloud
|
|
|
- 插件式集成服务:如 DingTalkService、GoView、ReZero
|
|
|
|
|
|
#### 19.2 插件能力概览
|
|
|
|
|
|
- `DingTalk`:已默认引用,可直接做钉钉接口和审批流程对接
|
|
|
- `WorkWeixin`:已提供代理接口与配置类,但默认应用层未引用
|
|
|
- `K3Cloud`:已提供配置与命名客户端,适合 ERP 集成入口
|
|
|
- `ReZero`:提供超级 API 能力,并通过 `SuperApiAop` 复用 JWT 校验和日志链路
|
|
|
|
|
|
#### 19.3 集成规范建议
|
|
|
|
|
|
外部系统集成时建议统一做到:
|
|
|
|
|
|
- 配置化
|
|
|
- DTO 化
|
|
|
- 结果统一封装
|
|
|
- 错误日志统一记录
|
|
|
- 与业务逻辑解耦
|
|
|
|
|
|
### 20. 消息队列补充
|
|
|
|
|
|
#### 20.1 事件总线和传统 MQ 的边界
|
|
|
|
|
|
当前脚手架更准确的说法是“具备事件驱动能力”,而不是已经完整搭好企业 MQ 平台。
|
|
|
|
|
|
因为它已具备:
|
|
|
|
|
|
- 发布订阅
|
|
|
- 重试
|
|
|
- fallback
|
|
|
- Redis 事件源
|
|
|
|
|
|
但未完整体现:
|
|
|
|
|
|
- 可视化消费组管理
|
|
|
- 死信队列治理
|
|
|
- 顺序消费控制
|
|
|
- 分区消费治理
|
|
|
- 大规模消息堆积治理
|
|
|
|
|
|
#### 20.2 适合接入的业务场景
|
|
|
|
|
|
适合:
|
|
|
|
|
|
- 登录事件
|
|
|
- 异常告警
|
|
|
- 审批通知
|
|
|
- 第三方异步同步
|
|
|
- 文件处理后事件
|
|
|
|
|
|
不建议一开始就用它承载超大规模设备遥测主链路。
|
|
|
|
|
|
### 21. 定时任务补充
|
|
|
|
|
|
#### 21.1 当前任务体系的两条主线
|
|
|
|
|
|
很多项目会把“任务调度”和“业务日程”写在一起,但当前脚手架其实已经分清楚了:
|
|
|
|
|
|
- 调度器:系统级后台作业
|
|
|
- 日程服务:用户或业务日程数据
|
|
|
|
|
|
这个区分是对的,后续扩展时要保持。
|
|
|
|
|
|
#### 21.2 制造业场景适合的调度任务
|
|
|
|
|
|
常见适合放入调度器的任务:
|
|
|
|
|
|
- 班次统计汇总
|
|
|
- 设备状态同步
|
|
|
- 库存快照生成
|
|
|
- 质检逾期预警
|
|
|
- 日报周报生成
|
|
|
- ERP / MES / WMS 数据对账
|
|
|
|
|
|
### 22. 令牌 Token 补充
|
|
|
|
|
|
#### 22.1 Token 相关默认行为
|
|
|
|
|
|
当前默认行为包括:
|
|
|
|
|
|
- 登录签发 AccessToken 和 RefreshToken
|
|
|
- 在响应头回传
|
|
|
- 鉴权时做黑名单校验
|
|
|
- 在需要时自动续期
|
|
|
- 退出时写入黑名单
|
|
|
|
|
|
这意味着前后端配合时,响应头 Token 处理规则必须稳定。
|
|
|
|
|
|
#### 22.2 高安全项目建议
|
|
|
|
|
|
如果后续安全要求更高,建议再加:
|
|
|
|
|
|
- 设备指纹
|
|
|
- 登录地异常校验
|
|
|
- 多端登录策略配置
|
|
|
- RefreshToken 单独存储和吊销策略
|
|
|
- Token 审计日志
|
|
|
|
|
|
### 23. 日志记录补充
|
|
|
|
|
|
#### 23.1 日志应如何分层看
|
|
|
|
|
|
当前日志体系可以拆成四层:
|
|
|
|
|
|
- 平台运行日志
|
|
|
- 业务操作日志
|
|
|
- 异常日志
|
|
|
- 数据差异日志
|
|
|
|
|
|
其中差异日志对制造业很重要,因为很多主数据和工单、质检数据要求可追溯。
|
|
|
|
|
|
#### 23.2 建议重点保留的日志
|
|
|
|
|
|
对于制造业平台,建议重点保留:
|
|
|
|
|
|
- 主数据变更日志
|
|
|
- 审批操作日志
|
|
|
- 工单状态变更日志
|
|
|
- 库存调整日志
|
|
|
- 质检结论变更日志
|
|
|
- 接口异常日志
|
|
|
|
|
|
### 24. 代码生成补充
|
|
|
|
|
|
#### 24.1 当前代码生成的真正价值
|
|
|
|
|
|
代码生成的价值不是“生成一次后永远不用管”,而是:
|
|
|
|
|
|
- 快速建立标准模块骨架
|
|
|
- 统一后端目录和前端目录
|
|
|
- 统一菜单和按钮权限命名
|
|
|
- 统一 DTO 和页面结构
|
|
|
|
|
|
因此它更适合当“模块起步工具”,而不是“复杂业务最终实现工具”。
|
|
|
|
|
|
#### 24.2 适合生成的模块
|
|
|
|
|
|
适合:
|
|
|
|
|
|
- 主数据管理
|
|
|
- 参数管理
|
|
|
- 基础业务台账
|
|
|
- 标准 CRUD 配置类模块
|
|
|
|
|
|
不适合直接完全生成:
|
|
|
|
|
|
- 复杂审批流
|
|
|
- 多状态机驱动业务
|
|
|
- 多表联动强事务业务
|
|
|
- 复杂排程类业务
|
|
|
|
|
|
### 25. 可视化大屏补充
|
|
|
|
|
|
#### 25.1 大屏插件的定位
|
|
|
|
|
|
GoView 插件更像“项目承载层”,而不是“业务计算引擎”。
|
|
|
|
|
|
它负责:
|
|
|
|
|
|
- 项目内容保存
|
|
|
- 发布状态管理
|
|
|
- 预览图与背景图
|
|
|
|
|
|
业务实际要展示的数据应由业务 API 提供。
|
|
|
|
|
|
#### 25.2 制造业大屏落地建议
|
|
|
|
|
|
如果用于制造业大屏,建议数据来源按主题拆接口:
|
|
|
|
|
|
- 生产主题
|
|
|
- 质量主题
|
|
|
- 仓储主题
|
|
|
- 设备主题
|
|
|
- 能源主题
|
|
|
|
|
|
不要把所有统计塞到一个超大接口里。
|
|
|
|
|
|
### 26. OpenAPI 补充
|
|
|
|
|
|
#### 26.1 内部文档与开放接口要分开治理
|
|
|
|
|
|
当前项目同时具备:
|
|
|
|
|
|
- 内部接口文档系统
|
|
|
- 对外开放接口身份体系
|
|
|
|
|
|
这两个能力可以共存,但治理方式不同:
|
|
|
|
|
|
- 内部文档重点是开发调试效率
|
|
|
- 对外开放接口重点是安全、审计、稳定性
|
|
|
|
|
|
#### 26.2 对外开放接口建议的最小治理清单
|
|
|
|
|
|
建议至少做到:
|
|
|
|
|
|
- 每个系统独立凭据
|
|
|
- 请求签名
|
|
|
- nonce 防重放
|
|
|
- 时间戳校验
|
|
|
- 调用日志
|
|
|
- 限流
|
|
|
- 租户绑定
|
|
|
- 用户绑定
|
|
|
|
|
|
#### 26.3 `AdminResultProvider` 的补充价值
|
|
|
|
|
|
当前统一返回不仅影响普通接口,也影响:
|
|
|
|
|
|
- 鉴权失败
|
|
|
- 校验失败
|
|
|
- 系统异常
|
|
|
- 401 / 403 / 302
|
|
|
|
|
|
这对开放接口很重要,因为它保证对外响应结构一致,不会因为不同异常路径而返回完全不同的格式。
|
|
|
|
|
|
## 附录六:发布版章节补充
|
|
|
|
|
|
### 1. 框架简介发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 不清楚项目真正的后端入口在哪里
|
|
|
- 误以为 `Admin.NET.Application` 是全部后端核心
|
|
|
- 新人不知道应该先看哪几个文件建立上下文
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 先确认启动注册是否在 `Admin.NET.Web.Core/Startup.cs`
|
|
|
- 再确认全局配置绑定是否在 `ProjectOptions.cs`
|
|
|
- 再确认能力最终归属是在 `Admin.NET.Core` 还是插件
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Entry/Program.cs`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/ProjectOptions.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/AdminResultProvider.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 平台基础能力放 `Admin.NET.Core`
|
|
|
- 行业集成或外部系统对接优先做插件
|
|
|
- 强业务服务优先放应用层或新增业务工程
|
|
|
|
|
|
### 2. 开发流程发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 业务开发直接改核心层,后期升级困难
|
|
|
- 新功能上来就写 SQL,没有先确认是否已有封装
|
|
|
- 只开发接口,不补字典、权限、日志和导入导出
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 新模块开发前,先搜索是否已有同类系统服务
|
|
|
- 如果某能力看似缺失,先查 `Service`、`Utils`、`Extension`、`Plugins`
|
|
|
- 如果改动涉及全局行为,先确认是否应进 `Startup` 或 `ProjectOptions`
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/*`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/*`
|
|
|
- `Admin.NET/Admin.NET.Core/Extension/*`
|
|
|
- `Admin.NET/Plugins/*`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 新模块至少补齐实体、DTO、Service、菜单权限、日志点
|
|
|
- 规则多变的业务先做配置模型,再写执行逻辑
|
|
|
- 对标准 CRUD 模块优先考虑代码生成,再二次收敛
|
|
|
|
|
|
### 3. 数据库配置发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 启动时反复初始化表结构或种子数据
|
|
|
- 查询到了错误的数据库连接
|
|
|
- 开启连接串加密后数据库连不上
|
|
|
- 生产环境误开自动建表
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 `Database.json` 中 `EnableInitDb/EnableInitTable/EnableInitSeed/EnableInitView`
|
|
|
- 检查实体是否带 `TenantAttribute`、`SysTableAttribute`、`LogTableAttribute`
|
|
|
- 检查连接串加密配置键是否与 `DbConnectionOptions` 一致
|
|
|
- 检查 `SqlSugarRepository<T>` 是否因为请求头或 Claim 切到了租户库
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Database.json`
|
|
|
- `Admin.NET/Admin.NET.Core/Option/DbConnectionOptions.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 多数据库场景统一扩展 `ConnectionConfigs`
|
|
|
- 需要特殊数据库行为时优先补 `SqlSugarSetup.SetDbConfig()`
|
|
|
- 生产环境使用正式 SQL 脚本,不依赖自动建表
|
|
|
|
|
|
### 4. 实体基类发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 新增业务表后租户字段不自动写入
|
|
|
- 审计字段为空
|
|
|
- 软删除逻辑不生效
|
|
|
- 数据权限过滤不生效
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查是否继承了正确基类
|
|
|
- 检查实体是否真的包含 `TenantId`、`OrgId`、`IsDelete`
|
|
|
- 检查 `SqlSugarSetup.DataExecuting` 是否会自动填充对应字段
|
|
|
- 检查业务查询是否调用了 `ClearFilter()`
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Entity/EntityBase.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 新业务实体统一基于现有基类扩展
|
|
|
- 不要复制系统字段到业务实体里重写
|
|
|
- 需要自定义过滤标记时,可新增接口或特性并在过滤器层统一处理
|
|
|
|
|
|
### 5. 缓存管理发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 多节点环境下缓存不一致
|
|
|
- 清理了缓存但业务看起来仍然没更新
|
|
|
- 分布式锁没生效
|
|
|
- Redis 切换后部分功能异常
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查当前 `CacheType` 是 `Memory` 还是 `Redis`
|
|
|
- 检查缓存 Key 是否带统一前缀
|
|
|
- 检查是否通过 `SysCacheService` 操作,而不是直接用底层缓存
|
|
|
- 检查是否清理了多个关联 Key,而不是只删一个主 Key
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Cache.json`
|
|
|
- `Admin.NET/Admin.NET.Core/Cache/CacheSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Const/CacheConst.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 所有业务缓存统一定义常量前缀
|
|
|
- 复杂缓存场景封装成专用缓存服务,不直接散写在业务方法里
|
|
|
- 对需要跨节点一致性的功能强制要求 Redis
|
|
|
|
|
|
### 6. 导入导出发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- Excel 导入模板和实际字段不一致
|
|
|
- 字典文本导入后无法正确映射
|
|
|
- 导入失败但错误信息不清晰
|
|
|
- 直接导实体导致导出列过多
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 DTO 是否继承 `BaseImportInput`
|
|
|
- 检查 `ImporterHeader/ExporterHeader` 是否和模板列一致
|
|
|
- 检查字典字段是否正确配置 `ImportDictAttribute`
|
|
|
- 检查错误回写是否进入 `Error` 字段
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/CommonUtil.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/ExcelHelper.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/BaseImportInput.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Attribute/ImportDictAttribute.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 业务导入导出一律使用专用 DTO
|
|
|
- 错误标记与业务校验分层处理
|
|
|
- 大批量导入可继续扩展成异步任务模式
|
|
|
|
|
|
### 7. 上传下载发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 文件上传成功但预览或下载失败
|
|
|
- 本地和 OSS 场景切换后 URL 异常
|
|
|
- 文件删除了数据库记录但物理文件未删除
|
|
|
- 多存储提供者下默认桶配置混乱
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 `SysFileService` 最终选择了哪个 `FileProvider`
|
|
|
- 检查 `Upload.json` 中 `OSSProvider`、`SSHProvider`、`MultiOSS`
|
|
|
- 检查 `SysFileProviderService` 的默认提供者配置
|
|
|
- 检查文件记录中的 `BucketName`、`Url`、`FilePath`
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/File/SysFileProviderService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/File/FileProvider/*`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Upload.json`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 多业务线文件统一接入 `SysFileService`
|
|
|
- 多存储场景统一通过 `SysFileProviderService` 管理
|
|
|
- 高安全附件可在 Provider 层增加水印、病毒扫描、权限校验
|
|
|
|
|
|
### 8. 模板打印发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 模板能保存但渲染结果不符合预期
|
|
|
- 模板变量缺失导致运行异常
|
|
|
- 打印模板和消息模板概念混用
|
|
|
- 复杂打印需求误以为当前脚手架已完整支持
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查模板变量名与传入数据对象字段是否一致
|
|
|
- 检查 `SysTemplateService.RenderAsync()` 的渲染表达式
|
|
|
- 区分是 `SysPrintService` 的打印模板,还是 `SysTemplateService` 的通用模板
|
|
|
- 对 PDF、套打、打印路由需求,先确认当前代码是否已有统一实现
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Print/SysPrintService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Template/SysTemplateService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Entity/SysPrint.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Entity/SysTemplate.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 打印模板元数据走 `SysPrintService`
|
|
|
- 动态内容渲染走 `SysTemplateService`
|
|
|
- 复杂打印流程单独再封装打印模块,不把逻辑堆在现有两个服务中
|
|
|
|
|
|
### 9. 统一认证发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 登录成功但后续接口仍返回 401
|
|
|
- 开放接口签名认证失败
|
|
|
- OAuth 登录成功但后台权限链路不通
|
|
|
- Swagger 登录可用但普通接口授权失败
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查响应头里是否正确返回了 `access-token` / `refresh-token`
|
|
|
- 检查前端是否按 Bearer 规范携带 Token
|
|
|
- 检查 `JwtHandler` 是否因为黑名单或权限判定导致失败
|
|
|
- 检查开放接口请求头中的 `accessKey/timestamp/nonce/sign`
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SignatureAuth/SignatureAuthenticationHandler.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/OAuth/OAuthSetup.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 新增登录方式时复用 `CreateToken()` 主链路
|
|
|
- 后台接口继续走 JWT,不要自行另发 Token
|
|
|
- 开放接口继续走 Signature,不和后台用户鉴权混用
|
|
|
|
|
|
### 10. 数据权限发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 查询结果变少或为空
|
|
|
- 超级管理员和普通管理员看到的数据差异异常
|
|
|
- 自定义过滤器加了但没有生效
|
|
|
- 调试时怀疑 SQL 有问题,实际是全局过滤导致
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 先看实体基类是否正确
|
|
|
- 再看当前用户角色的数据范围缓存
|
|
|
- 再看租户 Claim、组织 Claim、用户 Claim
|
|
|
- 最后检查是否显式使用了 `ClearFilter()` 或 `IgnoreColumns`
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Enum/DataScopeEnum.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Entity/IEntityFilter.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 行业特殊过滤规则统一实现 `IEntityFilter`
|
|
|
- 角色、机构、用户权限调整后统一清缓存
|
|
|
- 避免每个业务服务自己拼数据权限 where 条件
|
|
|
|
|
|
### 11. 即时通讯发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 本地单机可推送,多节点后消息不同步
|
|
|
- 连接正常但广播不到目标用户
|
|
|
- 在线用户状态不准确
|
|
|
- 实时通知丢失后无法追溯
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 Redis Backplane 是否启用
|
|
|
- 检查 `Cluster.Enabled`、`SignalR.RedisConfiguration`
|
|
|
- 检查客户端连接是否带上了正确身份上下文
|
|
|
- 检查重要消息是否也落了数据库或通知表
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/SignalR/SignalRSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Hub/OnlineUserHub.cs`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 实时消息只做通知层,正式状态落库
|
|
|
- 多节点场景统一启用 Redis
|
|
|
- 高价值通知可增加“未读消息中心”补偿机制
|
|
|
|
|
|
### 12. 图片压缩发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 误以为当前已经支持上传自动压缩
|
|
|
- 图片上传后体积仍很大
|
|
|
- 不同业务需要不同压缩策略但没有统一入口
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 确认当前是否只是注册了 ImageSharp 中间件
|
|
|
- 确认 `SysFileService` 中是否真的有压缩逻辑
|
|
|
- 确认业务是否自行在前端做了压缩,从而误判后端能力
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 在 `SysFileService` 增加统一图片处理管线
|
|
|
- 图片压缩参数配置化
|
|
|
- 可按业务目录、文件类型、像素区间定义不同策略
|
|
|
|
|
|
### 13. 接口限流发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 本地测试总是触发 429
|
|
|
- 生产环境明明流量不大却误伤合法请求
|
|
|
- 反向代理后限流识别到的 IP 不正确
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 `Limit.json` 中 `EnableEndpointRateLimiting`
|
|
|
- 检查 `RealIpHeader` 是否与网关头一致
|
|
|
- 检查黑名单策略是否误配为 `Limit=0`
|
|
|
- 检查客户端是否共用了同一个 `X-ClientId`
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Limit.json`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Option/RateLimitOptions.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 登录、短信、开放接口用独立限流规则
|
|
|
- 把限流策略和环境区分开
|
|
|
- 高风险接口可同时叠加设备指纹或验证码策略
|
|
|
|
|
|
### 14. 国密信创发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 前端加密和后端解密不一致
|
|
|
- 换了公私钥后登录全部失败
|
|
|
- 连接串加密后读取失败
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查前端是否同步了新的公钥
|
|
|
- 检查后端 `Cryptogram.CryptoType` 是否与实际一致
|
|
|
- 检查历史数据是否仍使用旧算法
|
|
|
- 检查连接串是否经过同一算法加密
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/CryptogramUtil.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Option/CryptogramOptions.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/App.json`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 密钥统一配置和版本管理
|
|
|
- 需要平滑升级时增加算法兼容判定层
|
|
|
- 国密能力的使用场景统一走工具类,不散写加解密代码
|
|
|
|
|
|
### 15. 邮件发送发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 邮件发送报 SMTP 认证失败
|
|
|
- 本地测试能发,服务器发不出去
|
|
|
- 模板邮件文案和业务逻辑耦合太深
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 SMTP 服务器、端口、SSL、授权码
|
|
|
- 检查部署环境网络出口和防火墙
|
|
|
- 检查是否误把邮箱密码当成授权码
|
|
|
- 检查是否应该先通过模板服务生成内容
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Message/SysEmailService.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Email.json`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Template/SysTemplateService.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 邮件内容先模板化
|
|
|
- 发信动作事件化或异步化
|
|
|
- 后续可扩展发信日志、失败重试和多模板管理
|
|
|
|
|
|
### 16. 短信发送发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 验证码短信能发但校验失败
|
|
|
- 自定义短信接口返回成功但系统判断失败
|
|
|
- 高并发下同一手机号被重复发送
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查验证码缓存 Key 是否一致
|
|
|
- 检查 `VerifyCodeExpireSeconds`
|
|
|
- 检查自定义短信接口 `SuccessFlag`
|
|
|
- 检查是否对发送接口做了限流和防重复
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Message/SysSmsService.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/SMS.json`
|
|
|
- `Admin.NET/Admin.NET.Core/Const/CacheConst.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 验证码类短信统一封装发送频率控制
|
|
|
- 多短信通道增加主备切换
|
|
|
- 短信发送明细和状态单独落日志表
|
|
|
|
|
|
### 17. 微信对接发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 公众号、小程序、企业微信接口混用
|
|
|
- OpenId 登录成功但无法映射到业务用户
|
|
|
- 微信支付回调到了但订单状态没更新
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 先区分是 `SysWechatService`、`SysWechatPayService` 还是 `WorkWeixin` 插件
|
|
|
- 检查支付回调地址是否和配置一致
|
|
|
- 检查本地订单号与微信交易号的映射
|
|
|
- 检查支付和退款回调中的商户号、应用号是否匹配
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Wechat.json`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.WorkWeixin/*`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 微信用户、支付单、退款单分别建清晰的业务边界
|
|
|
- 企业微信场景继续插件化
|
|
|
- 支付状态同步建议增加幂等与补偿查询任务
|
|
|
|
|
|
### 18. 多租户 SAAS发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 租户切换后数据仍然是旧租户的
|
|
|
- 新增租户后菜单和管理员没初始化完整
|
|
|
- 独立库租户有时连不上
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查请求头 `TenantId` 和当前登录 Claim `TenantId`
|
|
|
- 检查 `SysTenantService.CacheTenant()` 是否执行
|
|
|
- 检查租户库连接串是否已加密或已解密
|
|
|
- 检查实体是否继承租户基类
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 新业务从建模阶段就明确租户模式
|
|
|
- 租户初始化逻辑集中在租户服务,不分散到业务模块
|
|
|
- 独立库模式可继续补租户迁移、备份和回收策略
|
|
|
|
|
|
### 19. 远程请求发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 第三方接口调用超时或结果格式不统一
|
|
|
- 插件提供了代理接口但系统没真正启用
|
|
|
- 业务里到处出现裸 `HttpClient`
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查插件是否被 `Application.csproj` 引用
|
|
|
- 检查插件 `Startup.cs` 是否注册了对应代理
|
|
|
- 检查配置类是否已绑定
|
|
|
- 检查 DTO 和返回模型是否与对方接口版本一致
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/*`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.WorkWeixin/*`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.K3Cloud/*`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.ReZero/*`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 所有三方系统集成做成“配置 + DTO + Proxy + Service”四件套
|
|
|
- 异常、超时、签名、重试统一封装
|
|
|
- 新插件如需鉴权,尽量复用现有 JWT 或开放接口机制
|
|
|
|
|
|
### 20. 消息队列发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 事件发布了但订阅器没执行
|
|
|
- Redis 模式下消息行为和单机不一致
|
|
|
- 失败重试后仍无结果,不知道在哪里排查
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查事件是否真的通过 `IEventPublisher` 发布
|
|
|
- 检查订阅器是否正确标注 `EventSubscribe`
|
|
|
- 检查 Redis 缓存是否启用,事件源是否已替换
|
|
|
- 检查 `RetryEventHandlerExecutor` 的重试日志和 fallback
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/EventBus/AppEventSubscriber.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/EventBus/RetryEventHandlerExecutor.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/EventBus/RabbitMQEventSourceStore.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 事件用于解耦非主流程动作
|
|
|
- 高可靠消息场景继续在现有基础上补正式 MQ 治理能力
|
|
|
- 关键事件建议加业务日志与重放能力
|
|
|
|
|
|
### 21. 定时任务发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 作业能在本地跑,部署后不执行
|
|
|
- 任务看板登录异常
|
|
|
- 动态作业编译成功但执行报错
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 `JobSchedule.Enabled`
|
|
|
- 检查作业持久化与监控是否已注册
|
|
|
- 检查任务代码是否实现 `IJob`
|
|
|
- 检查 `/schedule` 登录时是否依赖后台账号认证链路
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Job/DynamicJobCompiler.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Schedule/SysScheduleService.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 系统级任务统一走调度器
|
|
|
- 用户日程统一走业务日程服务
|
|
|
- 动态任务建议加来源审计和发布审批
|
|
|
|
|
|
### 22. 令牌 Token发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 刷新 Token 后旧 Token 还能用或不能用
|
|
|
- 退出登录后依然能访问部分接口
|
|
|
- 自动续期和前端 Token 刷新策略冲突
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 `Logout()` 是否写入黑名单缓存
|
|
|
- 检查 `JwtHandler` 是否真正参与授权链路
|
|
|
- 检查前端是否及时替换响应头里的新 Token
|
|
|
- 检查刷新逻辑是否走了系统自带接口
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Const/CacheConst.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- Token 体系统一由认证服务维护
|
|
|
- 多端登录策略配置化
|
|
|
- 高安全项目增加 Token 审计与设备指纹校验
|
|
|
|
|
|
### 23. 日志记录发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 数据库日志或 ES 日志没写入
|
|
|
- SQL 执行异常但看不到关键定位信息
|
|
|
- 业务操作日志不全,后续无法追溯
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 `Logging.json` 是否开启对应日志通道
|
|
|
- 检查 ES 或数据库写入器配置是否正确
|
|
|
- 检查 `SqlSugarSetup` 的 AOP 是否已挂上
|
|
|
- 检查关键业务动作是否真的打了操作日志
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Logging/LoggingSetup.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Logging/DatabaseLoggingWriter.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Logging/ElasticSearchLoggingWriter.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Log/*`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Logging.json`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 重要业务动作统一补操作日志
|
|
|
- 关键主数据启用差异日志
|
|
|
- 针对制造业追溯需求,可扩展业务轨迹日志表
|
|
|
|
|
|
### 24. 代码生成发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 代码生成出的模块路径不对
|
|
|
- 同步字段后配置丢失
|
|
|
- 菜单和按钮权限重复
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 `CodeGen.json` 中命名空间和前端根目录配置
|
|
|
- 检查生成前是否已正确设置页面路径、模块名、菜单父级
|
|
|
- 检查表字段变更后是否重新同步字段配置
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/CodeGenUtil.cs`
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/CodeGen.json`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 代码生成只做骨架和标准模块起步
|
|
|
- 生成后进入业务层继续收敛
|
|
|
- 复杂模块单独维护模板或直接手写
|
|
|
|
|
|
### 25. 可视化大屏发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- 大屏项目数据保存了但预览图不显示
|
|
|
- 大屏插件能用,但业务数据接口没有统一规划
|
|
|
- 误把大屏插件当成统计引擎
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 `GoViewProService` 中预览图和背景图的 Base64 存储
|
|
|
- 检查项目内容与项目元数据是否同时存在
|
|
|
- 检查大屏消费的数据接口是否由业务服务正确提供
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.GoView/Startup.cs`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.GoView/Service/GoViewPro/GoViewProService.cs`
|
|
|
- `Admin.NET/Plugins/Admin.NET.Plugin.GoView/Util/GoViewResultProvider.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 大屏插件继续只做项目管理层
|
|
|
- 统计、聚合、指标统一从业务后端接口输出
|
|
|
- 可按生产、质量、设备、能源拆分大屏 API
|
|
|
|
|
|
### 26. OpenAPI发布版补充
|
|
|
|
|
|
#### 常见问题
|
|
|
|
|
|
- Swagger 可见但部分接口调试失败
|
|
|
- 开放接口签名通过但业务身份不正确
|
|
|
- 对外开放接口返回结构不统一
|
|
|
|
|
|
#### 排错建议
|
|
|
|
|
|
- 检查 `Swagger.json` 登录配置和生产环境开关
|
|
|
- 检查 `SysOpenAccessService` 是否正确绑定用户和租户
|
|
|
- 检查开放接口是否使用了 `SignatureAuthenticationDefaults.AuthenticationScheme`
|
|
|
- 检查统一返回是否被 `NonUnify` 绕过
|
|
|
|
|
|
#### 代码定位路径
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Application/Configuration/Swagger.json`
|
|
|
- `Admin.NET/Admin.NET.Application/OpenApi/DemoOpenApi.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/OpenAccess/SysOpenAccessService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/SignatureAuth/SignatureAuthenticationHandler.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/AdminResultProvider.cs`
|
|
|
|
|
|
#### 推荐扩展写法
|
|
|
|
|
|
- 对外开放接口使用独立分组和独立认证方案
|
|
|
- 开放接口接入时同步给出签名示例、错误码和调用频率约束
|
|
|
- 内外部接口文档分开治理,避免后台接口暴露过多
|
|
|
|
|
|
## 附录七:统一术语表
|
|
|
|
|
|
| 术语 | 含义 | 当前脚手架落点 | 备注 |
|
|
|
| --- | --- | --- | --- |
|
|
|
| 宿主 | 应用启动入口与 Web 容器承载层 | `Admin.NET.Web.Entry` | 只做最薄启动,不承载业务 |
|
|
|
| 启动装配层 | 全局注册服务与中间件链的层 | `Admin.NET.Web.Core` | 后端能力总入口 |
|
|
|
| 基础设施层 | 平台公共能力沉淀层 | `Admin.NET.Core` | 数据库、缓存、鉴权、文件、模板等 |
|
|
|
| 应用层 | 业务接口暴露和配置承载层 | `Admin.NET.Application` | 当前更偏示例与默认应用 |
|
|
|
| 插件 | 可独立启停的扩展模块 | `Admin.NET/Plugins/*` | 适合集成和独立业务域 |
|
|
|
| 动态 API | 通过服务类自动生成接口的模式 | `IDynamicApiController` | 不强制手写 Controller |
|
|
|
| 统一返回 | 后端统一响应结构 | `AdminResultProvider` | 成功、异常、401/403 统一处理 |
|
|
|
| 仓储 | 默认数据访问入口 | `SqlSugarRepository<T>` | 自动切库、承接过滤器 |
|
|
|
| 切库 | 按租户或特性切换数据库连接 | `SqlSugarRepository<T>` | 主库、日志库、租户库 |
|
|
|
| 全局过滤器 | 统一附加到查询上的过滤条件 | `SqlSugarFilter` | 软删、租户、数据权限 |
|
|
|
| 租户隔离 | 按租户区分数据边界 | `SysTenantService` + `SqlSugar*` | 支持同库和独立库 |
|
|
|
| 数据权限 | 按组织、角色、本人范围过滤数据 | `SqlSugarFilter` | 与租户过滤可叠加 |
|
|
|
| 开放接口 | 面向外部系统的签名接口 | `SysOpenAccessService` | 不走后台 JWT |
|
|
|
| Signature 鉴权 | `accessKey/accessSecret` 签名认证 | `SignatureAuthenticationHandler` | 含时间戳与 nonce |
|
|
|
| JWT 鉴权 | 后台用户访问认证方式 | `SysAuthService` + `JwtHandler` | 支持刷新和黑名单 |
|
|
|
| Token 黑名单 | 失效 Token 缓存记录 | `SysCacheService` | 登出后写入 |
|
|
|
| 任务调度 | 系统后台作业调度能力 | `AddSchedule` | 与业务日程不同 |
|
|
|
| 业务日程 | 用户或业务提醒计划数据 | `SysScheduleService` | 不是系统作业引擎 |
|
|
|
| 事件总线 | 异步事件发布订阅机制 | `AddEventBus` | 可走内存或 Redis |
|
|
|
| 声明式 HTTP | 用接口声明远程请求 | `AddHttpRemote` | 适合 DingTalk/WorkWeixin |
|
|
|
| 文件提供者 | 文件存储适配实现 | `ICustomFileProvider` | 本地、OSS、SSH、多存储 |
|
|
|
| 多存储 | 多桶、多提供者文件方案 | `SysFileProviderService` | 可配置默认提供者 |
|
|
|
| 模板渲染 | 将模板内容与数据合成结果 | `SysTemplateService` | 适合消息、打印文本 |
|
|
|
| 打印模板 | 打印场景模板元数据管理 | `SysPrintService` | 偏管理,不是完整打印中心 |
|
|
|
| 差异日志 | 记录字段修改前后差异 | `SqlSugarSetup` + `SysLogDiff` | 适合追溯要求高的业务 |
|
|
|
| 代码生成 | 根据表结构生成前后端骨架 | `SysCodeGenService` | 适合标准 CRUD |
|
|
|
| 可视化大屏 | 大屏项目内容管理能力 | `GoView` 插件 | 不是统计引擎本身 |
|
|
|
| 超级 API | 面向库表的快速接口能力 | `ReZero` 插件 | 默认应用层未启用 |
|
|
|
|
|
|
## 附录八:架构图
|
|
|
|
|
|
### 1. 总体架构图
|
|
|
|
|
|
```mermaid
|
|
|
flowchart TB
|
|
|
U["用户 / 外部系统 / 三方平台"] --> E["Admin.NET.Web.Entry<br/>宿主入口"]
|
|
|
E --> W["Admin.NET.Web.Core<br/>启动装配层"]
|
|
|
W --> A["Admin.NET.Application<br/>默认应用层"]
|
|
|
W --> C["Admin.NET.Core<br/>基础设施中心"]
|
|
|
A --> C
|
|
|
W --> P["Plugins<br/>插件扩展层"]
|
|
|
|
|
|
C --> DB["SqlSugar / 多数据库 / 多租户"]
|
|
|
C --> CA["Cache / Redis / Memory"]
|
|
|
C --> AU["JWT / Signature / OAuth"]
|
|
|
C --> FS["File / OSS / MultiOSS / SSH"]
|
|
|
C --> EV["EventBus / Schedule / SignalR"]
|
|
|
C --> LG["Logging / DiffLog / ES"]
|
|
|
|
|
|
P --> DT["DingTalk"]
|
|
|
P --> GV["GoView"]
|
|
|
P --> WW["WorkWeixin"]
|
|
|
P --> K3["K3Cloud"]
|
|
|
P --> RZ["ReZero"]
|
|
|
```
|
|
|
|
|
|
### 2. 分层职责图
|
|
|
|
|
|
```mermaid
|
|
|
flowchart LR
|
|
|
ENTRY["Web.Entry<br/>负责启动"] --> COREWEB["Web.Core<br/>负责注册服务和中间件"]
|
|
|
COREWEB --> APP["Application<br/>负责默认业务接口和配置"]
|
|
|
COREWEB --> CORE["Core<br/>负责实体、基础设施、系统服务"]
|
|
|
APP --> CORE
|
|
|
APP --> PLUGIN["Plugins<br/>按需扩展能力"]
|
|
|
```
|
|
|
|
|
|
### 3. 核心能力归属图
|
|
|
|
|
|
```mermaid
|
|
|
mindmap
|
|
|
root(("Admin.NET 后端"))
|
|
|
启动
|
|
|
Web.Entry
|
|
|
Web.Core
|
|
|
数据
|
|
|
SqlSugarSetup
|
|
|
SqlSugarRepository
|
|
|
SqlSugarFilter
|
|
|
鉴权
|
|
|
SysAuthService
|
|
|
JwtHandler
|
|
|
SignatureAuthenticationHandler
|
|
|
SysOpenAccessService
|
|
|
租户
|
|
|
SysTenantService
|
|
|
缓存
|
|
|
CacheSetup
|
|
|
SysCacheService
|
|
|
文件
|
|
|
SysFileService
|
|
|
SysFileProviderService
|
|
|
模板
|
|
|
SysTemplateService
|
|
|
SysPrintService
|
|
|
调度与事件
|
|
|
AddSchedule
|
|
|
DynamicJobCompiler
|
|
|
AddEventBus
|
|
|
日志
|
|
|
LoggingSetup
|
|
|
SysLogExService
|
|
|
SysLogOpService
|
|
|
SysLogDiffService
|
|
|
```
|
|
|
|
|
|
## 附录九:请求链路图
|
|
|
|
|
|
### 1. 后台普通请求链路
|
|
|
|
|
|
```mermaid
|
|
|
sequenceDiagram
|
|
|
participant Client as 前端/客户端
|
|
|
participant Middleware as 中间件链
|
|
|
participant Auth as JwtHandler
|
|
|
participant Api as IDynamicApiController
|
|
|
participant Service as 业务服务
|
|
|
participant Repo as SqlSugarRepository
|
|
|
participant Db as Database
|
|
|
|
|
|
Client->>Middleware: HTTP 请求 + Bearer Token
|
|
|
Middleware->>Auth: 认证授权
|
|
|
Auth->>Auth: 黑名单校验 / 自动续期 / 按钮权限
|
|
|
Auth-->>Middleware: 通过
|
|
|
Middleware->>Api: 路由到动态接口
|
|
|
Api->>Service: 调用服务方法
|
|
|
Service->>Repo: 仓储访问
|
|
|
Repo->>Repo: 判断系统表/日志表/租户表/请求头TenantId
|
|
|
Repo->>Db: 执行查询或写入
|
|
|
Db-->>Repo: 返回结果
|
|
|
Repo-->>Service: 返回实体/分页结果
|
|
|
Service-->>Api: 返回业务结果
|
|
|
Api-->>Middleware: 统一返回包装
|
|
|
Middleware-->>Client: AdminResult
|
|
|
```
|
|
|
|
|
|
### 2. 开放接口请求链路
|
|
|
|
|
|
```mermaid
|
|
|
sequenceDiagram
|
|
|
participant Partner as 外部系统
|
|
|
participant Sig as SignatureAuthenticationHandler
|
|
|
participant OpenSvc as SysOpenAccessService
|
|
|
participant Api as OpenApi服务
|
|
|
participant Repo as SqlSugarRepository
|
|
|
participant Db as Database
|
|
|
|
|
|
Partner->>Sig: accessKey + timestamp + nonce + sign
|
|
|
Sig->>Sig: 时间戳校验
|
|
|
Sig->>OpenSvc: 根据accessKey读取accessSecret
|
|
|
OpenSvc-->>Sig: accessSecret + 绑定用户/租户
|
|
|
Sig->>Sig: 签名校验 + nonce防重放
|
|
|
Sig-->>Api: 注入Claims并通过认证
|
|
|
Api->>Repo: 执行业务查询
|
|
|
Repo->>Db: 自动套用租户/权限逻辑
|
|
|
Db-->>Repo: 返回结果
|
|
|
Repo-->>Api: 返回数据
|
|
|
Api-->>Partner: 统一结果
|
|
|
```
|
|
|
|
|
|
### 3. 文件上传链路
|
|
|
|
|
|
```mermaid
|
|
|
flowchart LR
|
|
|
A["客户端上传文件"] --> B["SysFileService"]
|
|
|
B --> C["校验文件名/大小/类型/后缀/MD5"]
|
|
|
C --> D["选择FileProvider"]
|
|
|
D --> E["本地 / OSS / SSH / MultiOSS"]
|
|
|
E --> F["保存SysFile元数据"]
|
|
|
F --> G["返回文件URL/Id/路径信息"]
|
|
|
```
|
|
|
|
|
|
## 附录十:角色与权限关系图
|
|
|
|
|
|
### 1. 角色权限主关系
|
|
|
|
|
|
```mermaid
|
|
|
flowchart TB
|
|
|
U["用户 SysUser"] --> UR["用户角色关系 SysUserRole"]
|
|
|
UR --> R["角色 SysRole"]
|
|
|
R --> RM["角色菜单关系 SysRoleMenu"]
|
|
|
RM --> M["菜单 / 按钮 SysMenu"]
|
|
|
|
|
|
U --> O["机构 SysOrg"]
|
|
|
R --> DS["数据范围 DataScope"]
|
|
|
DS --> DF["SqlSugarFilter 数据权限过滤"]
|
|
|
M --> BTN["按钮权限集合"]
|
|
|
BTN --> JH["JwtHandler 路由按钮鉴权"]
|
|
|
```
|
|
|
|
|
|
### 2. 权限判定简图
|
|
|
|
|
|
```mermaid
|
|
|
flowchart LR
|
|
|
Req["请求路由"] --> Jwt["JwtHandler"]
|
|
|
Jwt --> Super{"是否超管"}
|
|
|
Super -- 是 --> Pass["直接放行"]
|
|
|
Super -- 否 --> Btn["获取用户按钮权限"]
|
|
|
Btn --> Match{"路由是否命中按钮权限"}
|
|
|
Match -- 是 --> Pass
|
|
|
Match -- 否 --> AllBtn["获取系统全部按钮权限"]
|
|
|
AllBtn --> Public{"是否非受控按钮路由"}
|
|
|
Public -- 是 --> Pass
|
|
|
Public -- 否 --> Deny["403 / 无权限"]
|
|
|
```
|
|
|
|
|
|
## 附录十一:租户隔离说明图
|
|
|
|
|
|
### 1. 租户隔离模型图
|
|
|
|
|
|
```mermaid
|
|
|
flowchart TB
|
|
|
T["租户访问请求"] --> R["SqlSugarRepository<T>"]
|
|
|
R --> A{"实体是否系统表"}
|
|
|
A -- 是 --> MAIN["主库 MainConfig"]
|
|
|
A -- 否 --> B{"实体是否日志表"}
|
|
|
B -- 是 --> LOG["日志库 LogConfig"]
|
|
|
B -- 否 --> C{"实体是否显式指定TenantAttribute"}
|
|
|
C -- 是 --> SPEC["指定库连接"]
|
|
|
C -- 否 --> D{"请求头/Claim中是否存在TenantId"}
|
|
|
D -- 否 --> MAIN
|
|
|
D -- 是 --> E{"租户模式"}
|
|
|
E -- ID隔离 --> MAIN
|
|
|
E -- DB隔离 --> TENANTDB["租户独立库"]
|
|
|
```
|
|
|
|
|
|
### 2. 租户请求与过滤器关系图
|
|
|
|
|
|
```mermaid
|
|
|
flowchart LR
|
|
|
H["请求头 TenantId"] --> Repo["SqlSugarRepository"]
|
|
|
C["用户Claim TenantId"] --> Repo
|
|
|
Repo --> Scope["连接作用域"]
|
|
|
Scope --> Filter["SqlSugarFilter"]
|
|
|
Filter --> Soft["软删过滤"]
|
|
|
Filter --> Tenant["租户过滤"]
|
|
|
Filter --> Org["机构过滤"]
|
|
|
Filter --> Self["仅本人过滤"]
|
|
|
Filter --> Custom["自定义实体过滤"]
|
|
|
```
|
|
|
|
|
|
### 3. 租户初始化图
|
|
|
|
|
|
```mermaid
|
|
|
flowchart TD
|
|
|
Add["新增租户"] --> Init["SysTenantService.InitNewTenant"]
|
|
|
Init --> Org["初始化机构"]
|
|
|
Init --> Role["初始化默认角色"]
|
|
|
Init --> Pos["初始化岗位"]
|
|
|
Init --> User["初始化管理员账号"]
|
|
|
Init --> Menu["初始化租户菜单授权"]
|
|
|
Init --> Cache["刷新租户缓存"]
|
|
|
```
|
|
|
|
|
|
## 附录十二:插件启用矩阵表
|
|
|
|
|
|
### 1. 插件矩阵
|
|
|
|
|
|
| 插件 | 目录 | 当前默认应用层是否引用 | Startup 是否存在 | 主要能力 | 当前状态 | 启用建议 |
|
|
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
|
| ApprovalFlow | `Admin.NET.Plugin.ApprovalFlow` | 是 | 是 | 审批流中间件 | 默认启用 | 审批场景可直接基于此扩展 |
|
|
|
| DingTalk | `Admin.NET.Plugin.DingTalk` | 是 | 是 | 钉钉接口、审批、组织同步、消息卡片 | 默认启用 | 钉钉集成优先复用该插件 |
|
|
|
| GoView | `Admin.NET.Plugin.GoView` | 是 | 是 | 大屏项目管理、发布、预览图 | 默认启用 | 可直接作为大屏后端支撑 |
|
|
|
| HwPortal | `Admin.NET.Plugin.HwPortal` | 是 | 以项目引用为准 | 行业门户相关能力 | 默认引用 | 使用前建议补专项文档 |
|
|
|
| WorkWeixin | `Admin.NET.Plugin.WorkWeixin` | 否 | 是 | 企业微信代理接口与配置 | 代码存在未默认启用 | 需要企业微信时先补项目引用 |
|
|
|
| K3Cloud | `Admin.NET.Plugin.K3Cloud` | 否 | 是 | 金蝶云星空命名客户端与配置 | 代码存在未默认启用 | ERP 集成时按需启用 |
|
|
|
| ReZero | `Admin.NET.Plugin.ReZero` | 否 | 是 | 超级 API、JWT 校验 AOP、日志接入 | 代码存在未默认启用 | 仅在需要超级 API 时启用 |
|
|
|
|
|
|
### 2. 默认启用判断依据
|
|
|
|
|
|
默认是否启用,以 `Admin.NET/Admin.NET.Application/Admin.NET.Application.csproj` 中是否存在对应 `ProjectReference` 为准。
|
|
|
|
|
|
### 3. 插件启用步骤建议
|
|
|
|
|
|
1. 在 `Application.csproj` 中增加对应插件引用
|
|
|
2. 确认插件有无专属配置文件和配置项
|
|
|
3. 确认插件 `Startup.cs` 是否注册了必要服务
|
|
|
4. 检查插件是否依赖第三方服务、证书、账号或回调地址
|
|
|
5. 补充模块级验证与接入文档
|
|
|
|
|
|
## 附录十三:培训与交接版最小示例代码片段
|
|
|
|
|
|
### 1. 框架简介示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Application/Example/ExampleService.cs
|
|
|
[ApiDescriptionSettings("示例分组", Name = "Example", Order = 100)]
|
|
|
public class ExampleService : IDynamicApiController
|
|
|
{
|
|
|
[HttpGet("ping")]
|
|
|
public string Ping()
|
|
|
{
|
|
|
return "pong";
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 新增服务优先实现 `IDynamicApiController`
|
|
|
- 分组、名称、顺序统一通过 `ApiDescriptionSettings` 管理
|
|
|
- 不要轻易改动对外暴露路径风格,避免影响前端与培训材料
|
|
|
|
|
|
### 2. 开发流程示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Web.Core/ProjectOptions.cs
|
|
|
public static IServiceCollection AddProjectOptions(this IServiceCollection services)
|
|
|
{
|
|
|
services.AddConfigurableOptions<ExampleOptions>();
|
|
|
return services;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 新增配置类时必须同步注册 Options 绑定
|
|
|
- 公共流程改动前先确认是否影响已有插件和现有业务模块
|
|
|
- 培训资料中的开发顺序一旦确定,尽量不要频繁调整
|
|
|
|
|
|
### 3. 数据库配置示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"DbConnection": {
|
|
|
"EnableConsoleSql": false,
|
|
|
"ConnectionConfigs": [
|
|
|
{
|
|
|
"ConfigId": "1300000000001",
|
|
|
"DbType": "Sqlite",
|
|
|
"ConnectionString": "DataSource=./Admin.NET.db",
|
|
|
"DbSettings": {
|
|
|
"EnableInitDb": true,
|
|
|
"EnableInitView": true,
|
|
|
"EnableDiffLog": false,
|
|
|
"EnableUnderLine": false,
|
|
|
"EnableConnStringEncrypt": false
|
|
|
}
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 自动建表、种子、视图开关变更要明确环境范围
|
|
|
- 连接串加密配置键必须与代码属性保持一致
|
|
|
- 新增连接配置后要同步更新部署文档和实施手册
|
|
|
|
|
|
### 4. 实体基类示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Entity/ExampleOrder.cs
|
|
|
[SugarTable("sys_example_order", "示例订单")]
|
|
|
public class ExampleOrder : EntityBaseTenantOrgDel
|
|
|
{
|
|
|
[SugarColumn(ColumnDescription = "单号", Length = 64)]
|
|
|
public string OrderNo { get; set; }
|
|
|
|
|
|
[SugarColumn(ColumnDescription = "状态")]
|
|
|
public int Status { get; set; }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 基类变更会直接影响租户、机构、软删和审计行为
|
|
|
- 已上线表修改基类前必须做数据兼容评估
|
|
|
- 培训时要明确不同业务对象应该继承哪类基类
|
|
|
|
|
|
### 5. 缓存管理示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleCacheService.cs
|
|
|
public class ExampleCacheService
|
|
|
{
|
|
|
private readonly SysCacheService _sysCacheService;
|
|
|
|
|
|
public ExampleCacheService(SysCacheService sysCacheService)
|
|
|
{
|
|
|
_sysCacheService = sysCacheService;
|
|
|
}
|
|
|
|
|
|
public string GetOrCreateName(long id)
|
|
|
{
|
|
|
return _sysCacheService.GetOrAdd($"example:name:{id}", _ => $"NAME-{id}", 300);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 缓存 Key 规则变更要同步清理历史 Key
|
|
|
- Memory 切 Redis 后要补多节点回归测试
|
|
|
- 缓存前缀调整要同步培训文档和运维脚本
|
|
|
|
|
|
### 6. 导入导出示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/Dto/ExampleImportInput.cs
|
|
|
public class ExampleImportInput : BaseImportInput
|
|
|
{
|
|
|
[ImporterHeader(Name = "单号")]
|
|
|
[ExporterHeader("单号")]
|
|
|
public string OrderNo { get; set; }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 模板列名变更要同步 DTO 特性和培训模板
|
|
|
- 导入 DTO 不建议直接复用实体
|
|
|
- 错误标记格式变更要同步实施与用户培训说明
|
|
|
|
|
|
### 7. 上传下载示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleFileService.cs
|
|
|
public class ExampleFileService : IDynamicApiController
|
|
|
{
|
|
|
private readonly SysFileService _sysFileService;
|
|
|
|
|
|
public ExampleFileService(SysFileService sysFileService)
|
|
|
{
|
|
|
_sysFileService = sysFileService;
|
|
|
}
|
|
|
|
|
|
[HttpPost("uploadAttachment")]
|
|
|
public Task<SysFile> UploadAttachment(IFormFile file)
|
|
|
{
|
|
|
return _sysFileService.UploadFile(new UploadFileInput { File = file }, "upload/example");
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 存储路径规则调整要考虑历史文件兼容
|
|
|
- OSS、SSH、多存储切换后要回归预览、下载、删除
|
|
|
- 文件 URL 生成规则变更要同步前端和培训资料
|
|
|
|
|
|
### 8. 模板打印示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleTemplateFacade.cs
|
|
|
public class ExampleTemplateFacade
|
|
|
{
|
|
|
private readonly SysTemplateService _sysTemplateService;
|
|
|
|
|
|
public ExampleTemplateFacade(SysTemplateService sysTemplateService)
|
|
|
{
|
|
|
_sysTemplateService = sysTemplateService;
|
|
|
}
|
|
|
|
|
|
public Task<string> RenderNotice()
|
|
|
{
|
|
|
return _sysTemplateService.RenderByCode("example_notice", new Dictionary<string, object>
|
|
|
{
|
|
|
{ "OrderNo", "MO-20260315-001" },
|
|
|
{ "Status", "已完成" }
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 模板变量名变更要同步业务渲染代码
|
|
|
- 模板编码建议一经发布尽量稳定
|
|
|
- 打印模板和消息模板改动要分开发布说明
|
|
|
|
|
|
### 9. 统一认证示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Auth/ExampleAuthFacade.cs
|
|
|
public class ExampleAuthFacade : IDynamicApiController
|
|
|
{
|
|
|
private readonly SysAuthService _sysAuthService;
|
|
|
|
|
|
public ExampleAuthFacade(SysAuthService sysAuthService)
|
|
|
{
|
|
|
_sysAuthService = sysAuthService;
|
|
|
}
|
|
|
|
|
|
[AllowAnonymous]
|
|
|
[HttpPost("loginByAccount")]
|
|
|
public Task<LoginOutput> LoginByAccount(LoginInput input)
|
|
|
{
|
|
|
return _sysAuthService.Login(input);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 登录入参结构变更要同步前端、Swagger 和培训材料
|
|
|
- Token 响应头名称不要频繁调整
|
|
|
- 新增认证方式时要优先复用现有主链路
|
|
|
|
|
|
### 10. 数据权限示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Entity/ExampleTask.cs
|
|
|
[SugarTable("sys_example_task", "示例任务")]
|
|
|
public class ExampleTask : EntityBaseTenantOrg
|
|
|
{
|
|
|
[SugarColumn(ColumnDescription = "任务名称", Length = 128)]
|
|
|
public string Name { get; set; }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 从无组织基类切到带组织基类会改变查询结果
|
|
|
- 权限相关缓存清理要纳入变更步骤
|
|
|
- 自定义过滤器上线前要先评估历史报表和统计口径
|
|
|
|
|
|
### 11. 即时通讯示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleNoticeService.cs
|
|
|
public class ExampleNoticeService
|
|
|
{
|
|
|
private readonly IHubContext<OnlineUserHub, IOnlineUserHub> _hubContext;
|
|
|
|
|
|
public ExampleNoticeService(IHubContext<OnlineUserHub, IOnlineUserHub> hubContext)
|
|
|
{
|
|
|
_hubContext = hubContext;
|
|
|
}
|
|
|
|
|
|
public Task Broadcast(string message)
|
|
|
{
|
|
|
return _hubContext.Clients.All.ReceiveMessage(message);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- Hub 方法名变更要同步前端订阅代码
|
|
|
- 多节点部署前必须验证 Redis Backplane
|
|
|
- 培训中要强调“通知层”和“状态层”分离
|
|
|
|
|
|
### 12. 图片压缩示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleImageService.cs
|
|
|
public class ExampleImageService
|
|
|
{
|
|
|
// 建议在此处继续封装统一图片压缩逻辑,
|
|
|
// 不建议在各业务服务中散写处理代码。
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 该章节当前属于二开能力,不能按现成功能培训为“已完整支持”
|
|
|
- 图片压缩上线后要评估原图兼容策略
|
|
|
- 质量和尺寸参数必须可配置
|
|
|
|
|
|
### 13. 接口限流示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"IpRateLimiting": {
|
|
|
"EnableEndpointRateLimiting": true,
|
|
|
"GeneralRules": [
|
|
|
{
|
|
|
"Endpoint": "*:/api/example/sendCode",
|
|
|
"Period": "1m",
|
|
|
"Limit": 5
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 限流阈值变更要同步测试和生产配置
|
|
|
- 代理头配置变更要与网关一起发布
|
|
|
- 开放接口限流规则调整要提前通知对接方
|
|
|
|
|
|
### 14. 国密信创示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"Cryptogram": {
|
|
|
"CryptoType": "SM2",
|
|
|
"PublicKey": "your_public_key",
|
|
|
"PrivateKey": "your_private_key"
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 公私钥切换必须前后端同步
|
|
|
- 算法调整前要评估历史数据兼容
|
|
|
- 培训时要明确密钥和普通配置的权限边界
|
|
|
|
|
|
### 15. 邮件发送示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleMailFacade.cs
|
|
|
public class ExampleMailFacade
|
|
|
{
|
|
|
private readonly SysEmailService _sysEmailService;
|
|
|
|
|
|
public ExampleMailFacade(SysEmailService sysEmailService)
|
|
|
{
|
|
|
_sysEmailService = sysEmailService;
|
|
|
}
|
|
|
|
|
|
public Task SendAlarm()
|
|
|
{
|
|
|
return _sysEmailService.SendEmail("<b>设备告警</b>", "设备告警通知", "alarm@example.com");
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- SMTP 通道调整要同步运维配置
|
|
|
- 邮件模板或标题规范变更要同步培训资料
|
|
|
- 上线前建议增加发送日志和失败回溯能力
|
|
|
|
|
|
### 16. 短信发送示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleSmsFacade.cs
|
|
|
public class ExampleSmsFacade : IDynamicApiController
|
|
|
{
|
|
|
private readonly SysSmsService _sysSmsService;
|
|
|
|
|
|
public ExampleSmsFacade(SysSmsService sysSmsService)
|
|
|
{
|
|
|
_sysSmsService = sysSmsService;
|
|
|
}
|
|
|
|
|
|
[AllowAnonymous]
|
|
|
[HttpPost("sendSmsCode")]
|
|
|
public Task SendSmsCode(string phone)
|
|
|
{
|
|
|
return _sysSmsService.SendSms(phone);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 短信模板 ID、签名、通道切换要同步实施说明
|
|
|
- 验证码时效变更要同步前端倒计时
|
|
|
- 自定义短信接口成功判定规则变更要先联调验证
|
|
|
|
|
|
### 17. 微信对接示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleWechatFacade.cs
|
|
|
public class ExampleWechatFacade : IDynamicApiController
|
|
|
{
|
|
|
private readonly SysWechatService _sysWechatService;
|
|
|
|
|
|
public ExampleWechatFacade(SysWechatService sysWechatService)
|
|
|
{
|
|
|
_sysWechatService = sysWechatService;
|
|
|
}
|
|
|
|
|
|
[AllowAnonymous]
|
|
|
[HttpGet("genAuthUrl")]
|
|
|
public string GenAuthUrl(string redirectUrl)
|
|
|
{
|
|
|
return _sysWechatService.GenAuthUrl(new GenAuthUrlInput { RedirectUrl = redirectUrl, Scope = "snsapi_userinfo" });
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 公众号、小程序、企业微信培训内容必须分开
|
|
|
- 支付和回调地址调整要做完整联调
|
|
|
- OpenId 映射策略变更要评估存量用户兼容
|
|
|
|
|
|
### 18. 多租户 SAAS示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleTenantFacade.cs
|
|
|
public class ExampleTenantFacade : IDynamicApiController
|
|
|
{
|
|
|
private readonly SysTenantService _sysTenantService;
|
|
|
|
|
|
public ExampleTenantFacade(SysTenantService sysTenantService)
|
|
|
{
|
|
|
_sysTenantService = sysTenantService;
|
|
|
}
|
|
|
|
|
|
[HttpPost("switchTenant")]
|
|
|
public Task<LoginOutput> SwitchTenant(BaseIdInput input)
|
|
|
{
|
|
|
return _sysTenantService.ChangeTenant(input);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 租户模式调整会影响数据库、缓存、权限和文件逻辑
|
|
|
- 初始化策略改动要同步运维与实施流程
|
|
|
- 独立库模式变更前要准备迁移和回滚方案
|
|
|
|
|
|
### 19. 远程请求示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/Service/ExampleDingTalkFacade.cs
|
|
|
public class ExampleDingTalkFacade
|
|
|
{
|
|
|
private readonly IDingTalkApi _dingTalkApi;
|
|
|
|
|
|
public ExampleDingTalkFacade(IDingTalkApi dingTalkApi)
|
|
|
{
|
|
|
_dingTalkApi = dingTalkApi;
|
|
|
}
|
|
|
|
|
|
public Task<GetDingTalkTokenOutput> GetToken(string appKey, string appSecret)
|
|
|
{
|
|
|
return _dingTalkApi.GetDingTalkToken(appKey, appSecret);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 第三方接口版本变更要同步 DTO 和培训示例
|
|
|
- 插件是否默认启用变更要同步插件矩阵表
|
|
|
- 回调地址、密钥、域名变更要做环境区分
|
|
|
|
|
|
### 20. 消息队列示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/EventBus/ExampleEventPublisher.cs
|
|
|
public class ExampleEventPublisher
|
|
|
{
|
|
|
private readonly IEventPublisher _eventPublisher;
|
|
|
|
|
|
public ExampleEventPublisher(IEventPublisher eventPublisher)
|
|
|
{
|
|
|
_eventPublisher = eventPublisher;
|
|
|
}
|
|
|
|
|
|
public Task PublishOrderCreated(object payload)
|
|
|
{
|
|
|
return _eventPublisher.PublishAsync("example:order:created", payload);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 事件名不要随意改
|
|
|
- 事件源切 Redis 要同步监控和排障手册
|
|
|
- 高可靠事件需继续补偿机制和回放能力
|
|
|
|
|
|
### 21. 定时任务示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Job/ExampleJob.cs
|
|
|
public class ExampleJob : IJob
|
|
|
{
|
|
|
public Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
|
|
|
{
|
|
|
Console.WriteLine("example job running");
|
|
|
return Task.CompletedTask;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 作业频率调整要评估对业务峰谷的影响
|
|
|
- 动态作业上线要配权限和审计
|
|
|
- 培训时要区分调度器作业和业务日程
|
|
|
|
|
|
### 22. 令牌 Token示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleTokenFacade.cs
|
|
|
public class ExampleTokenFacade : IDynamicApiController
|
|
|
{
|
|
|
private readonly SysAuthService _sysAuthService;
|
|
|
|
|
|
public ExampleTokenFacade(SysAuthService sysAuthService)
|
|
|
{
|
|
|
_sysAuthService = sysAuthService;
|
|
|
}
|
|
|
|
|
|
[HttpGet("refreshToken")]
|
|
|
public Task<LoginOutput> RefreshToken(string accessToken)
|
|
|
{
|
|
|
return _sysAuthService.GetRefreshToken(accessToken);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- Token 时效调整要同步前端刷新机制
|
|
|
- 黑名单规则变更要同步缓存和培训说明
|
|
|
- Bearer 使用规范尽量长期稳定
|
|
|
|
|
|
### 23. 日志记录示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleLogFacade.cs
|
|
|
public class ExampleLogFacade
|
|
|
{
|
|
|
public void WriteBusinessLog()
|
|
|
{
|
|
|
var logger = App.GetRequiredService<ILoggerFactory>().CreateLogger(CommonConst.SysLogCategoryName);
|
|
|
logger.LogInformation("示例业务日志");
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 日志级别调整会影响成本和排障方式
|
|
|
- 差异日志开启前要确认敏感字段策略
|
|
|
- 培训时应明确业务日志和平台日志的区别
|
|
|
|
|
|
### 24. 代码生成示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"CodeGen": {
|
|
|
"EntityAssemblyNames": [ "Admin.NET.Core", "Admin.NET.Application" ],
|
|
|
"FrontRootPath": "Web",
|
|
|
"BackendApplicationNamespaces": [ "Admin.NET.Application" ]
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 代码生成模板路径和命名空间规则变更会影响后续所有新模块
|
|
|
- 字段同步前建议备份历史配置
|
|
|
- 培训资料中的生成流程一旦成型,尽量少改顺序
|
|
|
|
|
|
### 25. 可视化大屏示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Plugins/Admin.NET.Plugin.GoView/Service/ExampleGoViewFacade.cs
|
|
|
public class ExampleGoViewFacade : IDynamicApiController
|
|
|
{
|
|
|
private readonly GoViewProService _goViewProService;
|
|
|
|
|
|
public ExampleGoViewFacade(GoViewProService goViewProService)
|
|
|
{
|
|
|
_goViewProService = goViewProService;
|
|
|
}
|
|
|
|
|
|
[HttpGet("projectList")]
|
|
|
public Task<List<GoViewProItemOutput>> ProjectList(int page = 1, int limit = 12)
|
|
|
{
|
|
|
return _goViewProService.GetList(page, limit);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 大屏项目结构调整要同步前端模板
|
|
|
- 预览图和背景图策略变更要考虑历史项目兼容
|
|
|
- 统计口径变化要同步现场培训资料
|
|
|
|
|
|
### 26. OpenAPI示例
|
|
|
|
|
|
#### 最小示例代码片段
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Application/OpenApi/ExampleOpenApi.cs
|
|
|
[ApiDescriptionSettings("开放接口", Name = "Example", Order = 200)]
|
|
|
[Authorize(AuthenticationSchemes = SignatureAuthenticationDefaults.AuthenticationScheme)]
|
|
|
public class ExampleOpenApi : IDynamicApiController
|
|
|
{
|
|
|
[HttpGet("status")]
|
|
|
public string Status()
|
|
|
{
|
|
|
return "ok";
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 变更注意事项
|
|
|
|
|
|
- 开放接口路径、签名规则、返回结构尽量保持长期稳定
|
|
|
- 凭据绑定关系变更要先评估对接系统影响
|
|
|
- 对外接口文档更新要同步通知外部对接方
|
|
|
|
|
|
## 附录十四:章节培训导航表
|
|
|
|
|
|
这张表用于培训、交接和新人自学时快速跳转:
|
|
|
|
|
|
- 想先理解原理:看“主体章节”
|
|
|
- 想查坑位:看“发布版补充”
|
|
|
- 想直接照着写:看“最小示例”
|
|
|
- 想配合图理解:看“附录八~十一”
|
|
|
|
|
|
| 章节 | 主体章节 | 发布版补充 | 最小示例 | 推荐联读图表/附录 |
|
|
|
| --- | --- | --- | --- | --- |
|
|
|
| 1. 框架简介 | 第一章 | 附录六 第1节 | 附录十三 第1节 | 附录八 总体架构图 |
|
|
|
| 2. 开发流程 | 第二章 | 附录六 第2节 | 附录十三 第2节 | `6. 零基础快速入门`、`7. 新建业务模块完整示例` |
|
|
|
| 3. 数据库配置 | 第三章 | 附录六 第3节 | 附录十三 第3节 | 附录八 核心能力归属图、附录十一 租户隔离模型 |
|
|
|
| 4. 实体基类 | 第四章 | 附录六 第4节 | 附录十三 第4节 | `7. 新建业务模块完整示例` |
|
|
|
| 5. 缓存管理 | 第五章 | 附录六 第5节 | 附录十三 第5节 | 附录八 核心能力归属图 |
|
|
|
| 6. 导入导出 | 第六章 | 附录六 第6节 | 附录十三 第6节 | `7. 新建业务模块完整示例` |
|
|
|
| 7. 上传下载 | 第七章 | 附录六 第7节 | 附录十三 第7节 | 附录九 文件上传链路图 |
|
|
|
| 8. 模板打印 | 第八章 | 附录六 第8节 | 附录十三 第8节 | 附录八 核心能力归属图 |
|
|
|
| 9. 统一认证 | 第九章 | 附录六 第9节 | 附录十三 第9节 | 附录九 后台普通请求链路图 |
|
|
|
| 10. 数据权限 | 第十章 | 附录六 第10节 | 附录十三 第10节 | 附录十 角色与权限关系图、附录十一 过滤关系图 |
|
|
|
| 11. 即时通讯 | 第十一章 | 附录六 第11节 | 附录十三 第11节 | 附录八 总体架构图 |
|
|
|
| 12. 图片压缩 | 第十二章 | 附录六 第12节 | 附录十三 第12节 | 第七章 文件体系一起看 |
|
|
|
| 13. 接口限流 | 第十三章 | 附录六 第13节 | 附录十三 第13节 | 附录九 后台普通请求链路图 |
|
|
|
| 14. 国密信创 | 第十四章 | 附录六 第14节 | 附录十三 第14节 | 第九章 统一认证、第三章 数据库配置 |
|
|
|
| 15. 邮件发送 | 第十五章 | 附录六 第15节 | 附录十三 第15节 | 第八章 模板打印一起看 |
|
|
|
| 16. 短信发送 | 第十六章 | 附录六 第16节 | 附录十三 第16节 | 第十三章 接口限流一起看 |
|
|
|
| 17. 微信对接 | 第十七章 | 附录六 第17节 | 附录十三 第17节 | 第十九章 远程请求、附录十二 插件矩阵 |
|
|
|
| 18. 多租户 SAAS | 第十八章 | 附录六 第18节 | 附录十三 第18节 | 附录十一 全部图 |
|
|
|
| 19. 远程请求 | 第十九章 | 附录六 第19节 | 附录十三 第19节 | 附录十二 插件启用矩阵表 |
|
|
|
| 20. 消息队列 | 第二十章 | 附录六 第20节 | 附录十三 第20节 | 附录九 请求链路图 |
|
|
|
| 21. 定时任务 | 第二十一章 | 附录六 第21节 | 附录十三 第21节 | 附录八 总体架构图 |
|
|
|
| 22. 令牌 Token | 第二十二章 | 附录六 第22节 | 附录十三 第22节 | 第九章 统一认证、附录九 请求链路图 |
|
|
|
| 23. 日志记录 | 第二十三章 | 附录六 第23节 | 附录十三 第23节 | 附录八 核心能力归属图 |
|
|
|
| 24. 代码生成 | 第二十四章 | 附录六 第24节 | 附录十三 第24节 | `7. 新建业务模块完整示例` |
|
|
|
| 25. 可视化大屏 | 第二十五章 | 附录六 第25节 | 附录十三 第25节 | 附录十二 插件启用矩阵表 |
|
|
|
| 26. OpenAPI | 第二十六章 | 附录六 第26节 | 附录十三 第26节 | 附录九 开放接口请求链路图 |
|
|
|
|
|
|
## 附录十五:事务管理与高并发专栏
|
|
|
|
|
|
### 1. 当前脚手架已具备的事务能力
|
|
|
|
|
|
当前项目已经具备两种事务用法:
|
|
|
|
|
|
- 基于 Furion 的 `[UnitOfWork]` 特性事务
|
|
|
- 基于 `ISqlSugarClient.AsTenant().BeginTran()` 的手动事务
|
|
|
|
|
|
对应关键实现:
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarUnitOfWork.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs`
|
|
|
|
|
|
`SqlSugarUnitOfWork` 已经把 Furion 的工作单元与 SqlSugar 事务适配起来:
|
|
|
|
|
|
- `BeginTransaction()` -> `BeginTran()`
|
|
|
- `CommitTransaction()` -> `CommitTran()`
|
|
|
- `RollbackTransaction()` -> `RollbackTran()`
|
|
|
|
|
|
### 2. 单库事务推荐写法
|
|
|
|
|
|
#### 2.1 事务型 Service 示例
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleOrderService.cs
|
|
|
[ApiDescriptionSettings("示例模块", Name = "ExampleOrder", Order = 120)]
|
|
|
public class ExampleOrderService : IDynamicApiController, ITransient
|
|
|
{
|
|
|
private readonly SqlSugarRepository<ExampleOrder> _orderRep;
|
|
|
private readonly SqlSugarRepository<ExampleOrderDetail> _detailRep;
|
|
|
|
|
|
public ExampleOrderService(
|
|
|
SqlSugarRepository<ExampleOrder> orderRep,
|
|
|
SqlSugarRepository<ExampleOrderDetail> detailRep)
|
|
|
{
|
|
|
_orderRep = orderRep;
|
|
|
_detailRep = detailRep;
|
|
|
}
|
|
|
|
|
|
[UnitOfWork]
|
|
|
[HttpPost("saveOrder")]
|
|
|
public async Task SaveOrder([FromBody] SaveOrderInput input)
|
|
|
{
|
|
|
var order = input.Adapt<ExampleOrder>();
|
|
|
await _orderRep.InsertAsync(order);
|
|
|
|
|
|
foreach (var item in input.Details)
|
|
|
{
|
|
|
var detail = item.Adapt<ExampleOrderDetail>();
|
|
|
detail.OrderId = order.Id;
|
|
|
await _detailRep.InsertAsync(detail);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 2.2 适用场景
|
|
|
|
|
|
- 单据主子表保存
|
|
|
- 库存主表和流水表同时写入
|
|
|
- 工单和工序任务一起落库
|
|
|
- 质检单和不合格品明细一起保存
|
|
|
|
|
|
### 3. 手动事务推荐写法
|
|
|
|
|
|
当你需要更细粒度控制时,可使用手动事务:
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleStockService.cs
|
|
|
public class ExampleStockService
|
|
|
{
|
|
|
private readonly ISqlSugarClient _db;
|
|
|
|
|
|
public ExampleStockService(ISqlSugarClient db)
|
|
|
{
|
|
|
_db = db;
|
|
|
}
|
|
|
|
|
|
public async Task DoBizAsync()
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
_db.AsTenant().BeginTran();
|
|
|
|
|
|
// 业务操作 1
|
|
|
// 业务操作 2
|
|
|
// 业务操作 3
|
|
|
|
|
|
_db.AsTenant().CommitTran();
|
|
|
}
|
|
|
catch
|
|
|
{
|
|
|
_db.AsTenant().RollbackTran();
|
|
|
throw;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 4. 多库事务说明
|
|
|
|
|
|
当前脚手架已具备:
|
|
|
|
|
|
- 主库
|
|
|
- 日志库
|
|
|
- 租户独立库
|
|
|
|
|
|
但从当前代码看,事务适配核心仍然基于 `ISqlSugarClient.AsTenant()`,适合单进程内同类数据库连接的事务控制。
|
|
|
|
|
|
对于以下场景,当前文档建议不要误判为“已经具备完整分布式事务能力”:
|
|
|
|
|
|
- 跨主库和日志库强一致提交
|
|
|
- 跨微服务事务
|
|
|
- 跨消息系统和数据库的强一致事务
|
|
|
|
|
|
### 5. 当前推荐的一致性方案
|
|
|
|
|
|
如果跨多个资源,建议优先采用:
|
|
|
|
|
|
- 主业务事务内只提交核心数据
|
|
|
- 日志、通知、同步动作走事件总线异步化
|
|
|
- 外部系统同步采用“最终一致性 + 重试 + 补偿”
|
|
|
|
|
|
这也是当前脚手架更自然的工程方式。
|
|
|
|
|
|
### 6. 并发防重推荐写法
|
|
|
|
|
|
针对同一工单、同一入库单被重复点击提交,推荐使用 `SysCacheService.BeginCacheLock()`:
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleSubmitService.cs
|
|
|
public class ExampleSubmitService : IDynamicApiController, ITransient
|
|
|
{
|
|
|
private readonly SysCacheService _sysCacheService;
|
|
|
|
|
|
public ExampleSubmitService(SysCacheService sysCacheService)
|
|
|
{
|
|
|
_sysCacheService = sysCacheService;
|
|
|
}
|
|
|
|
|
|
[HttpPost("submitOrder")]
|
|
|
public Task SubmitOrder([FromBody] BaseIdInput input)
|
|
|
{
|
|
|
using var cacheLock = _sysCacheService.BeginCacheLock($"lock:submit:order:{input.Id}", 500, 10000, true);
|
|
|
if (cacheLock == null)
|
|
|
throw Oops.Oh("单据正在处理中,请勿重复提交");
|
|
|
|
|
|
// 这里执行真正的提交逻辑
|
|
|
return Task.CompletedTask;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 7. 常见问题
|
|
|
|
|
|
- `[UnitOfWork]` 标了但事务没生效
|
|
|
- 事务里写了日志库或外部服务,出现部分成功、部分失败
|
|
|
- 用户重复点击导致重复入库、重复发起审批
|
|
|
|
|
|
### 8. 排错建议
|
|
|
|
|
|
- 检查方法是否真的通过 IoC 调用,而不是类内自调用
|
|
|
- 检查事务方法里是否混入了外部 HTTP 调用
|
|
|
- 检查并发场景是否使用了缓存锁或幂等键
|
|
|
- 检查多租户场景中事务是否都在同一连接作用域
|
|
|
|
|
|
### 9. 变更注意事项
|
|
|
|
|
|
- 核心事务逻辑变更前要先补并发用例
|
|
|
- `[UnitOfWork]` 使用范围扩大会影响异常回滚行为
|
|
|
- 引入外部服务调用进入事务前,要先评估是否改为事件驱动
|
|
|
|
|
|
## 附录十六:异常处理与统一返回落地指南
|
|
|
|
|
|
### 1. 当前脚手架的异常主线
|
|
|
|
|
|
当前项目的统一异常与返回链路已经比较完整:
|
|
|
|
|
|
- 业务方法中通过 `Oops.Oh(...)` 抛业务异常
|
|
|
- `AdminResultProvider` 统一包装成功、异常、校验失败、401/403
|
|
|
- `LoggingSetup`、异常日志服务和 SqlSugar AOP 负责记录运行信息
|
|
|
|
|
|
关键文件:
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Core/Utils/AdminResultProvider.cs`
|
|
|
- `Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs`
|
|
|
- `Admin.NET/Admin.NET.Web.Core/Startup.cs`
|
|
|
|
|
|
### 2. 业务抛错规范
|
|
|
|
|
|
#### 2.1 推荐写法
|
|
|
|
|
|
不要写:
|
|
|
|
|
|
```csharp
|
|
|
return false;
|
|
|
```
|
|
|
|
|
|
也不要写:
|
|
|
|
|
|
```csharp
|
|
|
return "工单状态不合法";
|
|
|
```
|
|
|
|
|
|
推荐统一使用:
|
|
|
|
|
|
```csharp
|
|
|
throw Oops.Oh("工单状态不合法");
|
|
|
```
|
|
|
|
|
|
或:
|
|
|
|
|
|
```csharp
|
|
|
throw Oops.Oh(ErrorCodeEnum.D3005);
|
|
|
```
|
|
|
|
|
|
#### 2.2 业务校验示例
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Core/Service/Example/ExampleWorkOrderService.cs
|
|
|
public class ExampleWorkOrderService : IDynamicApiController, ITransient
|
|
|
{
|
|
|
[HttpPost("complete")]
|
|
|
public Task Complete([FromBody] CompleteWorkOrderInput input)
|
|
|
{
|
|
|
if (input == null || input.Id <= 0)
|
|
|
throw Oops.Oh("工单参数不能为空");
|
|
|
|
|
|
if (input.Status != 2)
|
|
|
throw Oops.Oh("当前工单不是可完工状态");
|
|
|
|
|
|
return Task.CompletedTask;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 3. 状态码规约建议
|
|
|
|
|
|
当前统一返回结构里的 `Code` 本质上是状态码承载位,建议团队内形成最小规约:
|
|
|
|
|
|
- 200:成功
|
|
|
- 400:参数校验或业务前置条件失败
|
|
|
- 401:未登录、登录过期、签名认证失败
|
|
|
- 403:无权限
|
|
|
- 429:限流
|
|
|
- 500:系统异常
|
|
|
|
|
|
如果业务侧还需要更细粒度编码,建议:
|
|
|
|
|
|
- 对外给前端仍保持统一 HTTP 语义
|
|
|
- 细粒度业务错误通过 `ErrorCodeEnum` 或 `Message` 承载
|
|
|
|
|
|
### 4. 全局异常捕获验证
|
|
|
|
|
|
当前一旦抛出异常:
|
|
|
|
|
|
1. 中间件链或统一返回管道捕获异常
|
|
|
2. `AdminResultProvider.OnException()` 输出标准结果
|
|
|
3. 若启用监控日志,则进入日志体系
|
|
|
4. SQL 异常也会通过 `SqlSugarSetup.OnError` 记录
|
|
|
|
|
|
### 5. 前端收到的标准格式
|
|
|
|
|
|
典型统一返回结构:
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"code": 400,
|
|
|
"type": "error",
|
|
|
"message": "工单状态不合法",
|
|
|
"result": null,
|
|
|
"extras": null,
|
|
|
"time": "2026-03-15 10:00:00"
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 6. 常见问题
|
|
|
|
|
|
- 业务方法抛了异常,但前端收到非统一格式
|
|
|
- 401、403、302 的返回和业务异常不一致
|
|
|
- 某些接口用了 `NonUnify`,导致前端处理异常困难
|
|
|
|
|
|
### 7. 排错建议
|
|
|
|
|
|
- 检查接口是否被 `NonUnify` 标记绕过统一返回
|
|
|
- 检查异常是业务异常还是原生未处理异常
|
|
|
- 检查 Swagger / 开放接口 / 文件下载这类特殊接口是否有自定义返回策略
|
|
|
|
|
|
### 8. 变更注意事项
|
|
|
|
|
|
- 不要随意改 `AdminResultProvider` 的返回结构
|
|
|
- 错误码规约调整要同步前端、测试和实施文档
|
|
|
- 引入新的异常类型前要确认是否能被统一返回正确承接
|
|
|
|
|
|
## 附录十七:单元测试与接口测试模板
|
|
|
|
|
|
### 1. 当前测试项目现状
|
|
|
|
|
|
当前仓库已有:
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Test/Admin.NET.Test.csproj`
|
|
|
- `Furion.Xunit`
|
|
|
- `xunit`
|
|
|
- Selenium WebDriver
|
|
|
|
|
|
现有测试更偏:
|
|
|
|
|
|
- 工具类测试
|
|
|
- 部分 UI 自动化测试
|
|
|
|
|
|
从当前代码看,**完整的 Service 级业务单测模板还不充分**,这正是后续建议补齐的部分。
|
|
|
|
|
|
### 2. 现有测试文件
|
|
|
|
|
|
- `Admin.NET/Admin.NET.Test/BaseTest.cs`
|
|
|
- `Admin.NET/Admin.NET.Test/User/UserTest.cs`
|
|
|
- `Admin.NET/Admin.NET.Test/Utils/DateTimeUtilTests.cs`
|
|
|
- `Admin.NET/Admin.NET.Test/Utils/SafeMathTests.cs`
|
|
|
|
|
|
### 3. Service 测试推荐模板
|
|
|
|
|
|
下面给出一个适合后续扩展的 Service 测试骨架示例:
|
|
|
|
|
|
```csharp
|
|
|
// 文件:Admin.NET/Admin.NET.Test/Example/ExampleMaterialServiceTests.cs
|
|
|
using Xunit;
|
|
|
|
|
|
namespace Admin.NET.Test.Example;
|
|
|
|
|
|
public class ExampleMaterialServiceTests
|
|
|
{
|
|
|
[Fact]
|
|
|
public async Task Page_Should_Return_Result()
|
|
|
{
|
|
|
// Arrange
|
|
|
var input = new ExampleMaterialInput
|
|
|
{
|
|
|
Page = 1,
|
|
|
PageSize = 10,
|
|
|
Keyword = "MAT"
|
|
|
};
|
|
|
|
|
|
// Act
|
|
|
// 这里建议后续在测试基类中统一构建 ServiceProvider,再解析真实 Service
|
|
|
await Task.CompletedTask;
|
|
|
|
|
|
// Assert
|
|
|
Assert.True(input.Page == 1);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 4. 数据库测试建议
|
|
|
|
|
|
当前文档建议按这两种方式二选一:
|
|
|
|
|
|
- 连测试库
|
|
|
- 使用轻量 Sqlite 测试库
|
|
|
|
|
|
对制造业核心业务,建议优先连独立测试库,因为:
|
|
|
|
|
|
- 可以更贴近真实 SQL 和索引行为
|
|
|
- 可以验证事务和并发
|
|
|
- 可以验证租户过滤和数据权限
|
|
|
|
|
|
如果只是工具类或简单服务逻辑,可先用轻量测试方式。
|
|
|
|
|
|
### 5. Mock 外部请求建议
|
|
|
|
|
|
对于钉钉、企业微信、K3Cloud 等外部依赖,不建议单测直接请求真实接口。
|
|
|
|
|
|
建议做法:
|
|
|
|
|
|
- 抽离业务服务和外部代理接口
|
|
|
- 在测试里替换代理接口的实现
|
|
|
- 只验证业务编排逻辑
|
|
|
|
|
|
伪代码示例:
|
|
|
|
|
|
```csharp
|
|
|
public class FakeDingTalkApi : IDingTalkApi
|
|
|
{
|
|
|
public Task<GetDingTalkTokenOutput> GetDingTalkToken(string appkey, string appsecret)
|
|
|
{
|
|
|
return Task.FromResult(new GetDingTalkTokenOutput
|
|
|
{
|
|
|
AccessToken = "fake-token",
|
|
|
ErrCode = 0
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 其它接口按测试需要继续补假实现
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 6. UI 测试说明
|
|
|
|
|
|
当前 `BaseTest` 和 `UserTest` 使用 Selenium + EdgeDriver,适合:
|
|
|
|
|
|
- 验证登录
|
|
|
- 验证用户管理页面
|
|
|
- 做简单页面回归
|
|
|
|
|
|
但它不是 Service 单测替代品。
|
|
|
|
|
|
### 7. 常见问题
|
|
|
|
|
|
- `dotnet test` 能跑,但业务逻辑没有真正被断言
|
|
|
- UI 测试依赖本地环境,稳定性有限
|
|
|
- 外部系统联调导致测试不稳定
|
|
|
|
|
|
### 8. 变更注意事项
|
|
|
|
|
|
- 核心库存、工单、质检逻辑变更必须补测试
|
|
|
- 引入外部依赖到测试中前,要先区分是集成测试还是单元测试
|
|
|
- 不要把 Selenium UI 测试当成全部测试体系
|
|
|
|
|
|
## 附录十八:生产环境发布与部署清单
|
|
|
|
|
|
### 1. 生产环境安全阻断清单
|
|
|
|
|
|
生产环境至少应确认以下配置:
|
|
|
|
|
|
- `EnableInitDb = false`
|
|
|
- `EnableInitTable = false`
|
|
|
- `EnableInitSeed = false`
|
|
|
- `EnableInitView = false`
|
|
|
- `EnableConsoleSql = false`
|
|
|
- Swagger 生产开关按需关闭
|
|
|
- 测试账号和默认密码清理或强制修改
|
|
|
|
|
|
### 2. 当前仓库的 docker 目录
|
|
|
|
|
|
当前仓库已经提供:
|
|
|
|
|
|
- `docker/docker-compose.yml`
|
|
|
- `docker/docker-compose-builder.yml`
|
|
|
- `docker/README.md`
|
|
|
- `docker/nginx/conf/nginx.conf`
|
|
|
- `docker/app/Configuration/*`
|
|
|
|
|
|
说明当前项目已经有基础容器化部署样板。
|
|
|
|
|
|
### 3. Nginx 代理关键点
|
|
|
|
|
|
当前 `docker/nginx/conf/nginx.conf` 已给出关键代理配置:
|
|
|
|
|
|
- `/prod-api/` 反向代理到后端
|
|
|
- `/prod-api/hubs` 额外配置了 WebSocket 升级
|
|
|
- 已透传:
|
|
|
- `X-Real-IP`
|
|
|
- `X-Forwarded-For`
|
|
|
|
|
|
这对下面两类能力非常关键:
|
|
|
|
|
|
- SignalR
|
|
|
- 接口限流与真实 IP 获取
|
|
|
|
|
|
### 4. SignalR / WebSocket 配置提醒
|
|
|
|
|
|
如果前面有 Nginx 或网关,必须保留类似配置:
|
|
|
|
|
|
```nginx
|
|
|
location /prod-api/hubs {
|
|
|
proxy_pass http://adminNet:5005/hubs;
|
|
|
proxy_http_version 1.1;
|
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
|
proxy_set_header Connection "upgrade";
|
|
|
}
|
|
|
```
|
|
|
|
|
|
否则:
|
|
|
|
|
|
- 实时通知可能失效
|
|
|
- 在线用户功能可能异常
|
|
|
|
|
|
### 5. Dockerfile 建议模板
|
|
|
|
|
|
当前仓库主要基于 docker-compose 构建。若后续需要单独维护后端镜像,可参考精简模板:
|
|
|
|
|
|
```dockerfile
|
|
|
# 请按项目真实目标框架替换 sdk/runtime 镜像标签
|
|
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
|
|
WORKDIR /src
|
|
|
COPY . .
|
|
|
RUN dotnet publish Admin.NET/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj -c Release -o /app/publish
|
|
|
|
|
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0
|
|
|
WORKDIR /app
|
|
|
ENV TZ=Asia/Shanghai
|
|
|
COPY --from=build /app/publish .
|
|
|
ENTRYPOINT ["dotnet", "Admin.NET.Web.Entry.dll"]
|
|
|
```
|
|
|
|
|
|
### 6. 生产检查清单
|
|
|
|
|
|
上线前建议逐项核对:
|
|
|
|
|
|
1. 数据库初始化开关是否关闭
|
|
|
2. Swagger 是否符合生产策略
|
|
|
3. Redis 是否启用并验证通过
|
|
|
4. 真实 IP 头是否透传
|
|
|
5. SignalR WebSocket 是否可用
|
|
|
6. 连接串、密钥、短信、邮件配置是否使用生产参数
|
|
|
7. 默认管理员密码是否变更
|
|
|
8. 日志目录、磁盘空间、ES 索引策略是否确认
|
|
|
|
|
|
### 7. 常见问题
|
|
|
|
|
|
- 线上获取到的永远是 `127.0.0.1`
|
|
|
- WebSocket 连接被网关吃掉
|
|
|
- 生产环境误开建表
|
|
|
- 容器时区不对导致时间错乱
|
|
|
|
|
|
### 8. 变更注意事项
|
|
|
|
|
|
- 发布链路改动要同步实施和运维手册
|
|
|
- 代理层变更会影响限流、日志 IP、SignalR 三条链路
|
|
|
- 生产配置和开发配置必须物理隔离
|
|
|
|
|
|
## 附录十九:高频性能瓶颈排查指南
|
|
|
|
|
|
### 1. 慢 SQL 排查
|
|
|
|
|
|
当前项目已在 `SqlSugarSetup.SetDbAop()` 中挂了慢 SQL 记录逻辑:
|
|
|
|
|
|
- 当 SQL 执行时间超过 5 秒
|
|
|
- 会记录文件名、行号、方法名和原生 SQL
|
|
|
|
|
|
这意味着慢 SQL 的第一排查入口不是业务猜测,而是:
|
|
|
|
|
|
- 查看慢 SQL 日志
|
|
|
- 定位文件、方法和执行语句
|
|
|
|
|
|
### 2. 常见 SQL 性能问题
|
|
|
|
|
|
最常见的几类问题:
|
|
|
|
|
|
- N+1 查询
|
|
|
- 大表无条件分页
|
|
|
- 模糊查询未走索引
|
|
|
- 联表字段和过滤字段未建索引
|
|
|
- 报表导出未限制数据量
|
|
|
|
|
|
### 3. 如何快速定位 N+1 问题
|
|
|
|
|
|
建议看两个地方:
|
|
|
|
|
|
- 某个接口是否循环内反复查库
|
|
|
- 慢 SQL 日志是否出现同模板语句短时间重复执行很多次
|
|
|
|
|
|
排查顺序:
|
|
|
|
|
|
1. 看业务 Service
|
|
|
2. 看仓储调用次数
|
|
|
3. 看是否能合并查询、预加载或批量查询
|
|
|
|
|
|
### 4. 内存激增排查
|
|
|
|
|
|
后端内存激增常见原因:
|
|
|
|
|
|
- 导出超大 Excel
|
|
|
- 查询全表不分页
|
|
|
- 文件或图片大对象长期驻留内存
|
|
|
- 大批量日志对象 JSON 化
|
|
|
|
|
|
特别提醒:
|
|
|
|
|
|
- 第六章导入导出
|
|
|
- 第七章文件上传下载
|
|
|
|
|
|
这两章最容易出现大对象内存占用问题。
|
|
|
|
|
|
### 5. 分页与导出边界建议
|
|
|
|
|
|
- 页面查询必须分页
|
|
|
- 后台导出必须限制最大记录数
|
|
|
- 报表类接口建议异步生成文件
|
|
|
- 大批量统计建议落中间结果表或缓存快照
|
|
|
|
|
|
### 6. 当前 Trace 能力说明
|
|
|
|
|
|
从当前仓库代码看,已经有:
|
|
|
|
|
|
- 统一日志分类
|
|
|
- SQL 日志
|
|
|
- 统一返回
|
|
|
- 反向代理头透传
|
|
|
|
|
|
但**尚未确认已完整集成**以下任一全链路追踪方案:
|
|
|
|
|
|
- SkyWalking
|
|
|
- OpenTelemetry
|
|
|
- Jaeger
|
|
|
- Zipkin
|
|
|
|
|
|
因此当前建议写法是:
|
|
|
|
|
|
- 先利用日志、SQL AOP、统一请求入口做手动链路排查
|
|
|
- 如后续接入 TraceId 体系,可把网关、后端、SQL、日志串起来
|
|
|
|
|
|
### 7. 高并发热点排查建议
|
|
|
|
|
|
重点关注:
|
|
|
|
|
|
- 登录接口
|
|
|
- 短信发送接口
|
|
|
- 文件上传接口
|
|
|
- 开放接口签名认证入口
|
|
|
- 单据提交和库存扣减接口
|
|
|
|
|
|
这些接口建议同时检查:
|
|
|
|
|
|
- 限流
|
|
|
- 缓存锁
|
|
|
- 事务粒度
|
|
|
- SQL 索引
|
|
|
- 幂等控制
|
|
|
|
|
|
### 8. 常见问题
|
|
|
|
|
|
- SQL 看着不复杂但接口就是慢
|
|
|
- 导出时服务器内存飙升
|
|
|
- 多节点后性能下降明显
|
|
|
- 外部系统同步拖慢主流程
|
|
|
|
|
|
### 9. 变更注意事项
|
|
|
|
|
|
- 核心查询改写前要先保留慢 SQL 对比基线
|
|
|
- 大批量导出策略调整要同步培训和运维说明
|
|
|
- 如后续引入全链路追踪,要同步更新日志规范和排障手册
|