using YD_Event.Application.Event.Dtos;
using YD_Event.Core.Entities;
using YD_Event.Core.Enum;
using AppUserEntity = YD_Event.Core.Entities.AppUser;
using SysUserEntity = YD_Event.Core.Entities.SysUser;
using MerchantEntity = YD_Event.Core.Entities.Merchant;
namespace YD_Event.Application.Event;
///
/// 参赛记录管理
///
public class EventRecordService : BaseService, ITransient
{
private readonly ISqlSugarRepository _registrationRep;
private readonly ISqlSugarRepository _eventRep;
private readonly ISqlSugarRepository _certificateRep;
private readonly ISqlSugarRepository _appUserRep;
private readonly ISqlSugarRepository _sysUserRep;
private readonly ISqlSugarRepository _merchantRep;
private readonly ISqlSugarRepository _registrationItemRep;
private readonly ISqlSugarRepository _resultRep;
public EventRecordService(ISqlSugarRepository registrationRep,
ISqlSugarRepository eventRep,
ISqlSugarRepository certificateRep,
ISqlSugarRepository appUserRep,
ISqlSugarRepository sysUserRep,
ISqlSugarRepository merchantRep,
ISqlSugarRepository registrationItemRep,
ISqlSugarRepository resultRep) : base(registrationRep)
{
_registrationRep = registrationRep;
_eventRep = eventRep;
_certificateRep = certificateRep;
_appUserRep = appUserRep;
_sysUserRep = sysUserRep;
_merchantRep = merchantRep;
_registrationItemRep = registrationItemRep;
_resultRep = resultRep;
}
///
/// 分页查询参赛记录
///
[HttpGet("page")]
public async Task> Page([FromQuery] EventRecordPageInput input)
{
// 参数验证
ValidateInput(input);
// 第一步:查询用户报名过的所有赛事(去重,按赛事分组)
var eventsQuery = _registrationRep.AsQueryable()
.LeftJoin((r, e) => r.EventId == e.Id)
.LeftJoin((r, e, u) => r.CreatedUserId == u.Id)
.LeftJoin((r, e, u, s) => r.CreatedUserId == s.Id)
.LeftJoin((r, e, u, s, m) => r.CreatedUserId == m.CreatedUserId)
.WhereIF(!string.IsNullOrWhiteSpace(input.EventName), (r, e, u, s, m) => e.EventName.Contains(input.EventName))
.WhereIF(input.StartTime.HasValue, (r, e, u, s, m) => e.MatchStartTime >= input.StartTime)
.WhereIF(input.EndTime.HasValue, (r, e, u, s, m) => e.MatchStartTime <= input.EndTime)
.WhereIF(input.PaymentStatus.HasValue, (r, e, u, s, m) => r.PaymentStatus == input.PaymentStatus)
// Filter by User ID (AppUser, SysUser, or Merchant)
.WhereIF(input.AppUserId.HasValue, (r, e, u, s, m) => u.Id == input.AppUserId)
.WhereIF(input.SysUserId.HasValue, (r, e, u, s, m) => s.Id == input.SysUserId)
.WhereIF(input.MerchantId.HasValue, (r, e, u, s, m) => m.CreatedUserId == input.MerchantId)
.OrderByDescending((r, e, u, s, m) => r.CreatedTime)
.Select((r, e, u, s, m) => new
{
RegistrationId = r.Id,
EventId = e.Id,
EventName = e.EventName,
EventType = e.EventType.ToString(),
StartTime = e.MatchStartTime,
EndTime = e.MatchEndTime,
PaymentStatus = r.PaymentStatus,
ContactName = r.ContactName,
ContactPhone = r.ContactPhone,
TeamName = r.TeamName,
CreatedTime = r.CreatedTime
});
var allEventRecords = await eventsQuery.ToListAsync();
// 第二步:按赛事分组并聚合
var groupedEvents = allEventRecords
.GroupBy(x => x.EventId)
.Select(g => {
// 获取该赛事最早的报名记录作为主记录
var firstRecord = g.OrderBy(x => x.CreatedTime).First();
// 收集该赛事的所有报名记录ID
var registrationIds = g.Select(x => x.RegistrationId).ToList();
return new EventRecordOutput
{
// 用赛事ID作为主要ID(避免分页问题)
Id = firstRecord.EventId,
EventName = firstRecord.EventName,
EventType = firstRecord.EventType,
StartTime = firstRecord.StartTime,
EndTime = firstRecord.EndTime,
PaymentStatus = firstRecord.PaymentStatus,
EventId = firstRecord.EventId,
ContactName = firstRecord.ContactName,
ContactPhone = firstRecord.ContactPhone,
TeamName = firstRecord.TeamName,
RegistrationIds = registrationIds // 保存所有报名ID用于查询证书
};
})
.OrderByDescending(x => x.StartTime)
.ToList();
// 第三步:手动分页
var pageIndex = input.PageNo;
var pageSize = input.PageSize;
var total = groupedEvents.Count;
var pages = (int)Math.Ceiling((double)total / pageSize);
var pagedEvents = groupedEvents
.Skip((pageIndex - 1) * pageSize)
.Take(pageSize)
.ToList();
// 第四步:获取所有需要的报名记录ID(包括所有页面的,避免数据不完整)
var allRegistrationIds = groupedEvents.SelectMany(x => x.RegistrationIds).Distinct().ToList();
// 第五步:获取所有报名项目
var items = await _registrationItemRep.AsQueryable()
.Where(i => allRegistrationIds.Contains(i.RegistrationId))
.ToListAsync();
// 第六步:获取所有成绩
var results = await _resultRep.AsQueryable()
.Where(r => allRegistrationIds.Contains(r.RegistrationId))
.ToListAsync();
// 第七步:将项目和成绩数据填充到结果中
foreach (var row in pagedEvents)
{
// 获取该赛事所有报名记录的项目
var registrationItems = items.Where(i => row.RegistrationIds.Contains(i.RegistrationId)).ToList();
foreach (var item in registrationItems)
{
// 查找对应的成绩
var result = results.FirstOrDefault(r =>
r.RegistrationId == item.RegistrationId &&
r.ProjectId == item.ProjectId &&
r.GroupName == item.GroupName);
row.Items.Add(new EventRegistrationItemOutput
{
Id = item.Id,
ProjectName = item.ProjectName,
ProjectTypeName = item.ProjectTypeName,
GroupName = item.GroupName,
PersonCount = item.PersonCount,
Score = result?.Score,
Rank = result?.Rank > 0 ? GetRankName(result.Rank) : null
});
}
}
// 第八步:构造分页结果
var pageResult = new PageResult
{
Total = total,
PageNo = pageIndex,
PageSize = pageSize,
Pages = pages,
Rows = pagedEvents
};
return pageResult;
}
private string GetRankName(int rank)
{
return rank switch
{
1 => "冠军",
2 => "亚军",
3 => "季军",
_ => $"{rank}名"
};
}
///
/// 验证输入参数
///
private void ValidateInput(EventRecordPageInput input)
{
// 检查是否同时提供了多个用户ID类型
var userTypeCount = 0;
if (input.AppUserId.HasValue) userTypeCount++;
if (input.SysUserId.HasValue) userTypeCount++;
if (input.MerchantId.HasValue) userTypeCount++;
if (userTypeCount > 1)
{
throw Oops.Bah("只能提供一种用户类型ID参数(AppUserId、SysUserId或MerchantId)");
}
// 验证用户ID有效性
if (input.AppUserId.HasValue && input.AppUserId.Value <= 0)
{
throw Oops.Bah("普通用户ID无效");
}
if (input.SysUserId.HasValue && input.SysUserId.Value <= 0)
{
throw Oops.Bah("系统用户ID无效");
}
if (input.MerchantId.HasValue && input.MerchantId.Value <= 0)
{
throw Oops.Bah("商户ID无效");
}
}
///
/// 获取证书列表
///
[HttpGet("certificates")]
public async Task> GetCertificates([FromQuery] List registrationIds)
{
var certs = await _certificateRep.AsQueryable()
.Where(c => registrationIds.Contains(c.RegistrationId))
.ToListAsync();
return certs.Select(c => new CertificateOutput
{
Id = c.Id,
Name = c.ParticipantName,
AwardLevel = GetAwardLevelName(c.AwardLevel),
CertificateType = GetCertificateTypeName(c.CertificateType),
ImageUrl = c.CertificateUrl
}).ToList();
}
private string GetAwardLevelName(int level)
{
return level switch
{
1 => "特等奖",
2 => "一等奖",
3 => "二等奖",
4 => "三等奖",
5 => "优秀奖",
_ => "未知"
};
}
private string GetCertificateTypeName(int type)
{
return type switch
{
1 => "冠军证书",
2 => "亚军证书",
3 => "季军证书",
4 => "优胜证书",
5 => "参与证书",
_ => "未知"
};
}
}