You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 KiB

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
    • 示例业务层与开放接口示例
    • 包含 ConfigurationOpenApi
  • 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.csProjectOptions.cs
  • 涉及插件能力时,优先放入插件自己的 Startup.cs

6. 零基础快速入门

这一节不讲抽象概念,只讲一个刚接手项目的人,如何从 0 到 1 把后端跑起来。

6.1 第一步:先改数据库配置

找到:

  • Admin.NET/Admin.NET.Application/Configuration/Database.json

最小可运行配置通常先用本地 Sqlite,例如:

{
  "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 第二步:先跑后端

在项目根目录执行:

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. 页面或接口调试入口

最小实体示例:

// 文件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; }
}

最小服务示例:

// 文件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 会按请求路由去匹配按钮权限
  • 所以你的接口命名和菜单权限命名要保持一致的规则

最小认知示例:

接口路由:/api/exampleMaterial/page
对应按钮权限exampleMaterial:page

如果接口存在,但当前用户没有这个按钮权限,就会被 JwtHandler 拦截。

6.7 第七步:再上代码生成器

建议先手写跑通一个最小模块,再去用代码生成器。

原因是很多新人一开始直接用生成器,但不知道生成出来的:

  • 实体该放哪里
  • DTO 为什么这样命名
  • 菜单按钮为什么这么生成
  • 接口权限为什么是这套规则

先理解后再生成,后续二次收敛会轻松很多。

7. 新建业务模块完整示例

这一节给出一个更接近实际开发的“物料主数据”最小链路,适合做培训和交接时演示。

7.1 场景目标

目标是新增一个“物料主数据”模块,至少具备:

  • 物料分页查询
  • 新增物料
  • 编辑物料
  • 删除物料
  • 菜单权限可控

7.2 第一步:新增实体

// 文件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

// 文件Admin.NET/Admin.NET.Core/Service/Example/Dto/ExampleMaterialInput.cs
public class ExampleMaterialInput : BasePageInput
{
    public string Keyword { get; set; }
}

7.4 第三步:新增 Service

// 文件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. 阅读 StartupProjectOptionsSqlSugarSetup
  2. 确认功能是否已有系统服务可复用
  3. 补配置文件与 Options 绑定
  4. 建实体并选择合适基类
  5. 建服务并实现 IDynamicApiController
  6. 复用 SqlSugarRepository<T>SysCacheService 等门面
  7. 补日志、权限、租户、导入导出等周边能力
  8. 编译验证与必要测试

2.2 常用命令

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 使用方式

  • 普通系统表:继承 EntityBaseEntityBaseDel
  • 需要按机构做数据权限:继承 EntityBaseOrgEntityBaseOrgDel
  • 需要多租户隔离:继承 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 SysPrintServiceSysTemplateService 的差异

二者不要混淆:

  • 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没有先确认是否已有封装
  • 只开发接口,不补字典、权限、日志和导入导出

排错建议

  • 新模块开发前,先搜索是否已有同类系统服务
  • 如果某能力看似缺失,先查 ServiceUtilsExtensionPlugins
  • 如果改动涉及全局行为,先确认是否应进 StartupProjectOptions

代码定位路径

  • 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.jsonEnableInitDb/EnableInitTable/EnableInitSeed/EnableInitView
  • 检查实体是否带 TenantAttributeSysTableAttributeLogTableAttribute
  • 检查连接串加密配置键是否与 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. 实体基类发布版补充

常见问题

  • 新增业务表后租户字段不自动写入
  • 审计字段为空
  • 软删除逻辑不生效
  • 数据权限过滤不生效

排错建议

  • 检查是否继承了正确基类
  • 检查实体是否真的包含 TenantIdOrgIdIsDelete
  • 检查 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 切换后部分功能异常

排错建议

  • 检查当前 CacheTypeMemory 还是 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.jsonOSSProviderSSHProviderMultiOSS
  • 检查 SysFileProviderService 的默认提供者配置
  • 检查文件记录中的 BucketNameUrlFilePath

代码定位路径

  • 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.EnabledSignalR.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.jsonEnableEndpointRateLimiting
  • 检查 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 登录成功但无法映射到业务用户
  • 微信支付回调到了但订单状态没更新

排错建议

  • 先区分是 SysWechatServiceSysWechatPayService 还是 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. 总体架构图

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. 分层职责图

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. 核心能力归属图

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. 后台普通请求链路

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. 开放接口请求链路

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. 文件上传链路

flowchart LR
    A["客户端上传文件"] --> B["SysFileService"]
    B --> C["校验文件名/大小/类型/后缀/MD5"]
    C --> D["选择FileProvider"]
    D --> E["本地 / OSS / SSH / MultiOSS"]
    E --> F["保存SysFile元数据"]
    F --> G["返回文件URL/Id/路径信息"]

附录十:角色与权限关系图

1. 角色权限主关系

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. 权限判定简图

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. 租户隔离模型图

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. 租户请求与过滤器关系图

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. 租户初始化图

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. 框架简介示例

最小示例代码片段

// 文件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. 开发流程示例

最小示例代码片段

// 文件Admin.NET/Admin.NET.Web.Core/ProjectOptions.cs
public static IServiceCollection AddProjectOptions(this IServiceCollection services)
{
    services.AddConfigurableOptions<ExampleOptions>();
    return services;
}

变更注意事项

  • 新增配置类时必须同步注册 Options 绑定
  • 公共流程改动前先确认是否影响已有插件和现有业务模块
  • 培训资料中的开发顺序一旦确定,尽量不要频繁调整

3. 数据库配置示例

最小示例代码片段

{
  "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. 实体基类示例

最小示例代码片段

// 文件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. 缓存管理示例

最小示例代码片段

// 文件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. 导入导出示例

最小示例代码片段

// 文件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. 上传下载示例

最小示例代码片段

// 文件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. 模板打印示例

最小示例代码片段

// 文件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. 统一认证示例

最小示例代码片段

// 文件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. 数据权限示例

最小示例代码片段

// 文件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. 即时通讯示例

最小示例代码片段

// 文件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. 图片压缩示例

最小示例代码片段

// 文件Admin.NET/Admin.NET.Core/Service/Example/ExampleImageService.cs
public class ExampleImageService
{
    // 建议在此处继续封装统一图片压缩逻辑,
    // 不建议在各业务服务中散写处理代码。
}

变更注意事项

  • 该章节当前属于二开能力,不能按现成功能培训为“已完整支持”
  • 图片压缩上线后要评估原图兼容策略
  • 质量和尺寸参数必须可配置

13. 接口限流示例

最小示例代码片段

{
  "IpRateLimiting": {
    "EnableEndpointRateLimiting": true,
    "GeneralRules": [
      {
        "Endpoint": "*:/api/example/sendCode",
        "Period": "1m",
        "Limit": 5
      }
    ]
  }
}

变更注意事项

  • 限流阈值变更要同步测试和生产配置
  • 代理头配置变更要与网关一起发布
  • 开放接口限流规则调整要提前通知对接方

14. 国密信创示例

最小示例代码片段

{
  "Cryptogram": {
    "CryptoType": "SM2",
    "PublicKey": "your_public_key",
    "PrivateKey": "your_private_key"
  }
}

变更注意事项

  • 公私钥切换必须前后端同步
  • 算法调整前要评估历史数据兼容
  • 培训时要明确密钥和普通配置的权限边界

15. 邮件发送示例

最小示例代码片段

// 文件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. 短信发送示例

最小示例代码片段

// 文件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. 微信对接示例

最小示例代码片段

// 文件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示例

最小示例代码片段

// 文件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. 远程请求示例

最小示例代码片段

// 文件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. 消息队列示例

最小示例代码片段

// 文件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. 定时任务示例

最小示例代码片段

// 文件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示例

最小示例代码片段

// 文件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. 日志记录示例

最小示例代码片段

// 文件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. 代码生成示例

最小示例代码片段

{
  "CodeGen": {
    "EntityAssemblyNames": [ "Admin.NET.Core", "Admin.NET.Application" ],
    "FrontRootPath": "Web",
    "BackendApplicationNamespaces": [ "Admin.NET.Application" ]
  }
}

变更注意事项

  • 代码生成模板路径和命名空间规则变更会影响后续所有新模块
  • 字段同步前建议备份历史配置
  • 培训资料中的生成流程一旦成型,尽量少改顺序

25. 可视化大屏示例

最小示例代码片段

// 文件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示例

最小示例代码片段

// 文件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 示例

// 文件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. 手动事务推荐写法

当你需要更细粒度控制时,可使用手动事务:

// 文件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()

// 文件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 推荐写法

不要写:

return false;

也不要写:

return "工单状态不合法";

推荐统一使用:

throw Oops.Oh("工单状态不合法");

或:

throw Oops.Oh(ErrorCodeEnum.D3005);

2.2 业务校验示例

// 文件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 语义
  • 细粒度业务错误通过 ErrorCodeEnumMessage 承载

4. 全局异常捕获验证

当前一旦抛出异常:

  1. 中间件链或统一返回管道捕获异常
  2. AdminResultProvider.OnException() 输出标准结果
  3. 若启用监控日志,则进入日志体系
  4. SQL 异常也会通过 SqlSugarSetup.OnError 记录

5. 前端收到的标准格式

典型统一返回结构:

{
  "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 测试骨架示例:

// 文件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 等外部依赖,不建议单测直接请求真实接口。

建议做法:

  • 抽离业务服务和外部代理接口
  • 在测试里替换代理接口的实现
  • 只验证业务编排逻辑

伪代码示例:

public class FakeDingTalkApi : IDingTalkApi
{
    public Task<GetDingTalkTokenOutput> GetDingTalkToken(string appkey, string appsecret)
    {
        return Task.FromResult(new GetDingTalkTokenOutput
        {
            AccessToken = "fake-token",
            ErrCode = 0
        });
    }

    // 其它接口按测试需要继续补假实现
}

6. UI 测试说明

当前 BaseTestUserTest 使用 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 或网关,必须保留类似配置:

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 构建。若后续需要单独维护后端镜像,可参考精简模板:

# 请按项目真实目标框架替换 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 对比基线
  • 大批量导出策略调整要同步培训和运维说明
  • 如后续引入全链路追踪,要同步更新日志规范和排障手册