服务器端分页优化
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Security.Claims;
|
||||
using Jiaowu.Api.Contracts;
|
||||
using Jiaowu.Api.Domain.Academic;
|
||||
using Jiaowu.Api.Domain.Identity;
|
||||
using Jiaowu.Api.Infrastructure.Persistence;
|
||||
@@ -19,10 +20,35 @@ public sealed class UsersController(
|
||||
RoleManager<ApplicationRole> roleManager) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<object>> GetUsers(CancellationToken cancellationToken)
|
||||
public async Task<ActionResult<PagedResult<UserListItem>>> GetUsers(
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
string? keyword = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var users = await userManager.Users.AsNoTracking()
|
||||
if (page < 1 || pageSize is < 1 or > 100)
|
||||
return ValidationProblem("页码必须大于 0,且每页条数应在 1 至 100 之间。");
|
||||
|
||||
var query = userManager.Users.AsNoTracking();
|
||||
if (!string.IsNullOrWhiteSpace(keyword))
|
||||
{
|
||||
keyword = keyword.Trim();
|
||||
query = query.Where(user =>
|
||||
user.UserName!.Contains(keyword) ||
|
||||
user.DisplayName.Contains(keyword) ||
|
||||
(user.StaffNumber != null && user.StaffNumber.Contains(keyword)) ||
|
||||
(from userRole in db.UserRoles
|
||||
join role in db.Roles on userRole.RoleId equals role.Id
|
||||
where userRole.UserId == user.Id && role.Name!.Contains(keyword)
|
||||
select role.Id).Any());
|
||||
}
|
||||
|
||||
var total = await query.CountAsync(cancellationToken);
|
||||
var users = await query
|
||||
.OrderBy(x => x.UserName)
|
||||
.ThenBy(x => x.Id)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
@@ -36,26 +62,34 @@ public sealed class UsersController(
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var result = new List<object>();
|
||||
foreach (var user in users)
|
||||
{
|
||||
var identityUser = await userManager.FindByIdAsync(user.Id.ToString());
|
||||
result.Add(new
|
||||
{
|
||||
user.Id,
|
||||
user.UserName,
|
||||
user.DisplayName,
|
||||
user.StaffNumber,
|
||||
user.CollegeId,
|
||||
user.IsEnabled,
|
||||
user.LastLoginAt,
|
||||
user.CreatedAt,
|
||||
Roles = identityUser is null
|
||||
? []
|
||||
: await userManager.GetRolesAsync(identityUser)
|
||||
});
|
||||
}
|
||||
return Ok(result);
|
||||
var userIds = users.Select(x => x.Id).ToArray();
|
||||
var roleRows = await (
|
||||
from userRole in db.UserRoles.AsNoTracking()
|
||||
join role in db.Roles.AsNoTracking() on userRole.RoleId equals role.Id
|
||||
where userIds.Contains(userRole.UserId)
|
||||
select new { userRole.UserId, RoleName = role.Name! })
|
||||
.ToListAsync(cancellationToken);
|
||||
var rolesByUser = roleRows
|
||||
.GroupBy(x => x.UserId)
|
||||
.ToDictionary(
|
||||
group => group.Key,
|
||||
group => (IReadOnlyCollection<string>)group
|
||||
.Select(x => x.RoleName)
|
||||
.OrderBy(x => x)
|
||||
.ToArray());
|
||||
|
||||
var items = users.Select(user => new UserListItem(
|
||||
user.Id,
|
||||
user.UserName ?? string.Empty,
|
||||
user.DisplayName,
|
||||
user.StaffNumber,
|
||||
user.CollegeId,
|
||||
user.IsEnabled,
|
||||
user.LastLoginAt,
|
||||
user.CreatedAt,
|
||||
rolesByUser.GetValueOrDefault(user.Id, Array.Empty<string>())))
|
||||
.ToArray();
|
||||
return Ok(new PagedResult<UserListItem>(items, total, page, pageSize));
|
||||
}
|
||||
|
||||
[HttpGet("roles")]
|
||||
@@ -281,6 +315,16 @@ public sealed record CreateUserRequest(
|
||||
[MinLength(1)] string[] Roles);
|
||||
|
||||
public sealed record SetUserStatusRequest(bool IsEnabled);
|
||||
public sealed record UserListItem(
|
||||
Guid Id,
|
||||
string UserName,
|
||||
string DisplayName,
|
||||
string? StaffNumber,
|
||||
Guid? CollegeId,
|
||||
bool IsEnabled,
|
||||
DateTime? LastLoginAt,
|
||||
DateTime CreatedAt,
|
||||
IReadOnlyCollection<string> Roles);
|
||||
public sealed record SetRolesRequest(
|
||||
[MaxLength(30)] string? StaffNumber,
|
||||
Guid? CollegeId,
|
||||
|
||||
Reference in New Issue
Block a user