一、概述
最近整的有点大,几乎将工作之外的时间均投入到本项目的开发之中,完全废寝忘食。因此也喜提腰酸脖子痛,看来得加强锻炼了。
回到主题,本文档以用户管理模块为例,向大家展示如何使用CodeSpirit框架快速构建企业级应用的核心功能。用户管理是几乎所有系统的基础模块,包含用户的增删改查、角色分配、状态管理等核心功能。
总体项目结构如下:
Src/
├── ApiServices/
│ ├── CodeSpirit.IdentityApi/ # 身份认证API
│ ├── CodeSpirit.OrderApi/ # 订单服务API
│ └── CodeSpirit.ConfigCenter/ # 配置中心
│ └── CodeSpirit.ConfigCenter.Client/ # 配置中心客户端
├── Components/
│ ├── CodeSpirit.Aggregator/ # 聚合器组件
│ ├── CodeSpirit.Amis/ # UI生成引擎
│ ├── CodeSpirit.Authorization/ # 权限组件
│ └── CodeSpirit.Navigation/ # 导航组件
├── CodeSpirit.AppHost/ # Aspire应用宿主
├── CodeSpirit.Core/ # 核心定义
├── CodeSpirit.ServiceDefaults/ # 服务默认配置
├── CodeSpirit.Shared/ # 共享库
├── CodeSpirit.Web/ # Web相关组件
└── Tests/
├── Components/
│ ├── CodeSpirit.Aggregator.Tests/
│ ├── CodeSpirit.Authorization.Tests/
│ └── CodeSpirit.Components.TestsBase/
├── ApiServices/
│ └── CodeSpirit.IdentityApi.Tests/
└── CodeSpirit.Tests/ # 通用测试项目结构后续进一步介绍,我们继续。
CodeSpirit采用分层架构,根据迭代不断调整结构,以用户管理模块为例,主要包含以下结构:
Src/
├── CodeSpirit.IdentityApi/ # 用户管理API项目
│ ├── Controllers/ # 控制器层
│ │ ├── UsersController.cs # 用户管理控制器
│ │ └── ...
│ ├── Services/ # 服务层
│ │ ├── IUserService.cs # 用户服务接口
│ │ ├── UserService.cs # 用户服务实现
│ │ └── ...
│ ├── Dtos/ # 数据传输对象
│ │ ├── User/
│ │ │ ├── CreateUserDto.cs # 创建用户DTO
│ │ │ ├── UserDto.cs # 用户信息DTO
│ │ │ ├── UpdateUserDto.cs # 更新用户DTO
│ │ │ └── ...
│ │ └── ...
│ ├── Data/ # 数据访问层
│ │ ├── Models/ # 数据模型
│ │ │ ├── ApplicationUser.cs # 用户实体
│ │ │ └── ...
│ │ └── ...
│ └── ...
└── ...首先,我们需要定义用户实体类:
// ApplicationUser.cs
public class ApplicationUser : IdentityUser<long>
{
[Required]
[MaxLength(20)]
[PersonalData]
public string Name { get; set; }
[MaxLength(18)]
[PersonalData]
public string IdNo { get; set; }
[PersonalData]
public string AvatarUrl { get; set; }
[PersonalData]
public Gender Gender { get; set; }
public bool IsActive { get; set; } = true;
public DateTimeOffset? LastLoginTime { get; set; }
}
public enum Gender
{
[Description("未知")]
Unknown = 0,
[Description("男")]
Male = 1,
[Description("女")]
Female = 2
}在CodeSpirit框架中,DTO不仅用于数据传输,还承担了UI生成的职责。通过特性标注,系统能够自动生成对应的表单和表格。
// UserQueryDto.cs
public class UserQueryDto : PagedRequest
{
[DisplayName("姓名")]
public string Name { get; set; }
[DisplayName("用户名")]
public string UserName { get; set; }
[DisplayName("电子邮箱")]
public string Email { get; set; }
[DisplayName("手机号码")]
public string PhoneNumber { get; set; }
[DisplayName("是否激活")]
public bool? IsActive { get; set; }
[DisplayName("创建时间范围")]
public DateTimeOffset[] CreatedRange { get; set; }
}
// CreateUserDto.cs
public class CreateUserDto
{
[Required]
[MaxLength(20)]
[DisplayName("姓名")]
public string Name { get; set; }
[Required]
[DisplayName("用户名")]
[MaxLength(256)]
[RegularExpression(@"^[a-zA-Z0-9_]+$", ErrorMessage = "用户名只能包含字母、数字和下划线。")]
[Description("用户名只能包含字母、数字和下划线。")]
public string UserName { get; set; }
[MaxLength(18)]
[DisplayName("身份证")]
[RegularExpression(@"^\d{15}|\d{18}$", ErrorMessage = "身份证号码格式不正确。")]
public string IdNo { get; set; }
[MaxLength(255)]
[DataType(DataType.ImageUrl)]
[AmisInputImageField(
Label = "头像",
Receiver = "${API_HOST}/api/identity/upload/avatar",
Accept = "image/png,image/jpeg",
MaxSize = 1048576, // 1MB
Multiple = false,
Required = true,
Placeholder = "请上传您的头像"
)]
public string AvatarUrl { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[DisplayName("分配角色")]
[AmisSelectField(
Source = "${API_HOST}/api/identity/Roles",
ValueField = "name",
LabelField = "name",
Multiple = true,
JoinValues = false,
ExtractValue = true,
Searchable = true,
Clearable = true,
Placeholder = "请选择角色"
)]
public List<string> Roles { get; set; }
[DisplayName("性别")]
public Gender Gender { get; set; }
[DisplayName("手机号码")]
[DataType(DataType.PhoneNumber)]
public string PhoneNumber { get; set; }
}
// UserDto.cs
public class UserDto
{
public long Id { get; set; }
[DisplayName("姓名")]
[TplColumn(template: "${name}")]
[Badge(VisibleOn = "accessFailedCount > 0", Level = "warning", Mode = "text", Text = "${accessFailedCount}")]
public string Name { get; set; }
[DisplayName("头像")]
[AvatarColumn(Text = "${name}")]
[Badge(Animation = true, VisibleOn = "isActive", Level = "info")]
public string AvatarUrl { get; set; }
[Required]
[StringLength(50, MinimumLength = 3)]
[DisplayName("用户名")]
public string UserName { get; set; }
[Required]
[EmailAddress]
[DisplayName("电子邮箱")]
public string Email { get; set; }
[DisplayName("是否激活")]
public bool IsActive { get; set; }
[DisplayName("身份证")]
public string IdNo { get; set; }
[DisplayName("最后登录时间")]
[DateColumn(FromNow = true)]
public DateTimeOffset? LastLoginTime { get; set; }
[DisplayName("角色")]
public List<string> Roles { get; set; }
[DisplayName("手机号码")]
public string PhoneNumber { get; set; }
[DisplayName("性别")]
public Gender Gender { get; set; }
[DisplayName("启用锁定")]
public bool LockoutEnabled { get; set; }
[DisplayName("锁定结束时间")]
public DateTimeOffset? LockoutEnd { get; set; }
[DisplayName("访问失败次数")]
public int AccessFailedCount { get; set; }
}
设计服务接口,定义业务逻辑操作:
// IUserService.cs
public interface IUserService : IBaseCRUDIService<ApplicationUser, UserDto, long, CreateUserDto, UpdateUserDto, UserBatchImportItemDto>, IScopedDependency
{
/// <summary>
/// 获取用户列表(分页)
/// </summary>
Task<PageList<UserDto>> GetUsersAsync(UserQueryDto queryDto);
/// <summary>
/// 分配角色
/// </summary>
Task AssignRolesAsync(long id, List<string> roles);
/// <summary>
/// 移除角色
/// </summary>
Task RemoveRolesAsync(long id, List<string> roles);
/// <summary>
/// 更新用户信息
/// </summary>
Task UpdateUserAsync(long id, UpdateUserDto updateUserDto);
/// <summary>
/// 设置用户激活状态
/// </summary>
Task SetActiveStatusAsync(long id, bool isActive);
/// <summary>
/// 重置随机密码
/// </summary>
Task<string> ResetRandomPasswordAsync(long id);
/// <summary>
/// 解锁用户
/// </summary>
Task UnlockUserAsync(long id);
// 其他方法...
}控制器负责处理HTTP请求并调用相应的服务方法:
// UsersController.cs
[DisplayName("用户管理")]
[Navigation(Icon = "fa-solid fa-users")]
public class UsersController : ApiControllerBase
{
private readonly IUserService _userService;
private readonly IAuthService _authService;
public UsersController(
IUserService userService,
IAuthService authService)
{
_userService = userService;
_authService = authService;
}
// GET: api/Users
[HttpGet]
public async Task<ActionResult<ApiResponse<PageList<UserDto>>>> GetUsers([FromQuery] UserQueryDto queryDto)
{
PageList<UserDto> users = await _userService.GetUsersAsync(queryDto);
return SuccessResponse(users);
}
// GET: api/Users/{id}
[HttpGet("{id}")]
public async Task<ActionResult<ApiResponse<UserDto>>> Detail(long id)
{
UserDto userDto = await _userService.GetAsync(id);
return SuccessResponse(userDto);
}
// POST: api/Users
[HttpPost]
public async Task<ActionResult<ApiResponse<UserDto>>> CreateUser(CreateUserDto createUserDto)
{
var userDto = await _userService.CreateAsync(createUserDto);
return SuccessResponseWithCreate<UserDto>(nameof(Detail), userDto);
}
// PUT: api/Users/{id}
[HttpPut("{id}")]
public async Task<ActionResult<ApiResponse>> UpdateUser(long id, UpdateUserDto updateUserDto)
{
await _userService.UpdateUserAsync(id, updateUserDto);
return SuccessResponse();
}
// DELETE: api/Users/{id}
[HttpDelete("{id}")]
public async Task<ActionResult<ApiResponse>> DeleteUser(long id)
{
await _userService.DeleteAsync(id);
return SuccessResponse();
}
// 自定义操作:重置密码
[HttpPost("{id}/resetRandomPassword")]
[Operation("重置密码", "ajax", null, "确定要重置密码吗?", "isActive == true")]
public async Task<ActionResult<ApiResponse>> ResetRandomPassword(long id)
{
string newPassword = await _userService.ResetRandomPasswordAsync(id);
return SuccessResponse(newPassword);
}
// 自定义操作:解锁用户
[HttpPut("{id}/unlock")]
[Operation("解锁", "ajax", null, "确定要解除用户锁定吗?", "lockoutEnd != null")]
public async Task<ActionResult<ApiResponse>> UnlockUser(long id)
{
await _userService.UnlockUserAsync(id);
return SuccessResponse("用户已成功解锁。");
}
}[DisplayName("用户管理")]:设置模块的显示名称[Navigation(Icon = "fa-solid fa-users")]:配置导航菜单图标[Operation("重置密码", "ajax", null, "确定要重置密码吗?", "isActive == true")]action[AmisInputImageField]:图片上传控件[AmisSelectField]:下拉选择控件[DisplayName]:设置字段显示名[Description]:字段描述信息[Required]:必填字段验证[TplColumn]:模板列[AvatarColumn]:头像列[DateColumn]:日期列[Badge]:徽章标记CodeSpirit框架会根据控制器和DTO的定义自动生成完整的用户管理界面,包括:
Navigation特性生成UserQueryDto的字段定义生成UserDto的字段定义和特性生成Operation特性生成CreateUserDto和UpdateUserDto生成用户管理模块自动生成的界面包括:

以下是使用CodeSpirit框架开发用户管理模块的典型流程:
创建ApplicationUser.cs文件,定义用户实体类。
创建UserDto.cs、CreateUserDto.cs、UpdateUserDto.cs、UserQueryDto.cs等文件,定义数据传输对象。
创建IUserService.cs文件,定义服务接口。
创建UserService.cs文件,实现IUserService接口。
创建UsersController.cs文件,实现API接口。
运行应用后,CodeSpirit框架会自动生成用户管理界面。
[HttpPost("batch/import")]
public async Task<ActionResult<ApiResponse>> BatchImport([FromBody] BatchImportDtoBase<UserBatchImportItemDto> importDto)
{
var (successCount, failedIds) = await _userService.BatchImportAsync(importDto.ImportData);
return SuccessResponse($"成功批量导入了 {successCount} 个用户!");
}[HttpPost("batch/delete")]
[Operation("批量删除", "ajax", null, "确定要批量删除?", isBulkOperation: true)]
public async Task<ActionResult<ApiResponse>> BatchDelete([FromBody] BatchDeleteDto<long> request)
{
var (successCount, failedIds) = await _userService.BatchDeleteAsync(request.Ids);
return SuccessResponse($"成功删除 {successCount} 个用户!");
}[HttpGet("Export")]
public async Task<ActionResult<ApiResponse<PageList<UserDto>>>> Export([FromQuery] UserQueryDto queryDto)
{
// 设置导出时的分页参数
queryDto.PerPage = 10000; // 最大导出数量限制
queryDto.Page = 1;
// 获取用户数据
PageList<UserDto> users = await _userService.GetUsersAsync(queryDto);
return SuccessResponse(users);
}VNext:服务端队列生成Excel。
通过本文档,您已经了解了CodeSpirit框架中用户管理模块的完整开发流程。框架的核心优势在于:
通过CodeSpirit框架,您可以将更多精力放在业务逻辑实现上,而不是繁琐的UI开发工作,大幅提升开发效率。
GET http://identity/api/identity/users/1
特别说明:暂时弃用Dapr,一方面边车带来了不必要的复杂性和性能消耗,另一方面本地开发体验实在是不太友好。CodeSpirit框架提供了强大的聚合器功能,用于处理关联数据的自动替换和补充。聚合器通过HTTP头部指令工作,而非常规的API聚合器模式:
X-Aggregate-Keys: createdBy#User-{value}, updatedBy=/user/{value}.name, items.createdBy=/user/{value}.fullName#{value} ({field})支持静态、动态替换,使用起来非常简单,比如:
/// <summary>
/// 发布人(通过CreatedBy属性获取发布人信息)
/// TODO: 应提供聚合器独立的内部接口
/// </summary>
[DisplayName("发布人")]
[AggregateField(dataSource: "http://identity/api/identity/users/{value}.data.name", template: "用户: {field}")]
public string CreatedBy { get; set; }CodeSpirit框架提供了轻量级配置中心,支持动态更新、多环境配置和实时通知: