chore: 优化公告已读批量与用户维度

This commit is contained in:
2025-12-03 21:13:52 +08:00
parent 9fe7d9606d
commit a3dc5f54e5
4 changed files with 82 additions and 15 deletions

View File

@@ -2,6 +2,7 @@ using MediatR;
using TakeoutSaaS.Application.App.Tenants.Dto;
using TakeoutSaaS.Application.App.Tenants.Queries;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Security;
namespace TakeoutSaaS.Application.App.Tenants.Handlers;
@@ -10,7 +11,8 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
/// </summary>
public sealed class GetTenantAnnouncementQueryHandler(
ITenantAnnouncementRepository announcementRepository,
ITenantAnnouncementReadRepository readRepository)
ITenantAnnouncementReadRepository readRepository,
ICurrentUserAccessor? currentUserAccessor = null)
: IRequestHandler<GetTenantAnnouncementQuery, TenantAnnouncementDto?>
{
public async Task<TenantAnnouncementDto?> Handle(GetTenantAnnouncementQuery request, CancellationToken cancellationToken)
@@ -21,7 +23,20 @@ public sealed class GetTenantAnnouncementQueryHandler(
return null;
}
var reads = await readRepository.GetByAnnouncementAsync(request.TenantId, request.AnnouncementId, cancellationToken);
var userId = currentUserAccessor?.UserId ?? 0;
var reads = await readRepository.GetByAnnouncementAsync(
request.TenantId,
new[] { request.AnnouncementId },
userId == 0 ? null : userId,
cancellationToken);
// 如无用户级已读,再查租户级已读
if (reads.Count == 0)
{
var tenantReads = await readRepository.GetByAnnouncementAsync(request.TenantId, new[] { request.AnnouncementId }, null, cancellationToken);
reads = tenantReads;
}
var readRecord = reads.FirstOrDefault();
return announcement.ToDto(readRecord != null, readRecord?.ReadAt);
}

View File

@@ -1,9 +1,11 @@
using System.Collections.Generic;
using System.Linq;
using MediatR;
using TakeoutSaaS.Application.App.Tenants.Dto;
using TakeoutSaaS.Application.App.Tenants.Queries;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Abstractions.Security;
namespace TakeoutSaaS.Application.App.Tenants.Handlers;
@@ -12,7 +14,8 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
/// </summary>
public sealed class SearchTenantAnnouncementsQueryHandler(
ITenantAnnouncementRepository announcementRepository,
ITenantAnnouncementReadRepository announcementReadRepository)
ITenantAnnouncementReadRepository announcementReadRepository,
ICurrentUserAccessor? currentUserAccessor = null)
: IRequestHandler<SearchTenantAnnouncementsQuery, PagedResult<TenantAnnouncementDto>>
{
public async Task<PagedResult<TenantAnnouncementDto>> Handle(SearchTenantAnnouncementsQuery request, CancellationToken cancellationToken)
@@ -20,17 +23,6 @@ public sealed class SearchTenantAnnouncementsQueryHandler(
var effectiveAt = request.OnlyEffective == true ? DateTime.UtcNow : (DateTime?)null;
var announcements = await announcementRepository.SearchAsync(request.TenantId, request.AnnouncementType, request.IsActive, effectiveAt, cancellationToken);
var readMap = new Dictionary<long, (bool isRead, DateTime? readAt)>();
foreach (var announcement in announcements)
{
var reads = await announcementReadRepository.GetByAnnouncementAsync(request.TenantId, announcement.Id, cancellationToken);
var readRecord = reads.FirstOrDefault();
if (readRecord != null)
{
readMap[announcement.Id] = (true, readRecord.ReadAt);
}
}
var ordered = announcements
.OrderByDescending(x => x.Priority)
.ThenByDescending(x => x.CreatedAt)
@@ -39,9 +31,41 @@ public sealed class SearchTenantAnnouncementsQueryHandler(
var page = request.Page <= 0 ? 1 : request.Page;
var size = request.PageSize <= 0 ? 20 : request.PageSize;
var items = ordered
var pageItems = ordered
.Skip((page - 1) * size)
.Take(size)
.ToList();
var announcementIds = pageItems.Select(x => x.Id).ToArray();
var userId = currentUserAccessor?.UserId ?? 0;
var readMap = new Dictionary<long, (bool isRead, DateTime? readAt)>();
if (announcementIds.Length > 0)
{
// 优先查询当前用户维度的已读其次租户级已读UserId null
var reads = new List<Domain.Tenants.Entities.TenantAnnouncementRead>();
if (userId != 0)
{
var userReads = await announcementReadRepository.GetByAnnouncementAsync(request.TenantId, announcementIds, userId, cancellationToken);
reads.AddRange(userReads);
}
var tenantReads = await announcementReadRepository.GetByAnnouncementAsync(request.TenantId, announcementIds, null, cancellationToken);
reads.AddRange(tenantReads);
foreach (var read in reads.OrderByDescending(x => x.ReadAt))
{
// 若已存在用户级标记,跳过租户级覆盖
if (readMap.ContainsKey(read.AnnouncementId) && read.UserId.HasValue)
{
continue;
}
readMap[read.AnnouncementId] = (true, read.ReadAt);
}
}
var items = pageItems
.Select(a =>
{
readMap.TryGetValue(a.Id, out var read);