diff --git a/YD_Event.Application/Event/Dtos/ArrangementDtos.cs b/YD_Event.Application/Event/Dtos/ArrangementDtos.cs
index 34179c9..2693fd8 100644
--- a/YD_Event.Application/Event/Dtos/ArrangementDtos.cs
+++ b/YD_Event.Application/Event/Dtos/ArrangementDtos.cs
@@ -119,6 +119,11 @@ public class ArrangementPreviewOutput
///
public string ProjectName { get; set; }
+ ///
+ /// 项目类型
+ ///
+ public string ProjectType { get; set; }
+
///
/// 组别名称
///
diff --git a/YD_Event.Application/Event/Dtos/UnifiedRegistrationDtos.cs b/YD_Event.Application/Event/Dtos/UnifiedRegistrationDtos.cs
index a459339..e488d2e 100644
--- a/YD_Event.Application/Event/Dtos/UnifiedRegistrationDtos.cs
+++ b/YD_Event.Application/Event/Dtos/UnifiedRegistrationDtos.cs
@@ -81,7 +81,39 @@ public class UnifiedRegistrationItemInput
public string? GroupName { get; set; }
///
- /// 参赛人员列表
+ /// 团队列表(支持多个团队报名同一项目组别)
+ ///
+ public List Teams { get; set; } = new();
+
+ ///
+ /// 参赛人员列表(单个团队报名时使用,向后兼容)
+ ///
+ public List Persons { get; set; } = new();
+}
+
+///
+/// 统一团队输入DTO
+///
+public class UnifiedTeamInput
+{
+ ///
+ /// 团队ID(可选,已有团队时使用)
+ ///
+ public long? TeamId { get; set; }
+
+ ///
+ /// 团队名称
+ ///
+ [MaxLength(100, ErrorMessage = "团队名称不能超过100个字符")]
+ public string? TeamName { get; set; }
+
+ ///
+ /// 团队序号(用于显示,如"团队一"、"团队二")
+ ///
+ public int TeamIndex { get; set; }
+
+ ///
+ /// 该团队的参赛人员列表
///
[Required(ErrorMessage = "参赛人员列表不能为空")]
[MinLength(1, ErrorMessage = "请至少填写一个参赛人员")]
diff --git a/YD_Event.Application/Event/EventArrangementService.cs b/YD_Event.Application/Event/EventArrangementService.cs
index 56f0721..9b8d3e3 100644
--- a/YD_Event.Application/Event/EventArrangementService.cs
+++ b/YD_Event.Application/Event/EventArrangementService.cs
@@ -177,6 +177,7 @@ public class EventArrangementService : BaseService, ITransie
{
var regIds = result.Rows.Select(x => x.Id).ToList();
var items = await _itemRepository.GetListAsync(x => regIds.Contains(x.RegistrationId));
- var persons = await _personRepository.GetListAsync(x => regIds.Contains(x.RegistrationId));
+ // 使用关联查询获取报名人员及其关联的用户信息
+ var persons = await _personRepository.AsQueryable()
+ .Includes(p => p.User) // 关联查询用户信息
+ .Where(x => regIds.Contains(x.RegistrationId))
+ .ToListAsync();
foreach (var dto in result.Rows)
{
@@ -83,8 +87,16 @@ public class EventRegistrationService : BaseService, ITransie
{
var myPersons = persons.Where(p => p.RegistrationItemId == item.Id).ToList();
- // 构造参与人信息字符串
- var personInfo = string.Join(";", myPersons.Select(p => $"{p.Name}/{p.Gender}/{p.Age}/{p.IdCard}"));
+ // 构造参与人信息字符串,可以使用关联的 User 信息
+ var personInfo = string.Join(";", myPersons.Select(p =>
+ {
+ // 如果有关联的用户信息,可以使用更完整的信息
+ if (p.User != null)
+ {
+ return $"{p.Name}({p.User.Mobile})/{p.Gender}/{p.Age}";
+ }
+ return $"{p.Name}/{p.Gender}/{p.Age}/{p.IdCard}";
+ }));
if (personInfo.Length > 100) personInfo = personInfo.Substring(0, 97) + "..."; // 截断
var detail = new RegistrationItemDetailDto
diff --git a/YD_Event.Application/Event/UnifiedRegistrationService.cs b/YD_Event.Application/Event/UnifiedRegistrationService.cs
index 3b352ca..6bf105f 100644
--- a/YD_Event.Application/Event/UnifiedRegistrationService.cs
+++ b/YD_Event.Application/Event/UnifiedRegistrationService.cs
@@ -412,16 +412,63 @@ public class UnifiedRegistrationService : ITransient
return result;
}
- // 2.1 验证队员资质(年龄和性别)
- var qualificationResult = ValidatePersonQualifications(item.Persons, eventProjectGroup);
- if (!qualificationResult.IsValid)
+ // 处理团队列表(支持多团队报名)
+ var teamsToValidate = new List();
+
+ if (item.Teams != null && item.Teams.Any())
+ {
+ // 使用新的团队列表格式
+ teamsToValidate.AddRange(item.Teams);
+ }
+ else if (item.Persons != null && item.Persons.Any())
+ {
+ // 向后兼容:使用旧的单个团队格式
+ teamsToValidate.Add(new UnifiedTeamInput
+ {
+ TeamIndex = 1,
+ Persons = item.Persons
+ });
+ }
+ else
{
result.IsValid = false;
- result.ErrorMessage = qualificationResult.ErrorMessage;
- result.Details.AddRange(qualificationResult.Details);
+ result.ErrorMessage = $"请为项目添加至少一个团队和队员";
+ result.Details.Add(new ValidationDetail
+ {
+ ItemName = "团队验证",
+ IsPassed = false,
+ Message = result.ErrorMessage
+ });
return result;
}
- result.Details.AddRange(qualificationResult.Details);
+
+ // 验证每个团队
+ foreach (var team in teamsToValidate)
+ {
+ if (team.Persons == null || !team.Persons.Any())
+ {
+ result.IsValid = false;
+ result.ErrorMessage = $"团队{team.TeamIndex}请至少添加一个队员";
+ result.Details.Add(new ValidationDetail
+ {
+ ItemName = "团队验证",
+ IsPassed = false,
+ Message = result.ErrorMessage
+ });
+ return result;
+ }
+
+ // 验证队员资质(年龄和性别)
+ var qualificationResult = ValidatePersonQualifications(team.Persons, eventProjectGroup);
+ if (!qualificationResult.IsValid)
+ {
+ result.IsValid = false;
+ result.ErrorMessage = qualificationResult.ErrorMessage;
+ result.Details.AddRange(qualificationResult.Details);
+ return result;
+ }
+ result.Details.AddRange(qualificationResult.Details);
+ }
}
return result;
@@ -430,7 +477,7 @@ public class UnifiedRegistrationService : ITransient
///
/// 验证队员资质(年龄和性别)
///
- private RegistrationValidationResult ValidatePersonQualifications(List persons, EventProjectGroup group)
+ public RegistrationValidationResult ValidatePersonQualifications(List persons, EventProjectGroup group)
{
var result = new RegistrationValidationResult
{
@@ -565,51 +612,74 @@ public class UnifiedRegistrationService : ITransient
var baseProject = baseProjects.FirstOrDefault(p => p.Id == eventProject.ProjectId);
var groupName = GetGroupName(item, eventProjectGroups);
- // 计算费用
- var (unitPrice, totalPrice) = CalculateItemPrice(feeConfig, eventProject, item.Persons.Count);
-
- var regItemId = _idGenerator.NewLong();
- var regItem = new EventRegistrationItem
+ // 处理团队列表(支持多团队报名)
+ var teamsToProcess = new List();
+
+ if (item.Teams != null && item.Teams.Any())
{
- Id = regItemId,
- RegistrationId = registration.Id,
- ProjectId = item.ProjectId,
- EventProjectGroupId = item.GroupId,
- ProjectName = baseProject?.Name ?? "",
- GroupName = groupName,
- ProjectTypeName = baseProject?.ProjectType.Description() ?? "",
- UnitPrice = unitPrice,
- PersonCount = item.Persons.Count,
- TotalPrice = totalPrice,
- CreatedUserId = input.CreatedUserId,
- CreatedTime = DateTime.Now
- };
- regItems.Add(regItem);
-
- totalPersonCount += item.Persons.Count;
-
- // 添加参赛人员
- foreach (var pInput in item.Persons)
+ // 使用新的团队列表格式
+ teamsToProcess.AddRange(item.Teams);
+ }
+ else if (item.Persons != null && item.Persons.Any())
{
- persons.Add(new EventRegistrationPerson
+ // 向后兼容:使用旧的单个团队格式
+ teamsToProcess.Add(new UnifiedTeamInput
{
- Id = _idGenerator.NewLong(),
+ TeamIndex = 1,
+ Persons = item.Persons
+ });
+ }
+
+ // 为每个团队创建报名明细
+ foreach (var team in teamsToProcess)
+ {
+ // 计算费用
+ var (unitPrice, totalPrice) = CalculateItemPrice(feeConfig, eventProject, team.Persons.Count);
+
+ var regItemId = _idGenerator.NewLong();
+ var regItem = new EventRegistrationItem
+ {
+ Id = regItemId,
RegistrationId = registration.Id,
- RegistrationItemId = regItemId,
ProjectId = item.ProjectId,
EventProjectGroupId = item.GroupId,
- GroupName = groupName,
ProjectName = baseProject?.Name ?? "",
- Name = pInput.Name,
- Gender = pInput.Gender,
- IdCard = pInput.IdCardNumber,
- BirthDate = pInput.BirthDate,
- Phone = pInput.Mobile,
- Age = CalculateAge(pInput.BirthDate),
- PersonType = PersonType.Athlete,
+ GroupName = groupName,
+ ProjectTypeName = baseProject?.ProjectType.Description() ?? "",
+ UnitPrice = unitPrice,
+ PersonCount = team.Persons.Count,
+ TotalPrice = totalPrice,
CreatedUserId = input.CreatedUserId,
CreatedTime = DateTime.Now
- });
+ };
+ regItems.Add(regItem);
+
+ totalPersonCount += team.Persons.Count;
+
+ // 添加参赛人员
+ foreach (var pInput in team.Persons)
+ {
+ persons.Add(new EventRegistrationPerson
+ {
+ Id = _idGenerator.NewLong(),
+ RegistrationId = registration.Id,
+ RegistrationItemId = regItemId,
+ ProjectId = item.ProjectId,
+ EventProjectGroupId = item.GroupId,
+ GroupName = groupName,
+ ProjectName = baseProject?.Name ?? "",
+ Name = pInput.Name,
+ Gender = pInput.Gender,
+ IdCard = pInput.IdCardNumber,
+ BirthDate = pInput.BirthDate,
+ Phone = pInput.Mobile,
+ Age = CalculateAge(pInput.BirthDate),
+ PersonType = PersonType.Athlete,
+ UserId = pInput.UserId,
+ CreatedUserId = input.CreatedUserId,
+ CreatedTime = DateTime.Now
+ });
+ }
}
}
@@ -874,7 +944,7 @@ public class UnifiedRegistrationService : ITransient
var eventProject = eventProjects.FirstOrDefault(ep => ep.Id == eventProjectGroup.EventProjectId);
if (eventProject == null) continue;
- var projectLimit = projectLimits.FirstOrDefault(pl => pl.ProjectId == eventProject.ProjectId);
+ var projectLimit = projectLimits.FirstOrDefault(pl => pl.ProjectId == eventProject.Id);
if (projectLimit == null) continue;
var submittedTeamCount = groupTeamCount[groupId];
diff --git a/YD_Event.Application/Event/UserEventRegistrationService.cs b/YD_Event.Application/Event/UserEventRegistrationService.cs
index a05a9bb..cc5b56d 100644
--- a/YD_Event.Application/Event/UserEventRegistrationService.cs
+++ b/YD_Event.Application/Event/UserEventRegistrationService.cs
@@ -922,26 +922,41 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
var eventProjectGroup = await _eventProjectGroupRepository.GetByIdAsync(input.GroupId);
if (eventProjectGroup != null)
{
- var projectGroup = await _projectGroupRepository.GetByIdAsync(eventProjectGroup.ProjectGroupId);
-
- // 优先使用EventProjectGroup中保存的信息,如果没有则使用原始ProjectGroup的信息
- var birthDateStart = eventProjectGroup.BirthDateStart != DateTime.MinValue ? eventProjectGroup.BirthDateStart : (projectGroup?.BirthDateStart ?? DateTime.MinValue);
- var birthDateEnd = eventProjectGroup.BirthDateEnd != DateTime.MinValue ? eventProjectGroup.BirthDateEnd : (projectGroup?.BirthDateEnd ?? DateTime.MaxValue);
- var gender = eventProjectGroup.Gender;
-
- var birthDate = member.BirthDate.Value;
- if (birthDate < birthDateStart || birthDate > birthDateEnd)
+ // 创建单个队员的验证输入
+ var persons = new List
{
- result.AgeValid = false;
- result.IsValid = false;
- result.Message = "队员年龄不符合组别要求";
- }
+ new UnifiedPersonInput
+ {
+ UserId = member.Id,
+ Name = member.Name ?? "",
+ IdCardNumber = member.IdCardNumber ?? "",
+ Gender = member.Gender,
+ Mobile = member.Mobile,
+ BirthDate = member.BirthDate.Value
+ }
+ };
- if (gender != member.Gender && gender != Gender.Unknown && gender != Gender.All)
+ // 使用统一的验证方法进行验证
+ var validationResult = _unifiedRegistrationService.ValidatePersonQualifications(persons, eventProjectGroup);
+
+ if (!validationResult.IsValid)
{
- result.GenderValid = false;
result.IsValid = false;
- result.Message = "队员性别不符合组别要求";
+ result.Message = validationResult.ErrorMessage ?? "验证失败";
+
+ // 根据验证详情设置具体的验证状态
+ var ageDetail = validationResult.Details?.FirstOrDefault(d => d.ItemName == "年龄验证" || d.ItemName == "年龄跨组验证");
+ var genderDetail = validationResult.Details?.FirstOrDefault(d => d.ItemName == "性别验证");
+
+ if (ageDetail != null && !ageDetail.IsPassed)
+ {
+ result.AgeValid = false;
+ }
+
+ if (genderDetail != null && !genderDetail.IsPassed)
+ {
+ result.GenderValid = false;
+ }
}
}
@@ -987,7 +1002,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
var eventProject = eventProjects.FirstOrDefault(ep => ep.Id == eventProjectGroup.EventProjectId);
if (eventProject == null) continue;
- var projectLimit = projectLimits.FirstOrDefault(pl => pl.ProjectId == eventProject.ProjectId);
+ var projectLimit = projectLimits.FirstOrDefault(pl => pl.ProjectId == eventProject.Id);
if (projectLimit == null) continue;
// 统计该项目下已报名的队伍数量
@@ -1101,7 +1116,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
// 查找该组别的项目限报配置
var eventProject = eventProjects.FirstOrDefault(ep => ep.Id == eventProjectGroup.EventProjectId);
- var projectLimit = projectLimits.FirstOrDefault(pl => pl.ProjectId == eventProject?.ProjectId);
+ var projectLimit = projectLimits.FirstOrDefault(pl => pl.ProjectId == eventProject?.Id);
var maxTeams = projectLimit?.LimitCount ?? 2; // 默认2队
result.Add(new GroupTeamLimitOutput
diff --git a/YD_Event.Application/YD_Event.Application.xml b/YD_Event.Application/YD_Event.Application.xml
index 98471d9..40f1f1f 100644
--- a/YD_Event.Application/YD_Event.Application.xml
+++ b/YD_Event.Application/YD_Event.Application.xml
@@ -4020,6 +4020,11 @@
项目名称
+
+
+ 项目类型
+
+
组别名称
@@ -5635,9 +5640,39 @@
组别名称
+
+
+ 团队列表(支持多个团队报名同一项目组别)
+
+
- 参赛人员列表
+ 参赛人员列表(单个团队报名时使用,向后兼容)
+
+
+
+
+ 统一团队输入DTO
+
+
+
+
+ 团队ID(可选,已有团队时使用)
+
+
+
+
+ 团队名称
+
+
+
+
+ 团队序号(用于显示,如"团队一"、"团队二")
+
+
+
+
+ 该团队的参赛人员列表
diff --git a/YD_Event.Core/Entities/EventProjectRegistrationLimit.cs b/YD_Event.Core/Entities/EventProjectRegistrationLimit.cs
index 15fe19a..99c0951 100644
--- a/YD_Event.Core/Entities/EventProjectRegistrationLimit.cs
+++ b/YD_Event.Core/Entities/EventProjectRegistrationLimit.cs
@@ -12,7 +12,7 @@ public class EventProjectRegistrationLimit : Entity, ISoftDelete, ICreated
public long EventId { get; set; }
///
- /// 关联的项目ID
+ /// 关联的赛事项目ID
///
public long ProjectId { get; set; }
diff --git a/YD_Event.Core/Entities/EventRegistrationPerson.cs b/YD_Event.Core/Entities/EventRegistrationPerson.cs
index 64439ab..52cf8fd 100644
--- a/YD_Event.Core/Entities/EventRegistrationPerson.cs
+++ b/YD_Event.Core/Entities/EventRegistrationPerson.cs
@@ -33,6 +33,19 @@ public class EventRegistrationPerson : Entity, ISoftDelete, ICreatedUserId
///
public PersonType PersonType { get; set; }
+ ///
+ /// 关联的用户ID(必填)
+ ///
+ [SugarColumn(IsNullable = false)]
+ public long UserId { get; set; }
+
+ ///
+ /// 关联的用户信息(导航属性)
+ ///
+ [SugarColumn(IsIgnore = true)]
+ [Navigate(NavigateType.OneToOne, nameof(UserId))]
+ public AppUser? User { get; set; }
+
///
/// 姓名
///
diff --git a/YD_Event.Core/YD_Event.Core.xml b/YD_Event.Core/YD_Event.Core.xml
index fad338e..b74de19 100644
--- a/YD_Event.Core/YD_Event.Core.xml
+++ b/YD_Event.Core/YD_Event.Core.xml
@@ -1626,7 +1626,7 @@
- 关联的项目ID
+ 关联的赛事项目ID
@@ -2059,6 +2059,11 @@
人员类型:1-运动员,2-教练,3-领队
+
+
+ 关联的用户ID(可选)
+
+
姓名