GitHunt
RA

rain7788/dotnet10-vue3-admin-clean-architecture

🚀 A high-performance Enterprise Admin Template based on .NET 10 (Preview) and Vue 3. Featuring Clean Architecture, RBAC, and solid infrastructure. / 基于 .NET 10 与 Vue 3 的高性能企业级后台管理模板,采用整洁架构。

Art Admin

art-design-pro 前端, NET 10 + Minimal API 后端,采用清洁架构设计,提供完整的权限管理、用户认证和 API 路由功能。

🌟 特性

  • 清洁架构 - 四层分离设计(Api / Core / Domain / Infra)
  • 自动依赖注入 - 通过 [Service] 特性自动注册服务
  • 自动路由注册 - 基于接口的路由自动发现与注册
  • 多端 API 支持 - 管理端、应用端、公共端三套独立 API,可以随意扩展
  • 雪花 ID - 支持 Redis 分布式 WorkerId 分配
  • Token 认证 - 引用令牌鉴权,支持多端独立认证
  • RBAC 权限 - 用户-角色-权限-菜单完整权限体系
  • MySQL + Redis - 数据持久化与缓存支持
  • Swagger UI - 自动生成 API 文档
  • Serilog 日志 - 按日分表写入 MySQL

🌐 在线演示

项目 地址
项目主页 https://www.aftbay.com
管理后台 https://admin.aftbay.com
Swagger API 文档 https://api.aftbay.com/swagger

演示账号:admin / 123456

演示环境已开启 Demo 模式,所有修改操作(新增、编辑、删除、修改密码等)会被拦截,不会实际写入数据库。

🎨 查看更多前端效果:如果想看完整的前端界面演示,请访问 https://www.artd.pro/

Demo 模式

项目内置了演示模式开关,适用于部署公开 Demo 站点。开启后,用户可以正常浏览和登录,但所有写操作会返回 403 演示环境,不允许修改数据 提示。

开启/关闭方式:修改 backend/Art.Api/appsettings.json

{
  "Settings": {
    "DemoMode": true   // true 开启演示模式,false 或删除此项则关闭
  }
}

💡 完全删除演示模式:如果不需要演示模式功能,可以删除 backend/Art.Infra/Framework/Middlewares/DemoModeMiddleware.cs 文件,并在 backend/Art.Api/Program.cs 中删除 app.UseMiddleware<DemoModeMiddleware>(); 这一行。

也可通过环境变量覆盖:Settings__DemoMode=true

📁 项目结构

backend/
├── Art.Api/              # API 层 - 路由定义、中间件配置
│   ├── Routes/           # 路由定义(Admin/App/Common)
│   ├── Hosting/          # 启动配置
│   └── Program.cs        # 应用入口
│
├── Art.Core/             # 核心业务层 - 业务逻辑实现
│   ├── Services/         # 业务服务
│   │   ├── Admin/        # 管理端服务
│   │   └── App/          # 应用端服务
│   └── Workers/          # 后台任务
│
├── Art.Domain/           # 领域层 - 实体、枚举、常量
│   ├── Entities/         # 数据实体
│   ├── Enums/            # 枚举定义
│   ├── Constants/        # 常量定义
│   ├── Models/           # 数据模型
│   └── Exceptions/       # 异常定义
│
└── Art.Infra/            # 基础设施层 - 数据访问、缓存、工具
    ├── Data/             # EF Core DbContext
    ├── Cache/            # Redis 封装
    ├── Common/           # 通用工具(密码、雪花ID等)
    ├── Framework/        # 框架核心
    │   ├── Routes/       # 路由扩展
    │   ├── Middlewares/  # 中间件
    │   └── Jobs/         # 任务调度
    ├── Logging/          # 日志扩展
    └── MultiTenancy/     # 多租户支持

🛠️ 技术栈

技术 版本 说明
.NET 10.0 运行时框架
ASP.NET Core 10.0 Web 框架
Entity Framework Core 9.0 ORM
Pomelo.EntityFrameworkCore.MySql 9.0 MySQL 驱动
FreeRedis 1.5.5 Redis 客户端
Serilog 4.3.0 结构化日志
Yitter.IdGenerator 1.0.14 雪花 ID 生成
Swashbuckle 10.1.0 Swagger 文档
Flurl.Http 4.0.2 HTTP 客户端

🚀 快速开始

环境要求

  • .NET 10 SDK
  • MySQL 8.0+
  • Redis (可选,用于分布式 WorkerId)

配置

编辑 backend/Art.Api/appsettings.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;port=3306;Database=sea;User=root;Password=yourpassword;max pool size=100;",
    "Redis": "localhost,password=yourpassword,defaultDatabase=10"
  },
  "Settings": {
    "TokenExpireHours": 168
  }
}

数据库初始化

# 进入数据库目录,执行 SQL 脚本
cd database
# 按顺序执行 schemas/ 和 migrations/ 目录下的 SQL 文件
# 可选:执行 seeds/ 目录下的初始数据

运行

cd backend/Art.Api
dotnet run

访问 Swagger UI: http://localhost:5000/swagger

Docker 部署

后端

cd backend

# 构建镜像
docker build -t art-api .

# 运行(默认生产环境,读取 appsettings.Production.json)
docker run -d -p 5000:8080 art-api

# 切换到开发环境(读取 appsettings.Development.json)
docker run -d -p 5000:8080 -e ASPNETCORE_ENVIRONMENT=Development art-api

💡 配置建议:不同环境的数据库、Redis 等配置请在对应的 appsettings.{Environment}.json 中维护,通过 ASPNETCORE_ENVIRONMENT 环境变量切换,而非在命令行传递连接字符串。

前端

cd web-admin

# 构建镜像
docker build -t art-admin .

# 运行(通过环境变量指定 API 地址)
docker run -d -p 80:80 -e VITE_API_URL="https://api.example.com" art-admin
环境变量 说明 示例
ASPNETCORE_ENVIRONMENT 后端运行环境 Production / Development
VITE_API_URL 前端 API 地址 https://api.example.com

📖 核心功能

自动依赖注入

使用 [Service] 特性标记服务类,自动注册到 DI 容器:

[Service(ServiceLifetime.Scoped)]
public class UserService
{
    // 自动注入到 DI 容器
}

路由定义

实现 IAdminRouterBaseIAppRouterBaseICommonRouterBase 接口,路由自动注册:

public class UserRouter : IAdminRouterBase
{
    public void AddRoutes(RouteGroupBuilder group)
    {
        group.MapGet("/users", GetUsers);
        group.MapPost("/users", CreateUser);
    }
}

API 分组

  • /admin/* - 管理端 API(需要平台端 Token)
  • /app/* - 应用端 API(需要客户端 Token)
  • /common/* - 公共 API(无需鉴权)

雪花 ID

// 生成雪花 ID
var id = SnowflakeIdGenerator.NextId();

支持 Redis 自动分配 WorkerId,适合集群部署。

后台任务

框架内置了功能完善的后台任务调度器,支持两种任务类型:

1. 定时任务(Recurring Task)

适用于周期性执行的任务,如日志清理、数据统计等。

// 在 TaskConfiguration.cs 中配置
public void ConfigureTasks(ITaskScheduler taskScheduler)
{
    taskScheduler.AddRecurringTask(
        _dailyWorker.ClearLogs,              // 任务方法
        TimeSpan.FromMinutes(21),            // 检查间隔
        allowedHours: [2, 3],                // 仅在 2-3 点执行
        preventDuplicateInterval: TimeSpan.FromHours(12),  // 12小时内不重复
        useDistributedLock: true);           // 集群防重
}

2. 长任务(Long Running Task)

适用于需要持续运行的任务,如实时数据处理、WebSocket 推送等。

taskScheduler.AddLongRunningTask(
    _worker.ProcessMessages,             // 任务方法
    TimeSpan.FromSeconds(1),             // 每隔多久尝试进入一轮“运行窗口”(会参与去重/抢锁)
    processingInterval: TimeSpan.FromMilliseconds(100),  // 每 100ms 处理一批
    runDuration: TimeSpan.FromMinutes(1) // 单次运行时长,结束后所有pod去争夺下一轮任务执行权,如果关闭分布式锁则多个pod可以同时执行。
);

核心特性

  • 分布式锁 - 基于 Redis 的分布式锁,防止集群环境下任务重复执行
  • 优雅退出 - 应用关闭时等待任务完成当前业务闭环(最多 10 秒)
  • 时段控制 - 支持限制任务在特定时段执行(如凌晨维护窗口)
  • 防重保护 - 支持配置任务在指定时间内不重复执行
  • 自动恢复 - 任务失败会记录日志并在下个周期自动重试

实现 Worker

[Service(ServiceLifetime.Transient)]
public class DailyWorker
{
    public async Task ClearLogs(CancellationToken cancel)
    {
        try
        {
            // 业务逻辑
            await Task.Delay(TimeSpan.FromSeconds(5), cancel);
        }
        catch (OperationCanceledException)
        {
            // 优雅退出时会触发此异常
        }
    }
}

最佳实践:

  • Worker 必须标记 [Service(ServiceLifetime.Transient)],每次执行创建新实例
  • 任务方法中关键业务操作要使用 CancellationToken,支持优雅中断
  • 避免在 Worker 中注入 RequestContext(无用户上下文)

优雅退出

框架实现了完善的优雅退出机制,确保应用关闭时不丢失正在处理的任务:

工作原理

public async Task StopAsync(CancellationToken cancellationToken)
{
    _cts.Cancel();  // 发送取消信号

    // 等待所有任务完成,最多 10 秒
    var allTasks = Task.WhenAll(_runningTasks);
    var completed = await Task.WhenAny(
        allTasks,
        Task.Delay(TimeSpan.FromSeconds(10))
    );

    if (completed == allTasks)
        _logger.LogInformation("所有任务已正常停止");
    else
        _logger.LogWarning("任务停止超时,强制退出");
}

执行流程

  1. 接收停止信号 - Docker 发送 SIGTERM 或用户 Ctrl+C
  2. 取消任务循环 - 通知所有后台任务停止等待下一轮
  3. 等待任务完成 - 给正在执行的任务 10 秒时间完成当前业务
  4. 释放资源 - 关闭 Redis 连接、刷新日志缓冲区
// Program.cs 中的资源清理
app.Lifetime.ApplicationStopped.Register(() =>
{
    Redis.Dispose();      // 关闭 Redis 连接
    Log.CloseAndFlush();  // 刷新日志到数据库
});

任务中的优雅退出

public async Task ProcessData(CancellationToken cancel)
{
    while (!cancel.IsCancellationRequested)  // 检查取消信号
    {
        try
        {
            // 处理数据
            await Task.Delay(TimeSpan.FromSeconds(5), cancel);
        }
        catch (OperationCanceledException)
        {
            _logger.LogWarning("任务被取消,正在清理...");
            // 清理资源、保存状态
            return;
        }
    }
}

Docker 部署建议:

  • Docker 默认给 10 秒优雅关闭时间,与框架的 10 秒等待时间对齐
  • 如果任务可能超过 10 秒,在 docker-compose.yml 中增加 stop_grace_period
    services:
      api:
        stop_grace_period: 30s # 给任务 30 秒完成时间

🎨 前端

前端使用 Art Admin v3.0.1,一个基于 Vue 3 的现代化后台管理模板(源网站:ARTD.pro)。

📚 文档地址: https://www.artd.pro/docs

🤔 为什么不用微服务?

Art Admin 采用模块化单体架构,而非微服务,原因如下:

  1. 快速开发优先 - 本框架的设计目标是快速构建应用,在业务爆发前,单体架构能显著降低开发和运维复杂度
  2. 多端鉴权已内置 - 已支持管理端、应用端、公共端三套独立 API 和认证体系,满足绝大多数业务场景
  3. 清洁架构易拆分 - 四层分离设计使得未来拆分微服务成本极低,只需按 Domain 边界拆分即可
  4. 避免过早优化 - 在业务验证阶段,微服务的网络延迟、分布式事务、运维成本等问题往往得不偿失

如果业务确实需要微服务,建议:

  • Art.Core/Services 下的模块边界拆分
  • 每个服务独立部署,共享 DomainInfra
  • 引入 API Gateway 统一入口

📝 License

MIT License

🤝 贡献

欢迎提交 Issue 和 Pull Request!


如有问题或建议,请提交 Issue 或联系作者。