diff --git a/YD_Event.Application/Client/CheckinController.Progress.cs b/YD_Event.Application/Client/CheckinController.Progress.cs index 9ef96e9..1fc93d0 100644 --- a/YD_Event.Application/Client/CheckinController.Progress.cs +++ b/YD_Event.Application/Client/CheckinController.Progress.cs @@ -102,8 +102,21 @@ public partial class CheckinController .Where(x => taskIds.Contains(x.TaskId) && x.SessionKey != null && x.Checked && !x.DeleteMark) .ToListAsync(); + // 检录员姓名按 CheckerUserId 批量查一次,避免逐条检录记录反查用户; + // AppUser.Name 为实名认证姓名,未认证的检录员退回昵称展示。 + var checkerIds = records.Select(x => x.CheckerUserId).Distinct().ToList(); + var checkers = checkerIds.Count == 0 + ? new List() + : await _userRepository.AsQueryable() + .Where(x => checkerIds.Contains(x.Id) && !x.DeleteMark) + .ToListAsync(); + var checkerNameMap = checkers.ToDictionary( + x => x.Id, + x => !string.IsNullOrWhiteSpace(x.Name) ? x.Name! : x.NickName ?? string.Empty); + var taskCheckinNoMap = activeTasks.ToDictionary(x => x.Id, x => x.CheckinNo); var passedByKey = new Dictionary>(); + var checkerNameByKey = new Dictionary>(); foreach (var record in records.Where(x => validUnitKeys.Contains(x.SessionKey!))) { if (!taskCheckinNoMap.TryGetValue(record.TaskId, out var checkinNo)) continue; @@ -113,6 +126,13 @@ public partial class CheckinController passedByKey[record.SessionKey!] = rounds; } rounds[checkinNo] = record.CheckedTime; + + if (!checkerNameByKey.TryGetValue(record.SessionKey!, out var checkerNames)) + { + checkerNames = new Dictionary(); + checkerNameByKey[record.SessionKey!] = checkerNames; + } + checkerNames[checkinNo] = checkerNameMap.GetValueOrDefault(record.CheckerUserId) ?? string.Empty; } var firstCheckinNo = activeTasks.Count == 0 ? 1 : activeTasks.Min(x => x.CheckinNo); @@ -120,6 +140,7 @@ public partial class CheckinController var context = new CheckinProgressContext { PassedByKey = passedByKey, + CheckerNameByKey = checkerNameByKey, FirstCheckinNo = firstCheckinNo, LastCheckinNo = lastCheckinNo, ActiveCheckinNumbers = activeTasks.Select(x => x.CheckinNo).OrderBy(x => x).ToList() @@ -179,6 +200,9 @@ public partial class CheckinController StageStatus = 1, StageStatusText = "比赛中", TeamName = ResolveTeamName(competingUnit), + UnitName = string.IsNullOrWhiteSpace(competingUnit.UnitName) ? "/" : competingUnit.UnitName, + // 秩序册列没有独立的报名类型字段,以 TeamName 是否为空区分个人与团队报名。 + RegistrationTypeText = string.IsNullOrWhiteSpace(competingUnit.TeamName) ? "个人报名" : "团队报名", AthleteNames = competingUnit.Athletes.Select(x => x.Name).ToList() }; } @@ -230,7 +254,8 @@ public partial class CheckinController CheckinNo = checkinNo, CheckinName = ToCheckinName(checkinNo), Passed = context.IsPassed(unit.UnitKey, checkinNo), - CheckedTime = context.GetCheckedTime(unit.UnitKey, checkinNo) + CheckedTime = context.GetCheckedTime(unit.UnitKey, checkinNo), + CheckerName = context.GetCheckerName(unit.UnitKey, checkinNo) }).ToList(), Notice = status switch { @@ -311,7 +336,9 @@ public partial class CheckinController /// 检录进度计算的中间上下文,避免重复查询检录记录。 private sealed class CheckinProgressContext { + // 两个字典的键结构一致:外层为秩序册列 UnitKey,内层为检次号。 public Dictionary> PassedByKey { get; init; } = new(); + public Dictionary> CheckerNameByKey { get; init; } = new(); public int FirstCheckinNo { get; init; } = 1; public int LastCheckinNo { get; init; } = 1; public List ActiveCheckinNumbers { get; init; } = new(); @@ -326,5 +353,10 @@ public partial class CheckinController PassedByKey.TryGetValue(unitKey, out var rounds) && rounds.TryGetValue(checkinNo, out var time) ? time : null; + + public string GetCheckerName(string unitKey, int checkinNo) => + CheckerNameByKey.TryGetValue(unitKey, out var rounds) && rounds.TryGetValue(checkinNo, out var name) + ? name + : string.Empty; } } diff --git a/YD_Event.Application/Client/Dtos/CompetitionClientDtos.cs b/YD_Event.Application/Client/Dtos/CompetitionClientDtos.cs index 07ed59f..4e1bce8 100644 --- a/YD_Event.Application/Client/Dtos/CompetitionClientDtos.cs +++ b/YD_Event.Application/Client/Dtos/CompetitionClientDtos.cs @@ -416,6 +416,12 @@ public class CheckinProgressStageDto /// 该阶段正在比赛的队伍名称。 public string TeamName { get; set; } = string.Empty; + /// 该阶段正在比赛的单位名称。 + public string UnitName { get; set; } = string.Empty; + + /// 报名类型展示文本:个人报名或团队报名。 + public string RegistrationTypeText { get; set; } = string.Empty; + /// 该阶段正在比赛的队员名称列表。 public List AthleteNames { get; set; } = new(); } @@ -457,6 +463,9 @@ public class CheckinProgressRoundDto public string CheckinName { get; set; } = string.Empty; public bool Passed { get; set; } public DateTime? CheckedTime { get; set; } + + /// 执行本次检录的检录员姓名。 + public string CheckerName { get; set; } = string.Empty; } /// 检录投屏数据。