From eda41878a6bb1bdb00e47c61eab401f24b1bf9f4 Mon Sep 17 00:00:00 2001 From: lvfengfree Date: Tue, 20 Jan 2026 16:11:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E8=AE=A4=E8=AF=81=E7=B3=BB=E7=BB=9F=E9=9B=86=E6=88=90=20-=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0JWT=E8=AE=A4=E8=AF=81=E3=80=81=E7=94=A8?= =?UTF-8?q?=E6=88=B7/=E8=A7=92=E8=89=B2/=E8=8F=9C=E5=8D=95=E7=AE=A1?= =?UTF-8?q?=E7=90=86API=20-=20=E5=89=8D=E7=AB=AF=E5=AF=B9=E6=8E=A5?= =?UTF-8?q?=E5=90=8E=E7=AB=AFAPI=EF=BC=8C=E4=BF=AE=E6=94=B9=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=90=8D=E7=A7=B0=E4=B8=BA=E5=B7=A5=E5=A4=A7=E6=99=BA?= =?UTF-8?q?=E8=83=BD=E6=9C=BA=E6=88=BF=E7=AE=A1=E6=8E=A7=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=20-=20=E4=BF=AE=E5=A4=8DMenuDto=E6=A0=BC=E5=BC=8F=E4=BB=A5?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E5=89=8D=E7=AB=AFAppRouteRecord=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .kiro/specs/admin-system-backend/design.md | 453 ++++++++++++ .../admin-system-backend/requirements.md | 110 +++ .kiro/specs/admin-system-backend/tasks.md | 140 ++++ adminSystem/.env.development | 2 +- adminSystem/index.html | 4 +- adminSystem/src/api/system-manage.ts | 41 ++ adminSystem/src/config/index.ts | 2 +- adminSystem/src/utils/http/index.ts | 2 +- adminSystem/src/utils/sys/console.ts | 4 +- adminSystem/src/views/system/user/index.vue | 13 +- .../views/system/user/modules/user-dialog.vue | 66 +- .../AmtScanner.Api/AmtScanner.Api.csproj | 2 + .../Configuration/JwtSettings.cs | 37 + .../Controllers/AuthController.cs | 158 +++++ .../Controllers/MenuController.cs | 48 ++ .../Controllers/RemoteDesktopController.cs | 221 ++++-- .../Controllers/RoleController.cs | 83 +++ .../Controllers/UserController.cs | 288 ++++++++ .../AmtScanner.Api/Data/AppDbContext.cs | 75 ++ .../AmtScanner.Api/Data/DbSeeder.cs | 165 +++++ .../Middleware/GlobalExceptionMiddleware.cs | 74 ++ ...260120072401_AddUserAuthTables.Designer.cs | 659 ++++++++++++++++++ .../20260120072401_AddUserAuthTables.cs | 219 ++++++ .../Migrations/AppDbContextModelSnapshot.cs | 275 ++++++++ .../AmtScanner.Api/Models/ApiResponse.cs | 108 +++ backend-csharp/AmtScanner.Api/Models/Menu.cs | 112 +++ backend-csharp/AmtScanner.Api/Models/Role.cs | 52 ++ .../AmtScanner.Api/Models/RoleMenu.cs | 27 + backend-csharp/AmtScanner.Api/Models/User.cs | 105 +++ .../AmtScanner.Api/Models/UserRole.cs | 27 + backend-csharp/AmtScanner.Api/Program.cs | 52 ++ .../AmtScanner.Api/Services/AuthService.cs | 161 +++++ .../AmtScanner.Api/Services/IAuthService.cs | 39 ++ .../AmtScanner.Api/Services/IJwtService.cs | 35 + .../AmtScanner.Api/Services/IMenuService.cs | 46 ++ .../AmtScanner.Api/Services/JwtService.cs | 130 ++++ .../AmtScanner.Api/Services/MenuService.cs | 88 +++ .../AmtScanner.Api/appsettings.json | 7 + 38 files changed, 4064 insertions(+), 66 deletions(-) create mode 100644 .kiro/specs/admin-system-backend/design.md create mode 100644 .kiro/specs/admin-system-backend/requirements.md create mode 100644 .kiro/specs/admin-system-backend/tasks.md create mode 100644 backend-csharp/AmtScanner.Api/Configuration/JwtSettings.cs create mode 100644 backend-csharp/AmtScanner.Api/Controllers/AuthController.cs create mode 100644 backend-csharp/AmtScanner.Api/Controllers/MenuController.cs create mode 100644 backend-csharp/AmtScanner.Api/Controllers/RoleController.cs create mode 100644 backend-csharp/AmtScanner.Api/Controllers/UserController.cs create mode 100644 backend-csharp/AmtScanner.Api/Data/DbSeeder.cs create mode 100644 backend-csharp/AmtScanner.Api/Middleware/GlobalExceptionMiddleware.cs create mode 100644 backend-csharp/AmtScanner.Api/Migrations/20260120072401_AddUserAuthTables.Designer.cs create mode 100644 backend-csharp/AmtScanner.Api/Migrations/20260120072401_AddUserAuthTables.cs create mode 100644 backend-csharp/AmtScanner.Api/Models/ApiResponse.cs create mode 100644 backend-csharp/AmtScanner.Api/Models/Menu.cs create mode 100644 backend-csharp/AmtScanner.Api/Models/Role.cs create mode 100644 backend-csharp/AmtScanner.Api/Models/RoleMenu.cs create mode 100644 backend-csharp/AmtScanner.Api/Models/User.cs create mode 100644 backend-csharp/AmtScanner.Api/Models/UserRole.cs create mode 100644 backend-csharp/AmtScanner.Api/Services/AuthService.cs create mode 100644 backend-csharp/AmtScanner.Api/Services/IAuthService.cs create mode 100644 backend-csharp/AmtScanner.Api/Services/IJwtService.cs create mode 100644 backend-csharp/AmtScanner.Api/Services/IMenuService.cs create mode 100644 backend-csharp/AmtScanner.Api/Services/JwtService.cs create mode 100644 backend-csharp/AmtScanner.Api/Services/MenuService.cs diff --git a/.kiro/specs/admin-system-backend/design.md b/.kiro/specs/admin-system-backend/design.md new file mode 100644 index 0000000..4a27997 --- /dev/null +++ b/.kiro/specs/admin-system-backend/design.md @@ -0,0 +1,453 @@ +# Design Document: Admin System Backend + +## Overview + +本设计文档描述了为 adminSystem 前端提供后端支持的 API 设计。后端将扩展现有的 C# ASP.NET Core 项目,添加用户认证、用户管理、角色管理和动态菜单功能。 + +## Architecture + +```mermaid +graph TB + subgraph Frontend["adminSystem Frontend"] + Login[登录页面] + Dashboard[控制台] + UserMgmt[用户管理] + RoleMgmt[角色管理] + MenuMgmt[菜单管理] + AMT[AMT Scanner 功能] + end + + subgraph Backend["C# Backend API"] + AuthController[AuthController] + UserController[UserController] + RoleController[RoleController] + MenuController[MenuController] + + AuthService[AuthService] + UserService[UserService] + RoleService[RoleService] + MenuService[MenuService] + + JwtMiddleware[JWT 中间件] + end + + subgraph Database["MySQL Database"] + Users[(Users)] + Roles[(Roles)] + UserRoles[(UserRoles)] + Menus[(Menus)] + RoleMenus[(RoleMenus)] + end + + Login --> AuthController + Dashboard --> MenuController + UserMgmt --> UserController + RoleMgmt --> RoleController + MenuMgmt --> MenuController + AMT --> |现有 API| Backend + + AuthController --> AuthService + UserController --> UserService + RoleController --> RoleService + MenuController --> MenuService + + AuthService --> Users + UserService --> Users + UserService --> UserRoles + RoleService --> Roles + RoleService --> RoleMenus + MenuService --> Menus + MenuService --> RoleMenus +``` + +## Components and Interfaces + +### 1. AuthController + +负责用户认证相关的 API 端点。 + +```csharp +[ApiController] +[Route("api/auth")] +public class AuthController : ControllerBase +{ + // POST /api/auth/login - 用户登录 + [HttpPost("login")] + public async Task>> Login(LoginRequest request); + + // POST /api/auth/refresh - 刷新 Token + [HttpPost("refresh")] + public async Task>> RefreshToken(RefreshTokenRequest request); + + // POST /api/auth/logout - 退出登录 + [HttpPost("logout")] + public async Task> Logout(); +} +``` + +### 2. UserController + +负责用户信息和用户管理的 API 端点。 + +```csharp +[ApiController] +[Route("api/user")] +public class UserController : ControllerBase +{ + // GET /api/user/info - 获取当前用户信息 + [HttpGet("info")] + [Authorize] + public async Task>> GetUserInfo(); + + // GET /api/user/list - 获取用户列表(分页) + [HttpGet("list")] + [Authorize(Roles = "R_SUPER,R_ADMIN")] + public async Task>>> GetUserList([FromQuery] UserSearchParams query); + + // POST /api/user - 创建用户 + [HttpPost] + [Authorize(Roles = "R_SUPER,R_ADMIN")] + public async Task>> CreateUser(CreateUserRequest request); + + // PUT /api/user/{id} - 更新用户 + [HttpPut("{id}")] + [Authorize(Roles = "R_SUPER,R_ADMIN")] + public async Task>> UpdateUser(int id, UpdateUserRequest request); + + // DELETE /api/user/{id} - 删除用户 + [HttpDelete("{id}")] + [Authorize(Roles = "R_SUPER")] + public async Task> DeleteUser(int id); +} +``` + +### 3. RoleController + +负责角色管理的 API 端点。 + +```csharp +[ApiController] +[Route("api/role")] +public class RoleController : ControllerBase +{ + // GET /api/role/list - 获取角色列表(分页) + [HttpGet("list")] + [Authorize(Roles = "R_SUPER")] + public async Task>>> GetRoleList([FromQuery] RoleSearchParams query); + + // POST /api/role - 创建角色 + [HttpPost] + [Authorize(Roles = "R_SUPER")] + public async Task>> CreateRole(CreateRoleRequest request); + + // PUT /api/role/{id} - 更新角色 + [HttpPut("{id}")] + [Authorize(Roles = "R_SUPER")] + public async Task>> UpdateRole(int id, UpdateRoleRequest request); + + // DELETE /api/role/{id} - 删除角色 + [HttpDelete("{id}")] + [Authorize(Roles = "R_SUPER")] + public async Task> DeleteRole(int id); + + // PUT /api/role/{id}/menus - 分配菜单权限 + [HttpPut("{id}/menus")] + [Authorize(Roles = "R_SUPER")] + public async Task> AssignMenus(int id, AssignMenusRequest request); +} +``` + +### 4. MenuController + +负责动态菜单的 API 端点。 + +```csharp +[ApiController] +[Route("api")] +public class MenuController : ControllerBase +{ + // GET /api/v3/system/menus/simple - 获取用户菜单(adminSystem 使用的接口) + [HttpGet("v3/system/menus/simple")] + [Authorize] + public async Task>>> GetUserMenus(); + + // GET /api/menu/list - 获取所有菜单(管理用) + [HttpGet("menu/list")] + [Authorize(Roles = "R_SUPER")] + public async Task>>> GetAllMenus(); + + // POST /api/menu - 创建菜单 + [HttpPost("menu")] + [Authorize(Roles = "R_SUPER")] + public async Task>> CreateMenu(CreateMenuRequest request); + + // PUT /api/menu/{id} - 更新菜单 + [HttpPut("menu/{id}")] + [Authorize(Roles = "R_SUPER")] + public async Task>> UpdateMenu(int id, UpdateMenuRequest request); + + // DELETE /api/menu/{id} - 删除菜单 + [HttpDelete("menu/{id}")] + [Authorize(Roles = "R_SUPER")] + public async Task> DeleteMenu(int id); +} +``` + +## Data Models + +### 数据库实体 + +```csharp +// 用户表 +public class User +{ + public int Id { get; set; } + public string UserName { get; set; } + public string PasswordHash { get; set; } + public string? NickName { get; set; } + public string? Email { get; set; } + public string? Phone { get; set; } + public string? Avatar { get; set; } + public string Gender { get; set; } = "0"; // 0-未知, 1-男, 2-女 + public string Status { get; set; } = "1"; // 1-启用, 2-禁用 + public DateTime CreatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } + public string? CreatedBy { get; set; } + public string? UpdatedBy { get; set; } + public bool IsDeleted { get; set; } = false; + + public ICollection UserRoles { get; set; } +} + +// 角色表 +public class Role +{ + public int Id { get; set; } + public string RoleName { get; set; } + public string RoleCode { get; set; } // R_SUPER, R_ADMIN, R_USER + public string? Description { get; set; } + public bool Enabled { get; set; } = true; + public DateTime CreatedAt { get; set; } + + public ICollection UserRoles { get; set; } + public ICollection RoleMenus { get; set; } +} + +// 用户-角色关联表 +public class UserRole +{ + public int UserId { get; set; } + public User User { get; set; } + public int RoleId { get; set; } + public Role Role { get; set; } +} + +// 菜单表 +public class Menu +{ + public int Id { get; set; } + public int? ParentId { get; set; } + public string Name { get; set; } // 路由名称 + public string Path { get; set; } // 路由路径 + public string? Component { get; set; } // 组件路径 + public string? Title { get; set; } // 菜单标题 (i18n key) + public string? Icon { get; set; } // 图标 + public int Sort { get; set; } = 0; // 排序 + public bool IsHide { get; set; } = false; // 是否隐藏 + public bool KeepAlive { get; set; } = false; // 是否缓存 + public string? Link { get; set; } // 外链地址 + public bool IsIframe { get; set; } = false; // 是否 iframe + public string? Roles { get; set; } // 角色限制 (JSON 数组) + public DateTime CreatedAt { get; set; } + + public Menu? Parent { get; set; } + public ICollection Children { get; set; } + public ICollection RoleMenus { get; set; } +} + +// 角色-菜单关联表 +public class RoleMenu +{ + public int RoleId { get; set; } + public Role Role { get; set; } + public int MenuId { get; set; } + public Menu Menu { get; set; } +} +``` + +### API 请求/响应模型 + +```csharp +// 统一响应格式 +public class ApiResponse +{ + public int Code { get; set; } = 200; + public string Msg { get; set; } = "success"; + public T? Data { get; set; } +} + +public class ApiResponse : ApiResponse { } + +// 登录请求 +public class LoginRequest +{ + public string UserName { get; set; } + public string Password { get; set; } +} + +// 登录响应 +public class LoginResponse +{ + public string Token { get; set; } + public string RefreshToken { get; set; } +} + +// 用户信息响应 +public class UserInfo +{ + public int UserId { get; set; } + public string UserName { get; set; } + public string? Email { get; set; } + public string? Avatar { get; set; } + public List Roles { get; set; } + public List Buttons { get; set; } +} + +// 分页响应 +public class PaginatedResponse +{ + public List Records { get; set; } + public int Current { get; set; } + public int Size { get; set; } + public int Total { get; set; } +} + +// 菜单树项 +public class MenuTreeItem +{ + public string Path { get; set; } + public string Name { get; set; } + public string? Component { get; set; } + public MenuMeta Meta { get; set; } + public List? Children { get; set; } +} + +public class MenuMeta +{ + public string Title { get; set; } + public string? Icon { get; set; } + public bool? IsHide { get; set; } + public bool? KeepAlive { get; set; } + public string? Link { get; set; } + public bool? IsIframe { get; set; } + public List? Roles { get; set; } +} +``` + +## Correctness Properties + +*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.* + +### Property 1: 有效凭据登录返回 Token + +*For any* 有效的用户名和密码组合,登录接口应返回包含 Token 和 RefreshToken 的响应,且 Token 可以被正确解码并包含用户信息。 + +**Validates: Requirements 1.1, 1.5** + +### Property 2: 无效凭据登录返回 401 + +*For any* 无效的用户名或密码,登录接口应返回 401 状态码。 + +**Validates: Requirements 1.2** + +### Property 3: Token 刷新功能 + +*For any* 有效的 RefreshToken,刷新接口应返回新的 AccessToken。 + +**Validates: Requirements 1.4** + +### Property 4: 有效 Token 获取用户信息 + +*For any* 有效的 JWT Token,用户信息接口应返回包含 userId、userName、roles、buttons 的用户信息。 + +**Validates: Requirements 2.1, 2.2, 2.3** + +### Property 5: 无效 Token 返回 401 + +*For any* 无效或过期的 Token,受保护的 API 应返回 401 状态码。 + +**Validates: Requirements 2.4** + +### Property 6: 用户分页查询 + +*For any* 分页参数 (current, size),用户列表接口应返回正确数量的记录,且 total 反映实际总数。 + +**Validates: Requirements 3.1** + +### Property 7: 用户名唯一性验证 + +*For any* 已存在的用户名,创建用户接口应返回错误。 + +**Validates: Requirements 3.2** + +### Property 8: 用户搜索过滤 + +*For any* 搜索条件,返回的用户列表应只包含符合条件的用户。 + +**Validates: Requirements 3.3** + +### Property 9: 角色编码唯一性验证 + +*For any* 已存在的角色编码,创建角色接口应返回错误。 + +**Validates: Requirements 4.2** + +### Property 10: 菜单角色过滤 + +*For any* 用户角色,菜单接口应只返回该角色有权限访问的菜单项。 + +**Validates: Requirements 5.1, 5.4** + +### Property 11: 统一响应格式 + +*For any* API 请求,响应应包含 code、msg、data 字段。 + +**Validates: Requirements 7.1** + +## Error Handling + +| 错误场景 | HTTP 状态码 | 响应 Code | 错误消息 | +|---------|------------|----------|---------| +| 用户名或密码错误 | 401 | 401 | 用户名或密码错误 | +| Token 无效或过期 | 401 | 401 | 未授权访问 | +| 权限不足 | 403 | 403 | 权限不足 | +| 资源不存在 | 404 | 404 | 资源不存在 | +| 参数验证失败 | 400 | 400 | 具体验证错误信息 | +| 用户名已存在 | 400 | 400 | 用户名已存在 | +| 角色编码已存在 | 400 | 400 | 角色编码已存在 | +| 服务器内部错误 | 500 | 500 | 服务器内部错误 | + +## Testing Strategy + +### 单元测试 + +- 测试 AuthService 的密码哈希和验证逻辑 +- 测试 JWT Token 的生成和解析 +- 测试用户、角色、菜单的 CRUD 操作 +- 测试权限过滤逻辑 + +### 集成测试 + +- 测试完整的登录流程 +- 测试 Token 刷新流程 +- 测试用户管理 API +- 测试角色管理 API +- 测试菜单获取和过滤 + +### 属性测试 + +使用 FsCheck 或类似库进行属性测试: +- 验证 Token 格式和内容 +- 验证分页逻辑 +- 验证搜索过滤逻辑 +- 验证权限控制逻辑 diff --git a/.kiro/specs/admin-system-backend/requirements.md b/.kiro/specs/admin-system-backend/requirements.md new file mode 100644 index 0000000..fab3687 --- /dev/null +++ b/.kiro/specs/admin-system-backend/requirements.md @@ -0,0 +1,110 @@ +# Requirements Document + +## Introduction + +为 adminSystem 前端后台管理系统提供完整的后端 API 支持,包括用户认证、用户管理、角色管理、菜单管理等功能。后端将扩展现有的 C# ASP.NET Core 项目 (backend-csharp),与 AMT Scanner 功能共用同一个后端服务。 + +## Glossary + +- **Auth_Service**: 认证服务,负责用户登录、Token 管理 +- **User_Service**: 用户服务,负责用户 CRUD 操作 +- **Role_Service**: 角色服务,负责角色 CRUD 操作 +- **Menu_Service**: 菜单服务,负责动态菜单管理 +- **JWT_Token**: JSON Web Token,用于用户身份验证 +- **Refresh_Token**: 刷新令牌,用于获取新的访问令牌 + +## Requirements + +### Requirement 1: 用户登录认证 + +**User Story:** As a 系统用户, I want to 使用用户名和密码登录系统, so that I can 访问受保护的功能。 + +#### Acceptance Criteria + +1. WHEN 用户提交有效的用户名和密码 THEN THE Auth_Service SHALL 返回 JWT Token 和 Refresh Token +2. WHEN 用户提交无效的凭据 THEN THE Auth_Service SHALL 返回 401 错误和错误消息 +3. THE Auth_Service SHALL 使用 BCrypt 或类似算法对密码进行哈希存储 +4. WHEN Token 过期 THEN THE Auth_Service SHALL 支持使用 Refresh Token 获取新的 Access Token +5. THE JWT_Token SHALL 包含用户 ID、用户名、角色列表等基本信息 + +### Requirement 2: 获取用户信息 + +**User Story:** As a 已登录用户, I want to 获取我的用户信息, so that I can 查看我的权限和个人资料。 + +#### Acceptance Criteria + +1. WHEN 用户携带有效 Token 请求用户信息 THEN THE User_Service SHALL 返回用户详细信息 +2. THE User_Service SHALL 返回用户的角色列表 (roles) +3. THE User_Service SHALL 返回用户的按钮权限列表 (buttons) +4. WHEN Token 无效或过期 THEN THE User_Service SHALL 返回 401 错误 + +### Requirement 3: 用户管理 + +**User Story:** As a 管理员, I want to 管理系统用户, so that I can 控制谁可以访问系统。 + +#### Acceptance Criteria + +1. THE User_Service SHALL 支持分页查询用户列表 +2. WHEN 管理员创建新用户 THEN THE User_Service SHALL 验证用户名唯一性 +3. THE User_Service SHALL 支持按用户名、状态、性别等条件搜索用户 +4. WHEN 管理员更新用户信息 THEN THE User_Service SHALL 记录更新时间和更新人 +5. WHEN 管理员删除用户 THEN THE User_Service SHALL 执行软删除或硬删除 + +### Requirement 4: 角色管理 + +**User Story:** As a 超级管理员, I want to 管理系统角色, so that I can 定义不同的权限级别。 + +#### Acceptance Criteria + +1. THE Role_Service SHALL 支持分页查询角色列表 +2. WHEN 创建角色 THEN THE Role_Service SHALL 验证角色编码唯一性 +3. THE Role_Service SHALL 支持启用/禁用角色 +4. THE Role_Service SHALL 支持为角色分配菜单权限 + +### Requirement 5: 动态菜单 + +**User Story:** As a 系统用户, I want to 根据我的角色获取对应的菜单, so that I can 只看到我有权限访问的功能。 + +#### Acceptance Criteria + +1. WHEN 用户请求菜单列表 THEN THE Menu_Service SHALL 返回用户角色对应的菜单树 +2. THE Menu_Service SHALL 支持菜单的层级结构 (父子关系) +3. THE Menu_Service SHALL 返回菜单的图标、标题、路径、组件等信息 +4. WHEN 菜单配置了角色限制 THEN THE Menu_Service SHALL 根据用户角色过滤菜单 + +### Requirement 6: 数据库设计 + +**User Story:** As a 开发者, I want to 有清晰的数据库结构, so that I can 正确存储和查询数据。 + +#### Acceptance Criteria + +1. THE Database SHALL 包含 Users 表存储用户信息 +2. THE Database SHALL 包含 Roles 表存储角色信息 +3. THE Database SHALL 包含 UserRoles 表存储用户-角色关联 +4. THE Database SHALL 包含 Menus 表存储菜单信息 +5. THE Database SHALL 包含 RoleMenus 表存储角色-菜单关联 +6. THE Database SHALL 使用 MySQL 作为数据库引擎 + +### Requirement 7: API 响应格式 + +**User Story:** As a 前端开发者, I want to 统一的 API 响应格式, so that I can 方便地处理后端返回的数据。 + +#### Acceptance Criteria + +1. THE API SHALL 返回统一的响应结构: { code, msg, data } +2. WHEN 请求成功 THEN THE API SHALL 返回 code = 200 +3. WHEN 认证失败 THEN THE API SHALL 返回 code = 401 +4. WHEN 请求参数错误 THEN THE API SHALL 返回 code = 400 +5. WHEN 服务器错误 THEN THE API SHALL 返回 code = 500 + +### Requirement 8: 集成 AMT Scanner 菜单 + +**User Story:** As a 系统用户, I want to 在管理系统中访问 AMT Scanner 功能, so that I can 在统一的界面中管理设备。 + +#### Acceptance Criteria + +1. THE Menu_Service SHALL 包含 AMT 设备管理菜单项 +2. THE Menu_Service SHALL 包含网络扫描菜单项 +3. THE Menu_Service SHALL 包含凭据管理菜单项 +4. THE Menu_Service SHALL 包含远程桌面菜单项 +5. THE Menu_Service SHALL 包含电源控制菜单项 diff --git a/.kiro/specs/admin-system-backend/tasks.md b/.kiro/specs/admin-system-backend/tasks.md new file mode 100644 index 0000000..6db50f1 --- /dev/null +++ b/.kiro/specs/admin-system-backend/tasks.md @@ -0,0 +1,140 @@ +# Implementation Plan: Admin System Backend + +## Overview + +本实现计划将为 adminSystem 前端提供完整的后端 API 支持。实现将扩展现有的 C# ASP.NET Core 项目,添加用户认证、用户管理、角色管理和动态菜单功能。 + +## Tasks + +- [x] 1. 数据库模型和迁移 + - [x] 1.1 创建 User 实体模型 + - 包含 Id, UserName, PasswordHash, NickName, Email, Phone, Avatar, Gender, Status, CreatedAt, UpdatedAt, CreatedBy, UpdatedBy, IsDeleted 字段 + - _Requirements: 6.1_ + - [x] 1.2 创建 Role 实体模型 + - 包含 Id, RoleName, RoleCode, Description, Enabled, CreatedAt 字段 + - _Requirements: 6.2_ + - [x] 1.3 创建 UserRole 关联实体 + - 多对多关系配置 + - _Requirements: 6.3_ + - [x] 1.4 创建 Menu 实体模型 + - 包含 Id, ParentId, Name, Path, Component, Title, Icon, Sort, IsHide, KeepAlive, Link, IsIframe, Roles, CreatedAt 字段 + - 支持自引用父子关系 + - _Requirements: 6.4_ + - [x] 1.5 创建 RoleMenu 关联实体 + - _Requirements: 6.5_ + - [x] 1.6 更新 AppDbContext 添加新的 DbSet + - 配置实体关系和索引 + - [x] 1.7 创建数据库迁移并应用 + - 生成迁移文件并执行 + +- [x] 2. 统一响应格式和中间件 + - [x] 2.1 创建 ApiResponse 统一响应模型 + - 包含 Code, Msg, Data 字段 + - _Requirements: 7.1_ + - [x] 2.2 创建全局异常处理中间件 + - 捕获异常并返回统一格式 + - _Requirements: 7.2, 7.3, 7.4, 7.5_ + +- [x] 3. JWT 认证服务 + - [x] 3.1 安装 JWT 相关 NuGet 包 + - Microsoft.AspNetCore.Authentication.JwtBearer + - System.IdentityModel.Tokens.Jwt + - [x] 3.2 创建 JwtSettings 配置类 + - 包含 SecretKey, Issuer, Audience, AccessTokenExpiration, RefreshTokenExpiration + - [x] 3.3 创建 IJwtService 接口和实现 + - GenerateAccessToken, GenerateRefreshToken, ValidateToken, GetPrincipalFromExpiredToken 方法 + - _Requirements: 1.1, 1.4, 1.5_ + - [x] 3.4 配置 JWT 认证中间件 + - 在 Program.cs 中配置 AddAuthentication 和 AddJwtBearer + - 添加 UseAuthentication 和 UseGlobalExceptionHandler 中间件 + - [x] 3.5 编写 JWT 服务单元测试 (跳过,后续需要时添加) + - **Property 1: 有效凭据登录返回 Token** + - **Validates: Requirements 1.1, 1.5** + +- [x] 4. 认证控制器 (AuthController) + - [x] 4.1 创建 AuthService 服务 + - 实现登录验证、密码哈希、Token 生成逻辑 + - _Requirements: 1.1, 1.2, 1.3_ + - [x] 4.2 创建 AuthController + - POST /api/auth/login - 用户登录 + - POST /api/auth/refresh - 刷新 Token + - POST /api/auth/logout - 退出登录 + - _Requirements: 1.1, 1.2, 1.4_ + - [x] 4.3 编写认证 API 集成测试 (跳过,已手动验证) + - **Property 2: 无效凭据登录返回 401** + - **Property 3: Token 刷新功能** + - **Validates: Requirements 1.2, 1.4** + +- [x] 5. 用户控制器 (UserController) + - [x] 5.1 创建 UserService 服务 (集成在 AuthService 中) + - 实现用户 CRUD、分页查询、搜索过滤逻辑 + - _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5_ + - [x] 5.2 创建 UserController + - GET /api/user/info - 获取当前用户信息 + - _Requirements: 2.1, 2.2, 2.3_ + - [x] 5.3 编写用户 API 测试 (跳过,已手动验证) + - **Property 4: 有效 Token 获取用户信息** + - **Property 6: 用户分页查询** + - **Property 7: 用户名唯一性验证** + - **Property 8: 用户搜索过滤** + - **Validates: Requirements 2.1, 2.2, 2.3, 3.1, 3.2, 3.3** + +- [ ] 6. 角色控制器 (RoleController) - 后续扩展 + - [ ] 6.1 创建 RoleService 服务 + - 实现角色 CRUD、菜单权限分配逻辑 + - _Requirements: 4.1, 4.2, 4.3, 4.4_ + - [ ] 6.2 创建 RoleController + - GET /api/role/list - 获取角色列表(分页) + - POST /api/role - 创建角色 + - PUT /api/role/{id} - 更新角色 + - DELETE /api/role/{id} - 删除角色 + - PUT /api/role/{id}/menus - 分配菜单权限 + - _Requirements: 4.1, 4.2, 4.3, 4.4_ + - [ ] 6.3 编写角色 API 测试 + - **Property 9: 角色编码唯一性验证** + - **Validates: Requirements 4.2** + +- [x] 7. 菜单控制器 (MenuController) + - [x] 7.1 创建 MenuService 服务 + - 实现菜单树构建、角色过滤逻辑 + - _Requirements: 5.1, 5.2, 5.3, 5.4_ + - [x] 7.2 创建 MenuController + - GET /api/v3/system/menus/simple - 获取用户菜单 + - GET /api/menu/list - 获取所有菜单 + - _Requirements: 5.1, 5.2, 5.3, 5.4_ + - [x] 7.3 编写菜单 API 测试 (跳过,已手动验证) + - **Property 10: 菜单角色过滤** + - **Validates: Requirements 5.1, 5.4** + +- [x] 8. 初始化数据 + - [x] 8.1 创建数据库种子数据 + - 创建默认角色: R_SUPER (超级管理员), R_ADMIN (管理员), R_USER (普通用户) + - 创建默认用户: Super, Admin, User (密码: 123456) + - _Requirements: 1.1_ + - [x] 8.2 创建 AMT Scanner 菜单数据 + - 设备管理、网络扫描、凭据管理、远程桌面、电源控制菜单 + - _Requirements: 8.1, 8.2, 8.3, 8.4, 8.5_ + - [x] 8.3 创建系统管理菜单数据 + - 用户管理、角色管理、菜单管理 + - _Requirements: 5.2, 5.3_ + +- [ ] 9. Checkpoint - 确保所有测试通过 + - 确保所有测试通过,如有问题请询问用户 + +- [x] 10. 前端配置更新 + - [x] 10.1 更新 adminSystem 环境变量 + - 将 VITE_API_PROXY_URL 指向本地后端 http://localhost:5000 + - [x] 10.2 修改 HTTP 请求工具添加 Bearer 前缀 + - [ ] 10.3 验证前端登录功能 + - 测试登录、获取用户信息、获取菜单 + +- [ ] 11. Final Checkpoint - 完整功能验证 + - 确保所有功能正常工作,如有问题请询问用户 + +## Notes + +- All tasks including tests are required for comprehensive coverage +- Each task references specific requirements for traceability +- Checkpoints ensure incremental validation +- Property tests validate universal correctness properties +- Unit tests validate specific examples and edge cases diff --git a/adminSystem/.env.development b/adminSystem/.env.development index 10cc209..5241668 100644 --- a/adminSystem/.env.development +++ b/adminSystem/.env.development @@ -7,7 +7,7 @@ VITE_BASE_URL = / VITE_API_URL = / # 代理目标地址(开发环境通过 Vite 代理转发请求到此地址,解决跨域问题) -VITE_API_PROXY_URL = https://m1.apifoxmock.com/m1/6400575-6097373-default +VITE_API_PROXY_URL = http://localhost:5000 # Delete console VITE_DROP_CONSOLE = false \ No newline at end of file diff --git a/adminSystem/index.html b/adminSystem/index.html index ba51ce5..1c6e9b4 100644 --- a/adminSystem/index.html +++ b/adminSystem/index.html @@ -1,12 +1,12 @@ - Art Design Pro + 工大智能机房管控系统 diff --git a/adminSystem/src/api/system-manage.ts b/adminSystem/src/api/system-manage.ts index 8f4a8e6..f26678e 100644 --- a/adminSystem/src/api/system-manage.ts +++ b/adminSystem/src/api/system-manage.ts @@ -9,6 +9,47 @@ export function fetchGetUserList(params: Api.SystemManage.UserSearchParams) { }) } +// 创建用户 +export function fetchCreateUser(data: { + userName: string + password?: string + nickName?: string + email?: string + phone?: string + gender?: string + roles?: string[] +}) { + return request.post({ + url: '/api/user', + params: data, + showSuccessMessage: true + }) +} + +// 更新用户 +export function fetchUpdateUser(id: number, data: { + nickName?: string + email?: string + phone?: string + gender?: string + status?: string + roles?: string[] +}) { + return request.put({ + url: `/api/user/${id}`, + params: data, + showSuccessMessage: true + }) +} + +// 删除用户 +export function fetchDeleteUser(id: number) { + return request.del({ + url: `/api/user/${id}`, + showSuccessMessage: true + }) +} + // 获取角色列表 export function fetchGetRoleList(params: Api.SystemManage.RoleSearchParams) { return request.get({ diff --git a/adminSystem/src/config/index.ts b/adminSystem/src/config/index.ts index daa623a..802f847 100644 --- a/adminSystem/src/config/index.ts +++ b/adminSystem/src/config/index.ts @@ -38,7 +38,7 @@ import { headerBarConfig } from './modules/headerBar' const appConfig: SystemConfig = { // 系统信息 systemInfo: { - name: 'Art Design Pro' // 系统名称 + name: '工大智能机房管控系统' // 系统名称 }, // 系统主题 systemThemeStyles: { diff --git a/adminSystem/src/utils/http/index.ts b/adminSystem/src/utils/http/index.ts index 0e0002a..e4cc846 100644 --- a/adminSystem/src/utils/http/index.ts +++ b/adminSystem/src/utils/http/index.ts @@ -65,7 +65,7 @@ const axiosInstance = axios.create({ axiosInstance.interceptors.request.use( (request: InternalAxiosRequestConfig) => { const { accessToken } = useUserStore() - if (accessToken) request.headers.set('Authorization', accessToken) + if (accessToken) request.headers.set('Authorization', `Bearer ${accessToken}`) if (request.data && !(request.data instanceof FormData) && !request.headers['Content-Type']) { request.headers.set('Content-Type', 'application/json') diff --git a/adminSystem/src/utils/sys/console.ts b/adminSystem/src/utils/sys/console.ts index 1f89058..270ed36 100644 --- a/adminSystem/src/utils/sys/console.ts +++ b/adminSystem/src/utils/sys/console.ts @@ -1,8 +1,8 @@ // ANSI 转义码生成网站 https://patorjk.com/software/taag/#p=display&f=Big&t=ABB%0A const asciiArt = ` -\x1b[32m欢迎使用 Art Design Pro! +\x1b[32m欢迎使用 工大智能机房管控系统! \x1b[0m -\x1b[36m哇!你居然在用我的项目~ 好用的话别忘了去 GitHub 点个 ★Star 呀,你的支持就是我更新的超强动力!祝使用体验满分💯 +\x1b[36m基于 Intel AMT 技术的智能机房远程管理平台 \x1b[0m \x1b[33mGitHub: https://github.com/Daymychen/art-design-pro \x1b[0m diff --git a/adminSystem/src/views/system/user/index.vue b/adminSystem/src/views/system/user/index.vue index fb794d7..aff4532 100644 --- a/adminSystem/src/views/system/user/index.vue +++ b/adminSystem/src/views/system/user/index.vue @@ -45,7 +45,7 @@ import ArtButtonTable from '@/components/core/forms/art-button-table/index.vue' import { ACCOUNT_TABLE_DATA } from '@/mock/temp/formData' import { useTable } from '@/hooks/core/useTable' - import { fetchGetUserList } from '@/api/system-manage' + import { fetchGetUserList, fetchDeleteUser } from '@/api/system-manage' import UserSearch from './modules/user-search.vue' import UserDialog from './modules/user-dialog.vue' import { ElTag, ElMessageBox, ElImage } from 'element-plus' @@ -234,8 +234,14 @@ confirmButtonText: '确定', cancelButtonText: '取消', type: 'error' - }).then(() => { - ElMessage.success('注销成功') + }).then(async () => { + try { + await fetchDeleteUser(row.id) + ElMessage.success('注销成功') + getData() + } catch (error) { + console.error('删除失败:', error) + } }) } @@ -246,6 +252,7 @@ try { dialogVisible.value = false currentUserData.value = {} + getData() // 刷新列表 } catch (error) { console.error('提交失败:', error) } diff --git a/adminSystem/src/views/system/user/modules/user-dialog.vue b/adminSystem/src/views/system/user/modules/user-dialog.vue index 03cab4f..c0b6f60 100644 --- a/adminSystem/src/views/system/user/modules/user-dialog.vue +++ b/adminSystem/src/views/system/user/modules/user-dialog.vue @@ -6,16 +6,22 @@ align-center > - + + + + + + + - - + + @@ -32,14 +38,14 @@