优化服务器端分页
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user