using MediatR; using System.Text.Json; using TakeoutSaaS.Application.App.Personal.Dto; using TakeoutSaaS.Application.App.Personal.Queries; using TakeoutSaaS.Application.App.Personal.Services; using TakeoutSaaS.Application.App.Personal.Validators; using TakeoutSaaS.Domain.Tenants.Repositories; using TakeoutSaaS.Shared.Abstractions.Results; namespace TakeoutSaaS.Application.App.Personal.Handlers; /// /// 分页查询个人操作记录处理器。 /// public sealed class SearchPersonalOperationsQueryHandler( PersonalContextService personalContextService, PersonalDateRangeValidator personalDateRangeValidator, IOperationLogRepository operationLogRepository) : IRequestHandler> { /// /// 处理查询。 /// /// 查询请求。 /// 取消标记。 /// 操作记录分页结果。 public async Task> Handle(SearchPersonalOperationsQuery request, CancellationToken cancellationToken) { // 1. 获取上下文并解析时间窗 var context = personalContextService.GetRequiredContext(); var dateRange = personalDateRangeValidator.Resolve(request.From, request.To); // 2. 解析分页参数(默认 50,上限 50) var page = request.Page <= 0 ? 1 : request.Page; var pageSize = request.PageSize <= 0 ? 50 : Math.Min(request.PageSize, 50); // 3. 查询并映射 var paged = await operationLogRepository.SearchByOperatorPagedAsync( context.TenantId, context.UserId.ToString(), dateRange.From, dateRange.To, page, pageSize, cancellationToken); var items = paged.Items.Select(log => new PersonalOperationLogDto { OperationId = log.Id, OperatorUserId = ParseOperatorUserId(log.OperatorId, context.UserId), ActionType = log.OperationType, TargetType = log.TargetType, TargetId = ResolveTargetId(log.TargetIds), IsSuccess = log.Success, OccurredAt = log.CreatedAt }).ToList(); // 4. 返回分页结果 return new PagedResult(items, page, pageSize, paged.Total); } private static long ParseOperatorUserId(string? operatorId, long fallbackUserId) { // 1. 尝试从字符串解析用户 ID if (long.TryParse(operatorId, out var parsed) && parsed > 0) { return parsed; } // 2. 解析失败时回退当前用户 return fallbackUserId; } private static string? ResolveTargetId(string? targetIds) { // 1. 空值直接返回 if (string.IsNullOrWhiteSpace(targetIds)) { return null; } // 2. 尝试解析 JSON 数组并提取首个元素 var normalized = targetIds.Trim(); if (normalized.StartsWith("[", StringComparison.Ordinal)) { try { using var doc = JsonDocument.Parse(normalized); if (doc.RootElement.ValueKind == JsonValueKind.Array && doc.RootElement.GetArrayLength() > 0) { return doc.RootElement[0].ToString(); } } catch (JsonException) { // 3. JSON 解析失败时按原始字符串返回 } } // 4. 非数组场景直接返回原值 return normalized; } }