通知中心游标分页

This commit is contained in:
biss committed 2026-08-23 09:21:04 +08:00
1 parent 172577f668
commit f5db2f6e77
4 files changed
+160 -64

No files matched your search

@@ -138,15 +138,17 @@ public sealed class WarningsController(AppDbContext db, ICurrentUserDataScope sc
[HttpGet("records")]
[Authorize(Roles = Managers + "," + SystemRoles.Counselor)]
public async Task<ActionResult<PagedResult<WarningRecordListItem>>> GetRecords(
public async Task<ActionResult<CursorPagedResult<WarningRecordListItem>>> GetRecords(
Guid? academicTermId,
WarningType? type,
int page = 1,
string? cursor = null,
int pageSize = 20,
CancellationToken ct = default)
{
if (page < 1 || pageSize is < 1 or > 100)
return ValidationProblem("页码必须大于 0,且每页条数应在 1 至 100 之间。");
if (pageSize is < 1 or > 100)
return ValidationProblem("每批条数应在 1 至 100 之间。");
if (!CursorToken.TryDecode<WarningCursor>(cursor, out var after))
return BadRequest("预警记录游标无效。");
var q = db.WarningRecords.AsNoTracking().AsQueryable();
if (scope.Current.Scope == DataScope.College || scope.Current.IsInRole(SystemRoles.Counselor))
@@ -160,12 +162,15 @@ public sealed class WarningsController(AppDbContext db, ICurrentUserDataScope sc
if (academicTermId.HasValue) q = q.Where(x => x.AcademicTermId == academicTermId);
if (type.HasValue) q = q.Where(x => x.Type == type);
var total = await q.CountAsync(ct);
var items = await q
if (after is not null)
{
q = q.Where(x => x.CreatedAt < after.CreatedAt ||
x.CreatedAt == after.CreatedAt && x.Id.CompareTo(after.Id) < 0);
}
var rows = await q
.OrderByDescending(x => x.CreatedAt)
.ThenByDescending(x => x.Id)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Take(pageSize + 1)
.Select(x => new WarningRecordListItem(
x.Id,
x.StudentId,
@@ -180,9 +185,20 @@ public sealed class WarningsController(AppDbContext db, ICurrentUserDataScope sc
x.AcknowledgeComment,
x.CreatedAt))
.ToListAsync(ct);
return Ok(new PagedResult<WarningRecordListItem>(items, total, page, pageSize));
var hasMore = rows.Count > pageSize;
var items = rows.Take(pageSize).ToArray();
var last = items.LastOrDefault();
return Ok(new CursorPagedResult<WarningRecordListItem>(
items,
hasMore && last is not null
? CursorToken.Encode(new WarningCursor(last.CreatedAt, last.Id))
: null,
hasMore,
pageSize));
}
private sealed record WarningCursor(DateTime CreatedAt, Guid Id);
// ═══════════ Student ═══════════
[HttpGet("my-warnings")]
[Authorize(Roles = SystemRoles.Student)]