优化服务器端分页

This commit is contained in:
2026-08-11 11:52:43 +08:00 Unverified
parent 83103eebb8
commit 5d7322507b
6 changed files with 225 additions and 50 deletions
@@ -17,17 +17,53 @@ public sealed class StudentStatusChangesController(
ICurrentUserDataScope currentUserDataScope) : ControllerBase
{
[HttpGet]
public async Task<ActionResult> Get(CancellationToken token)
public async Task<ActionResult<StudentStatusChangePage>> Get(
int page = 1,
int pageSize = 20,
CancellationToken token = default)
{
if (page < 1 || pageSize is < 1 or > 100)
return ValidationProblem("页码必须大于 0,且每页条数应在 1 至 100 之间。");
var source = ScopedChanges().AsNoTracking();
return Ok(await source.OrderByDescending(x => x.SubmittedAt).Select(x => new
{
x.Id, x.StudentId, x.Student!.StudentNumber, x.Student.Name,
ClassName = x.Student.AdministrativeClass!.Name,
CollegeName = x.Student.AdministrativeClass.Major!.College!.Name,
x.Type, x.OriginalStatus, x.TargetStatus, x.Reason, x.State,
x.ReviewComment, x.SubmittedAt, x.ReviewedAt, x.ApprovedAt
}).ToListAsync(token));
var userScope = currentUserDataScope.Current;
var total = await source.CountAsync(token);
var actionableTotal = await source.CountAsync(change =>
(change.State == StudentStatusChangeState.Submitted &&
userScope.IsInRole(SystemRoles.Counselor)) ||
(change.State == StudentStatusChangeState.CounselorApproved &&
userScope.IsInRole(SystemRoles.CollegeAdmin)) ||
(change.State == StudentStatusChangeState.CollegeApproved &&
(userScope.IsInRole(SystemRoles.AcademicAdmin) ||
userScope.IsInRole(SystemRoles.SuperAdmin))), token);
var finishedTotal = await source.CountAsync(change =>
change.State == StudentStatusChangeState.Approved ||
change.State == StudentStatusChangeState.Rejected ||
change.State == StudentStatusChangeState.Cancelled, token);
var items = await source
.OrderByDescending(x => x.SubmittedAt)
.ThenByDescending(x => x.Id)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Select(x => new StudentStatusChangeListItem(
x.Id,
x.StudentId,
x.Student!.StudentNumber,
x.Student.Name,
x.Student.AdministrativeClass!.Name,
x.Student.AdministrativeClass.Major!.College!.Name,
x.Type,
x.OriginalStatus,
x.TargetStatus,
x.Reason,
x.State,
x.ReviewComment,
x.SubmittedAt,
x.ReviewedAt,
x.ApprovedAt))
.ToListAsync(token);
return Ok(new StudentStatusChangePage(
items, total, page, pageSize, actionableTotal, finishedTotal));
}
[HttpGet("options")]
@@ -199,6 +235,31 @@ public sealed class StudentStatusChangesController(
});
}
public sealed record StudentStatusChangePage(
IReadOnlyCollection<StudentStatusChangeListItem> Items,
int Total,
int Page,
int PageSize,
int ActionableTotal,
int FinishedTotal);
public sealed record StudentStatusChangeListItem(
Guid Id,
Guid StudentId,
string StudentNumber,
string Name,
string ClassName,
string CollegeName,
StudentStatusChangeType Type,
StudentStatus OriginalStatus,
StudentStatus TargetStatus,
string Reason,
StudentStatusChangeState State,
string? ReviewComment,
DateTime SubmittedAt,
DateTime? ReviewedAt,
DateTime? ApprovedAt);
public sealed record StudentStatusChangeRequest(
StudentStatusChangeType Type,
[Required, MinLength(10), MaxLength(1000)] string Reason);