YD_Event.Admin/YD_Event.Application/Arrangement/EventArrangementService.cs

183 lines
6.8 KiB
C#
Raw Normal View History

2026-02-08 18:09:05 +08:00
using YD_Event.Application.Arrangement.Dtos;
using YD_Event.Core.Entities;
using MiniExcelLibs;
using SqlSugar;
namespace YD_Event.Application.Arrangement;
/// <summary>
/// 赛事编排服务
/// </summary>
public class EventArrangementService : ITransient
{
2026-03-01 22:39:00 +08:00
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Project> _projectRepository;
private readonly ISqlSugarRepository<ProjectGroup> _groupRepository;
2026-02-08 18:09:05 +08:00
private readonly ISqlSugarRepository<EventRegistrationPerson> _personRepository;
private readonly ISqlSugarRepository<EventRegistration> _registrationRepository;
2026-03-01 22:39:00 +08:00
private readonly ISqlSugarRepository<ProjectType> _projectTypeRepository;
2026-02-08 18:09:05 +08:00
public EventArrangementService(
2026-03-01 22:39:00 +08:00
ISqlSugarRepository<YD_Event.Core.Entities.Project> projectRepository,
ISqlSugarRepository<ProjectGroup> groupRepository,
2026-02-08 18:09:05 +08:00
ISqlSugarRepository<EventRegistrationPerson> personRepository,
2026-03-01 22:39:00 +08:00
ISqlSugarRepository<EventRegistration> registrationRepository,
ISqlSugarRepository<ProjectType> projectTypeRepository)
2026-02-08 18:09:05 +08:00
{
_projectRepository = projectRepository;
_groupRepository = groupRepository;
_personRepository = personRepository;
_registrationRepository = registrationRepository;
2026-03-01 22:39:00 +08:00
_projectTypeRepository = projectTypeRepository;
2026-02-08 18:09:05 +08:00
}
/// <summary>
/// 获取编排项目列表
/// </summary>
[DisplayName("获取编排项目列表")]
public async Task<List<ArrangementProjectListOutput>> GetList(long eventId)
{
var projects = await _projectRepository.GetListAsync(x => x.EventId == eventId);
projects = projects.OrderBy(x => x.SortIndex).ToList();
var groups = await _groupRepository.GetListAsync(x => projects.Select(p => p.Id).Contains(x.ProjectId));
2026-03-01 22:39:00 +08:00
// 获取项目类型信息
var typeIds = projects.Select(x => x.ProjectTypeId).Distinct().ToList();
var types = await _projectTypeRepository.GetListAsync(x => typeIds.Contains(x.Id));
2026-02-08 18:09:05 +08:00
// 统计各组别报名人数(仅统计已支付或审核通过的)
var counts = await _personRepository.AsQueryable()
.InnerJoin<EventRegistration>((p, r) => p.RegistrationId == r.Id)
.Where((p, r) => r.EventId == eventId && (r.PaymentStatus == 1 || r.RegistrationStatus == 2))
.GroupBy(p => new { p.ProjectId, p.GroupName })
.Select(p => new { p.ProjectId, p.GroupName, Count = SqlFunc.AggregateCount(p.Id) })
.ToListAsync();
var result = new List<ArrangementProjectListOutput>();
foreach (var proj in projects)
{
2026-03-01 22:39:00 +08:00
var type = types.FirstOrDefault(x => x.Id == proj.ProjectTypeId);
2026-02-08 18:09:05 +08:00
var dto = new ArrangementProjectListOutput
{
ProjectId = proj.Id,
2026-03-01 22:39:00 +08:00
ProjectName = proj.Name,
ProjectType = type?.Name ?? "未知类型",
2026-02-08 18:09:05 +08:00
DurationSeconds = proj.DurationSeconds,
VenueCount = proj.VenueCount,
SortIndex = proj.SortIndex,
Groups = new List<ArrangementGroupDto>()
};
var projGroups = groups.Where(g => g.ProjectId == proj.Id).ToList();
foreach (var group in projGroups)
{
var countObj = counts.FirstOrDefault(c => c.ProjectId == proj.Id && c.GroupName == group.GroupName);
dto.Groups.Add(new ArrangementGroupDto
{
GroupName = group.GroupName,
ParticipantCount = countObj?.Count ?? 0
});
}
// 估算总时长
int venueCount = proj.VenueCount > 0 ? proj.VenueCount : 1;
int totalParticipants = dto.Groups.Sum(g => g.ParticipantCount);
int rounds = (int)Math.Ceiling((double)totalParticipants / venueCount);
dto.TotalDurationMinutes = (rounds * proj.DurationSeconds) / 60;
result.Add(dto);
}
return result;
}
/// <summary>
/// 更新编排设置
/// </summary>
[UnitOfWork]
[DisplayName("更新编排设置")]
public async Task Update(ArrangementUpdateInput input)
{
foreach (var setting in input.Settings)
{
2026-03-01 22:39:00 +08:00
await _projectRepository.UpdateAsync(x => new YD_Event.Core.Entities.Project
2026-02-08 18:09:05 +08:00
{
VenueCount = setting.VenueCount,
SortIndex = setting.SortIndex
}, x => x.Id == setting.ProjectId);
}
}
/// <summary>
/// 编排预览
/// </summary>
[DisplayName("编排预览")]
public async Task<List<ArrangementPreviewOutput>> Preview(long eventId)
{
// 1. 获取项目(按顺序)
var projects = await _projectRepository.GetListAsync(x => x.EventId == eventId);
projects = projects.OrderBy(x => x.SortIndex).ToList();
2026-03-01 22:39:00 +08:00
2026-02-08 18:09:05 +08:00
var result = new List<ArrangementPreviewOutput>();
// 2. 生成排期
foreach (var proj in projects)
{
int venueCount = proj.VenueCount > 0 ? proj.VenueCount : 1;
// 获取参赛人员(排序:组别 -> ID)
var persons = await _personRepository.AsQueryable()
.InnerJoin<EventRegistration>((p, r) => p.RegistrationId == r.Id)
.Where((p, r) => p.ProjectId == proj.Id && (r.PaymentStatus == 1 || r.RegistrationStatus == 2))
.OrderBy(p => p.GroupName)
.OrderBy(p => p.Id)
.Select((p, r) => new {
p.Name, p.GroupName, r.TeamName,
Duration = proj.DurationSeconds
})
.ToListAsync();
if (!persons.Any()) continue;
// 分组逻辑
int currentRound = 1;
int currentVenue = 1;
foreach (var person in persons)
{
result.Add(new ArrangementPreviewOutput
{
TimeRange = $"{proj.DurationSeconds}''",
2026-03-01 22:39:00 +08:00
ProjectName = proj.Name,
2026-02-08 18:09:05 +08:00
GroupName = person.GroupName,
TeamName = person.TeamName,
AthleteName = person.Name,
SessionIndex = currentRound,
VenueIndex = currentVenue
});
currentVenue++;
if (currentVenue > venueCount)
{
currentVenue = 1;
currentRound++;
}
}
}
return result;
}
/// <summary>
/// 导出编排
/// </summary>
[DisplayName("导出编排")]
public async Task<byte[]> Export(long eventId)
{
var data = await Preview(eventId);
using var stream = new MemoryStream();
stream.SaveAs(data);
return stream.ToArray();
}
}