赛事项目关联表重构
This commit is contained in:
parent
b1e918e5cb
commit
11b90517ee
@ -18,6 +18,7 @@ public class EventClientController : IDynamicApiController
|
||||
{
|
||||
private readonly ISqlSugarRepository<EventInfo> _eventRepository;
|
||||
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Project> _projectRepository;
|
||||
private readonly ISqlSugarRepository<EventProject> _eventProjectRepository;
|
||||
private readonly ISqlSugarRepository<ProjectGroup> _groupRepository;
|
||||
private readonly ISqlSugarRepository<EventRegistration> _registrationRepository;
|
||||
private readonly ISqlSugarRepository<EventRegistrationItem> _registrationItemRepository;
|
||||
@ -31,6 +32,7 @@ public class EventClientController : IDynamicApiController
|
||||
public EventClientController(
|
||||
ISqlSugarRepository<EventInfo> eventRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.Project> projectRepository,
|
||||
ISqlSugarRepository<EventProject> eventProjectRepository,
|
||||
ISqlSugarRepository<ProjectGroup> groupRepository,
|
||||
ISqlSugarRepository<EventRegistration> registrationRepository,
|
||||
ISqlSugarRepository<EventRegistrationItem> registrationItemRepository,
|
||||
@ -43,6 +45,7 @@ public class EventClientController : IDynamicApiController
|
||||
{
|
||||
_eventRepository = eventRepository;
|
||||
_projectRepository = projectRepository;
|
||||
_eventProjectRepository = eventProjectRepository;
|
||||
_groupRepository = groupRepository;
|
||||
_registrationRepository = registrationRepository;
|
||||
_registrationItemRepository = registrationItemRepository;
|
||||
@ -164,18 +167,22 @@ public class EventClientController : IDynamicApiController
|
||||
if (evt == null) throw Oops.Bah("赛事不存在");
|
||||
|
||||
// 获取项目及组别
|
||||
var projects = await _projectRepository.AsQueryable()
|
||||
var eventProjects = await _eventProjectRepository.AsQueryable()
|
||||
.Where(ep => ep.EventId == id)
|
||||
.ToListAsync();
|
||||
|
||||
var projectIds = eventProjects.Select(ep => ep.ProjectId).Distinct().ToList();
|
||||
|
||||
var baseProjects = await _projectRepository.AsQueryable()
|
||||
.LeftJoin<ProjectType>((p, t) => p.ProjectTypeId == t.Id)
|
||||
.Where(p => p.EventId == id && !p.DeleteMark && p.Status == AvailabilityStatus.Enable)
|
||||
.Where(p => projectIds.Contains(p.Id) && !p.DeleteMark && p.Status == AvailabilityStatus.Enable)
|
||||
.Select((p, t) => new {
|
||||
p.Id,
|
||||
p.Name,
|
||||
p.Fee,
|
||||
TypeName = t.Name
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
var projectIds = projects.Select(p => p.Id).ToList();
|
||||
var groups = await _groupRepository.AsQueryable()
|
||||
.Where(g => projectIds.Contains(g.ProjectId) && !g.DeleteMark)
|
||||
.ToListAsync();
|
||||
@ -222,20 +229,24 @@ public class EventClientController : IDynamicApiController
|
||||
LogoUrl = u.LogoUrl
|
||||
}).ToList(),
|
||||
|
||||
Projects = projects.Select(p => new EventProjectDto
|
||||
Projects = eventProjects.Select(ep =>
|
||||
{
|
||||
Id = p.Id,
|
||||
Name = p.Name,
|
||||
TypeName = p.TypeName,
|
||||
Fee = p.Fee,
|
||||
Groups = groups.Where(g => g.ProjectId == p.Id).Select(g => new EventProjectGroupDto
|
||||
var bp = baseProjects.FirstOrDefault(b => b.Id == ep.ProjectId);
|
||||
return new EventProjectDto
|
||||
{
|
||||
Id = g.Id,
|
||||
GroupName = g.GroupName,
|
||||
GenderRequirement = g.Gender == Gender.Male ? "男" : (g.Gender == Gender.Female ? "女" : "不限"),
|
||||
AgeRequirement = $"{g.BirthDateStart:yyyy-MM-dd} 至 {g.BirthDateEnd:yyyy-MM-dd}"
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
Id = ep.Id,
|
||||
Name = bp?.Name ?? "",
|
||||
TypeName = bp?.TypeName ?? "",
|
||||
Fee = ep.Price / 100m,
|
||||
Groups = groups.Where(g => g.ProjectId == ep.ProjectId).Select(g => new EventProjectGroupDto
|
||||
{
|
||||
Id = g.Id,
|
||||
GroupName = g.GroupName,
|
||||
GenderRequirement = g.Gender == Gender.Male ? "男" : (g.Gender == Gender.Female ? "女" : "不限"),
|
||||
AgeRequirement = $"{g.BirthDateStart:yyyy-MM-dd} 至 {g.BirthDateEnd:yyyy-MM-dd}"
|
||||
}).ToList()
|
||||
};
|
||||
}).Where(x => !string.IsNullOrEmpty(x.Name)).ToList()
|
||||
};
|
||||
|
||||
return detail;
|
||||
@ -306,8 +317,11 @@ public class EventClientController : IDynamicApiController
|
||||
|
||||
foreach (var item in input.Items)
|
||||
{
|
||||
var project = await _projectRepository.GetFirstAsync(p => p.Id == item.ProjectId);
|
||||
if (project == null) throw Oops.Bah($"项目不存在: {item.ProjectId}");
|
||||
var eventProject = await _eventProjectRepository.GetFirstAsync(p => p.Id == item.ProjectId);
|
||||
if (eventProject == null) throw Oops.Bah($"项目不存在: {item.ProjectId}");
|
||||
|
||||
var project = await _projectRepository.GetFirstAsync(p => p.Id == eventProject.ProjectId);
|
||||
if (project == null) throw Oops.Bah($"关联基础项目不存在: {item.ProjectId}");
|
||||
|
||||
// 校验组别
|
||||
// 略,假设前端传参正确,或需根据 GroupId 查
|
||||
@ -323,9 +337,9 @@ public class EventClientController : IDynamicApiController
|
||||
ProjectId = item.ProjectId,
|
||||
ProjectName = project.Name,
|
||||
GroupName = item.GroupName,
|
||||
UnitPrice = project.Fee,
|
||||
UnitPrice = eventProject.Price / 100m,
|
||||
PersonCount = item.Persons.Count,
|
||||
TotalPrice = project.Fee * item.Persons.Count,
|
||||
TotalPrice = (eventProject.Price / 100m) * item.Persons.Count,
|
||||
CreatedUserId = userId,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
|
||||
@ -300,40 +300,45 @@ public class AddEventInput
|
||||
public class EventProjectInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 项目ID (更新时使用)
|
||||
/// 赛事项目ID (更新时使用)
|
||||
/// </summary>
|
||||
public long? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目名称
|
||||
/// 项目ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "项目名称不能为空")]
|
||||
public string Name { get; set; }
|
||||
[Required(ErrorMessage = "项目ID不能为空")]
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目名称 (显示用)
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目类型ID
|
||||
/// 项目类型ID (显示用)
|
||||
/// </summary>
|
||||
public long ProjectTypeId { get; set; }
|
||||
public long? ProjectTypeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目类型名称 (显示用)
|
||||
/// </summary>
|
||||
public string? ProjectTypeName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 完成人数
|
||||
/// </summary>
|
||||
public int CompletionCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 比赛时长(分)
|
||||
/// 性别要求
|
||||
/// </summary>
|
||||
public int DurationMinutes { get; set; }
|
||||
public Gender GenderType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 比赛时长(秒)
|
||||
/// 比赛时长(分) (显示用)
|
||||
/// </summary>
|
||||
public int DurationSeconds { get; set; }
|
||||
public int? DurationMinutes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 比赛时长(秒) (显示用)
|
||||
/// </summary>
|
||||
public int? DurationSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目费用(Step 4)
|
||||
@ -348,7 +353,44 @@ public class EventProjectInput
|
||||
/// <summary>
|
||||
/// 组别列表
|
||||
/// </summary>
|
||||
public List<ProjectGroupInput> Groups { get; set; }
|
||||
public List<EventProjectGroupInput> Groups { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 赛事项目组别输入
|
||||
/// </summary>
|
||||
public class EventProjectGroupInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 赛事项目组别ID (更新时使用)
|
||||
/// </summary>
|
||||
public long? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的项目组别ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "项目组别ID不能为空")]
|
||||
public long ProjectGroupId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 组别名称 (显示用)
|
||||
/// </summary>
|
||||
public string? GroupName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 出生日期起始日期 (显示用)
|
||||
/// </summary>
|
||||
public DateTime? BirthDateStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 出生日期结束日期 (显示用)
|
||||
/// </summary>
|
||||
public DateTime? BirthDateEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 性别要求 (显示用)
|
||||
/// </summary>
|
||||
public Gender? Gender { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -170,6 +170,30 @@ public class SaveFeeConfigInput
|
||||
/// 费用配置
|
||||
/// </summary>
|
||||
public EventFeeConfigInput FeeConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目单价列表(当收费模式为“单价(项目)”时填写)
|
||||
/// </summary>
|
||||
public List<ProjectFeeInput>? ProjectFees { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 项目费用输入
|
||||
/// </summary>
|
||||
public class ProjectFeeInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 项目ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "项目ID不能为空")]
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目单价
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "项目单价不能为空")]
|
||||
[Range(0.01, (double)decimal.MaxValue, ErrorMessage = "项目单价必须大于0")]
|
||||
public decimal Fee { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -10,6 +10,7 @@ namespace YD_Event.Application.Event;
|
||||
/// </summary>
|
||||
public class EventArrangementService : BaseService<YD_Event.Core.Entities.Project>, ITransient
|
||||
{
|
||||
private readonly ISqlSugarRepository<EventProject> _eventProjectRepository;
|
||||
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Project> _projectRepository;
|
||||
private readonly ISqlSugarRepository<ProjectGroup> _groupRepository;
|
||||
private readonly ISqlSugarRepository<EventRegistrationPerson> _personRepository;
|
||||
@ -17,12 +18,14 @@ public class EventArrangementService : BaseService<YD_Event.Core.Entities.Projec
|
||||
private readonly ISqlSugarRepository<ProjectType> _projectTypeRepository;
|
||||
|
||||
public EventArrangementService(
|
||||
ISqlSugarRepository<EventProject> eventProjectRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.Project> projectRepository,
|
||||
ISqlSugarRepository<ProjectGroup> groupRepository,
|
||||
ISqlSugarRepository<EventRegistrationPerson> personRepository,
|
||||
ISqlSugarRepository<EventRegistration> registrationRepository,
|
||||
ISqlSugarRepository<ProjectType> projectTypeRepository) : base(projectRepository)
|
||||
{
|
||||
_eventProjectRepository = eventProjectRepository;
|
||||
_projectRepository = projectRepository;
|
||||
_groupRepository = groupRepository;
|
||||
_personRepository = personRepository;
|
||||
@ -36,10 +39,12 @@ public class EventArrangementService : BaseService<YD_Event.Core.Entities.Projec
|
||||
[DisplayName("获取编排项目列表")]
|
||||
public async Task<List<ArrangementProjectListOutput>> GetList(long eventId)
|
||||
{
|
||||
var projects = await _projectRepository.GetListAsync(x => x.EventId == eventId);
|
||||
var eventProjects = await _eventProjectRepository.GetListAsync(x => x.EventId == eventId);
|
||||
var projectIds = eventProjects.Select(x => x.ProjectId).Distinct().ToList();
|
||||
var projects = await _projectRepository.GetListAsync(x => projectIds.Contains(x.Id));
|
||||
projects = projects.OrderBy(x => x.SortIndex).ToList();
|
||||
|
||||
var groups = await _groupRepository.GetListAsync(x => projects.Select(p => p.Id).Contains(x.ProjectId));
|
||||
var groups = await _groupRepository.GetListAsync(x => projectIds.Contains(x.ProjectId));
|
||||
|
||||
// 获取项目类型信息
|
||||
var typeIds = projects.Select(x => x.ProjectTypeId).Distinct().ToList();
|
||||
@ -54,13 +59,16 @@ public class EventArrangementService : BaseService<YD_Event.Core.Entities.Projec
|
||||
.ToListAsync();
|
||||
|
||||
var result = new List<ArrangementProjectListOutput>();
|
||||
foreach (var proj in projects)
|
||||
foreach (var eventProj in eventProjects)
|
||||
{
|
||||
var proj = projects.FirstOrDefault(x => x.Id == eventProj.ProjectId);
|
||||
if (proj == null) continue;
|
||||
|
||||
var type = types.FirstOrDefault(x => x.Id == proj.ProjectTypeId);
|
||||
|
||||
var dto = new ArrangementProjectListOutput
|
||||
{
|
||||
ProjectId = proj.Id,
|
||||
ProjectId = eventProj.Id,
|
||||
ProjectName = proj.Name,
|
||||
ProjectType = type?.Name ?? "未知类型",
|
||||
DurationSeconds = proj.DurationSeconds,
|
||||
@ -72,7 +80,7 @@ public class EventArrangementService : BaseService<YD_Event.Core.Entities.Projec
|
||||
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);
|
||||
var countObj = counts.FirstOrDefault(c => c.ProjectId == eventProj.Id && c.GroupName == group.GroupName);
|
||||
dto.Groups.Add(new ArrangementGroupDto
|
||||
{
|
||||
GroupName = group.GroupName,
|
||||
@ -98,15 +106,22 @@ public class EventArrangementService : BaseService<YD_Event.Core.Entities.Projec
|
||||
[DisplayName("更新编排设置")]
|
||||
public async Task Update(ArrangementUpdateInput input)
|
||||
{
|
||||
var eventProjectIds = input.Settings.Select(x => x.ProjectId).ToList();
|
||||
var eventProjects = await _eventProjectRepository.GetListAsync(x => eventProjectIds.Contains(x.Id));
|
||||
|
||||
foreach (var setting in input.Settings)
|
||||
{
|
||||
await _projectRepository.UpdateAsync(x => new YD_Event.Core.Entities.Project
|
||||
{
|
||||
VenueCount = setting.VenueCount,
|
||||
SortIndex = setting.SortIndex,
|
||||
DurationSeconds = setting.DurationSeconds,
|
||||
DurationMinutes = setting.DurationSeconds / 60
|
||||
}, x => x.Id == setting.ProjectId);
|
||||
var ep = eventProjects.FirstOrDefault(x => x.Id == setting.ProjectId);
|
||||
if (ep != null)
|
||||
{
|
||||
await _projectRepository.UpdateAsync(x => new YD_Event.Core.Entities.Project
|
||||
{
|
||||
VenueCount = setting.VenueCount,
|
||||
SortIndex = setting.SortIndex,
|
||||
DurationSeconds = setting.DurationSeconds,
|
||||
DurationMinutes = setting.DurationSeconds / 60
|
||||
}, x => x.Id == ep.ProjectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,20 +132,25 @@ public class EventArrangementService : BaseService<YD_Event.Core.Entities.Projec
|
||||
public async Task<List<ArrangementPreviewOutput>> Preview(long eventId)
|
||||
{
|
||||
// 1. 获取项目(按顺序)
|
||||
var projects = await _projectRepository.GetListAsync(x => x.EventId == eventId);
|
||||
var eventProjects = await _eventProjectRepository.GetListAsync(x => x.EventId == eventId);
|
||||
var projectIds = eventProjects.Select(x => x.ProjectId).Distinct().ToList();
|
||||
var projects = await _projectRepository.GetListAsync(x => projectIds.Contains(x.Id));
|
||||
projects = projects.OrderBy(x => x.SortIndex).ToList();
|
||||
|
||||
var result = new List<ArrangementPreviewOutput>();
|
||||
|
||||
// 2. 生成排期
|
||||
foreach (var proj in projects)
|
||||
foreach (var eventProj in eventProjects)
|
||||
{
|
||||
var proj = projects.FirstOrDefault(x => x.Id == eventProj.ProjectId);
|
||||
if (proj == null) continue;
|
||||
|
||||
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))
|
||||
.Where((p, r) => p.ProjectId == eventProj.Id && (r.PaymentStatus == 1 || r.RegistrationStatus == 2))
|
||||
.OrderBy(p => p.GroupName)
|
||||
.OrderBy(p => p.Id)
|
||||
.Select((p, r) => new {
|
||||
|
||||
@ -19,6 +19,8 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
private readonly ISqlSugarRepository<SysCity> _cityRepository;
|
||||
private readonly ISqlSugarRepository<SysDistrict> _districtRepository;
|
||||
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Project> _projectRepository;
|
||||
private readonly ISqlSugarRepository<EventProject> _eventProjectRepository;
|
||||
private readonly ISqlSugarRepository<EventProjectGroup> _eventProjectGroupRepository;
|
||||
private readonly ISqlSugarRepository<ProjectGroup> _projectGroupRepository;
|
||||
private readonly ISqlSugarRepository<ProjectType> _projectTypeRepository;
|
||||
private readonly ISqlSugarRepository<EventRegistrationLimit> _registrationLimitRepository;
|
||||
@ -37,6 +39,8 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
ISqlSugarRepository<SysCity> cityRepository,
|
||||
ISqlSugarRepository<SysDistrict> districtRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.Project> projectRepository,
|
||||
ISqlSugarRepository<EventProject> eventProjectRepository,
|
||||
ISqlSugarRepository<EventProjectGroup> eventProjectGroupRepository,
|
||||
ISqlSugarRepository<ProjectGroup> projectGroupRepository,
|
||||
ISqlSugarRepository<ProjectType> projectTypeRepository,
|
||||
ISqlSugarRepository<EventRegistrationLimit> registrationLimitRepository,
|
||||
@ -54,6 +58,8 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
_cityRepository = cityRepository;
|
||||
_districtRepository = districtRepository;
|
||||
_projectRepository = projectRepository;
|
||||
_eventProjectRepository = eventProjectRepository;
|
||||
_eventProjectGroupRepository = eventProjectGroupRepository;
|
||||
_projectGroupRepository = projectGroupRepository;
|
||||
_projectTypeRepository = projectTypeRepository;
|
||||
_registrationLimitRepository = registrationLimitRepository;
|
||||
@ -171,28 +177,62 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
}
|
||||
|
||||
// 4. 获取项目列表 (Step 3)
|
||||
var projects = await _projectRepository.GetListAsync(x => x.EventId == id);
|
||||
if (projects.Any())
|
||||
var eventProjects = await _eventProjectRepository.GetListAsync(x => x.EventId == id);
|
||||
if (eventProjects.Any())
|
||||
{
|
||||
var projectIds = projects.Select(x => x.Id).ToList();
|
||||
var groups = await _projectGroupRepository.GetListAsync(x => projectIds.Contains(x.ProjectId));
|
||||
var projectLimits = await _projectLimitRepository.GetListAsync(x => projectIds.Contains(x.ProjectId));
|
||||
var eventProjectIds = eventProjects.Select(x => x.Id).ToList();
|
||||
var eventProjectGroups = await _eventProjectGroupRepository.GetListAsync(x => eventProjectIds.Contains(x.EventProjectId));
|
||||
var projectLimits = await _projectLimitRepository.GetListAsync(x => eventProjectIds.Contains(x.ProjectId));
|
||||
|
||||
// 获取关联的原始项目信息
|
||||
var projectIds = eventProjects.Select(x => x.ProjectId).Distinct().ToList();
|
||||
var baseProjects = await _projectRepository.GetListAsync(x => projectIds.Contains(x.Id));
|
||||
var baseProjectGroups = await _projectGroupRepository.GetListAsync(x => projectIds.Contains(x.ProjectId));
|
||||
|
||||
// 获取项目类型信息
|
||||
var typeIds = projects.Select(x => x.ProjectTypeId).Distinct().ToList();
|
||||
var typeIds = baseProjects.Select(x => x.ProjectTypeId).Distinct().ToList();
|
||||
var types = await _projectTypeRepository.GetListAsync(x => typeIds.Contains(x.Id));
|
||||
|
||||
output.Projects = projects.Select(p =>
|
||||
output.Projects = eventProjects.Select(ep =>
|
||||
{
|
||||
var dto = p.Adapt<EventProjectInput>();
|
||||
var type = types.FirstOrDefault(x => x.Id == p.ProjectTypeId);
|
||||
if (type != null)
|
||||
var baseProj = baseProjects.FirstOrDefault(p => p.Id == ep.ProjectId);
|
||||
var dto = new EventProjectInput
|
||||
{
|
||||
dto.ProjectTypeName = type.Name;
|
||||
Id = ep.Id,
|
||||
ProjectId = ep.ProjectId,
|
||||
GenderType = ep.GenderType,
|
||||
Fee = ep.Price / 100m,
|
||||
Name = baseProj?.Name,
|
||||
ProjectTypeId = baseProj?.ProjectTypeId,
|
||||
DurationMinutes = baseProj?.DurationMinutes,
|
||||
DurationSeconds = baseProj?.DurationSeconds
|
||||
};
|
||||
|
||||
if (baseProj != null)
|
||||
{
|
||||
var type = types.FirstOrDefault(x => x.Id == baseProj.ProjectTypeId);
|
||||
if (type != null)
|
||||
{
|
||||
dto.ProjectTypeName = type.Name;
|
||||
}
|
||||
}
|
||||
|
||||
dto.Groups = groups.Where(g => g.ProjectId == p.Id).Select(g => g.Adapt<ProjectGroupInput>()).ToList();
|
||||
var limit = projectLimits.FirstOrDefault(l => l.ProjectId == p.Id);
|
||||
var epGroups = eventProjectGroups.Where(g => g.EventProjectId == ep.Id).ToList();
|
||||
dto.Groups = epGroups.Select(eg =>
|
||||
{
|
||||
var baseGroup = baseProjectGroups.FirstOrDefault(bg => bg.Id == eg.ProjectGroupId);
|
||||
return new EventProjectGroupInput
|
||||
{
|
||||
Id = eg.Id,
|
||||
ProjectGroupId = eg.ProjectGroupId,
|
||||
GroupName = baseGroup?.GroupName,
|
||||
BirthDateStart = baseGroup?.BirthDateStart,
|
||||
BirthDateEnd = baseGroup?.BirthDateEnd,
|
||||
Gender = baseGroup?.Gender
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
var limit = projectLimits.FirstOrDefault(l => l.ProjectId == ep.Id);
|
||||
if (limit != null) dto.LimitCount = limit.LimitCount;
|
||||
return dto;
|
||||
}).ToList();
|
||||
@ -266,29 +306,43 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
|
||||
// 2. 自定义字段 (JSON) - Already in eventInfo
|
||||
|
||||
var projectFees = new List<ProjectFeeInput>();
|
||||
|
||||
// 3. 保存项目信息 (Step 3)
|
||||
if (input.Projects != null && input.Projects.Any())
|
||||
{
|
||||
foreach (var projInput in input.Projects)
|
||||
{
|
||||
var project = projInput.Adapt<YD_Event.Core.Entities.Project>();
|
||||
project.Id = _idGenerator.NewLong();
|
||||
project.EventId = eventInfo.Id;
|
||||
project.Status = AvailabilityStatus.Enable;
|
||||
project.CreatedTime = DateTime.Now;
|
||||
await _projectRepository.InsertAsync(project);
|
||||
var eventProject = new EventProject
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
EventId = eventInfo.Id,
|
||||
ProjectId = projInput.ProjectId,
|
||||
GenderType = projInput.GenderType,
|
||||
Price = (int)(projInput.Fee * 100),
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _eventProjectRepository.InsertAsync(eventProject);
|
||||
|
||||
projectFees.Add(new ProjectFeeInput { ProjectId = eventProject.Id, Fee = projInput.Fee });
|
||||
|
||||
// 保存项目分组
|
||||
if (projInput.Groups != null && projInput.Groups.Any())
|
||||
{
|
||||
var groups = projInput.Groups.Select(g =>
|
||||
{
|
||||
var group = g.Adapt<ProjectGroup>();
|
||||
group.Id = _idGenerator.NewLong();
|
||||
group.ProjectId = project.Id;
|
||||
var group = new EventProjectGroup
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
EventId = eventInfo.Id,
|
||||
EventProjectId = eventProject.Id,
|
||||
ProjectId = projInput.ProjectId,
|
||||
ProjectGroupId = g.ProjectGroupId,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
return group;
|
||||
}).ToList();
|
||||
await _projectGroupRepository.InsertRangeAsync(groups);
|
||||
await _eventProjectGroupRepository.InsertRangeAsync(groups);
|
||||
}
|
||||
|
||||
// 保存项目报名限制 (Step 3 - Project Limit)
|
||||
@ -298,8 +352,9 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
EventId = eventInfo.Id,
|
||||
ProjectId = project.Id,
|
||||
LimitCount = projInput.LimitCount.Value
|
||||
ProjectId = eventProject.Id,
|
||||
LimitCount = projInput.LimitCount.Value,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _projectLimitRepository.InsertAsync(projLimit);
|
||||
}
|
||||
@ -318,10 +373,18 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
// 5. 保存费用配置 (Step 4)
|
||||
if (input.FeeConfig != null)
|
||||
{
|
||||
var feeConfig = input.FeeConfig.Adapt<EventFeeConfig>();
|
||||
feeConfig.Id = _idGenerator.NewLong();
|
||||
feeConfig.EventId = eventInfo.Id;
|
||||
await _feeConfigRepository.InsertAsync(feeConfig);
|
||||
// 满足 SaveFeeConfig 的前置状态要求
|
||||
eventInfo.ProcessStatus = ProcessStatus.ProjectConfigCompleted;
|
||||
await _repository.UpdateAsync(eventInfo);
|
||||
|
||||
var feeConfigInput = new SaveFeeConfigInput
|
||||
{
|
||||
EventId = eventInfo.Id,
|
||||
FeeConfig = input.FeeConfig,
|
||||
ProjectFees = projectFees
|
||||
};
|
||||
|
||||
await SaveFeeConfig(feeConfigInput);
|
||||
}
|
||||
}
|
||||
|
||||
@ -366,38 +429,52 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
|
||||
// 2. 更新自定义字段 (JSON) - Updated in eventInfo
|
||||
|
||||
var projectFees = new List<ProjectFeeInput>();
|
||||
|
||||
// 3. 更新项目信息
|
||||
var oldProjects = await _projectRepository.GetListAsync(x => x.EventId == input.Id);
|
||||
var oldProjectIds = oldProjects.Select(x => x.Id).ToList();
|
||||
var oldEventProjects = await _eventProjectRepository.GetListAsync(x => x.EventId == input.Id);
|
||||
var oldEventProjectIds = oldEventProjects.Select(x => x.Id).ToList();
|
||||
|
||||
if (oldProjectIds.Any())
|
||||
if (oldEventProjectIds.Any())
|
||||
{
|
||||
await _projectGroupRepository.DeleteAsync(x => oldProjectIds.Contains(x.ProjectId));
|
||||
await _projectLimitRepository.DeleteAsync(x => oldProjectIds.Contains(x.ProjectId));
|
||||
await _projectRepository.DeleteAsync(x => x.EventId == input.Id);
|
||||
await _eventProjectGroupRepository.DeleteAsync(x => oldEventProjectIds.Contains(x.EventProjectId));
|
||||
await _projectLimitRepository.DeleteAsync(x => oldEventProjectIds.Contains(x.ProjectId));
|
||||
await _eventProjectRepository.DeleteAsync(x => x.EventId == input.Id);
|
||||
}
|
||||
|
||||
if (input.Projects != null && input.Projects.Any())
|
||||
{
|
||||
foreach (var projInput in input.Projects)
|
||||
{
|
||||
var project = projInput.Adapt<YD_Event.Core.Entities.Project>();
|
||||
project.Id = _idGenerator.NewLong();
|
||||
project.EventId = eventInfo.Id;
|
||||
project.Status = AvailabilityStatus.Enable;
|
||||
project.CreatedTime = DateTime.Now;
|
||||
await _projectRepository.InsertAsync(project);
|
||||
var eventProject = new EventProject
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
EventId = eventInfo.Id,
|
||||
ProjectId = projInput.ProjectId,
|
||||
GenderType = projInput.GenderType,
|
||||
Price = (int)(projInput.Fee * 100),
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _eventProjectRepository.InsertAsync(eventProject);
|
||||
|
||||
projectFees.Add(new ProjectFeeInput { ProjectId = eventProject.Id, Fee = projInput.Fee });
|
||||
|
||||
if (projInput.Groups != null && projInput.Groups.Any())
|
||||
{
|
||||
var groups = projInput.Groups.Select(g =>
|
||||
{
|
||||
var group = g.Adapt<ProjectGroup>();
|
||||
group.Id = _idGenerator.NewLong();
|
||||
group.ProjectId = project.Id;
|
||||
var group = new EventProjectGroup
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
EventId = eventInfo.Id,
|
||||
EventProjectId = eventProject.Id,
|
||||
ProjectId = projInput.ProjectId,
|
||||
ProjectGroupId = g.ProjectGroupId,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
return group;
|
||||
}).ToList();
|
||||
await _projectGroupRepository.InsertRangeAsync(groups);
|
||||
await _eventProjectGroupRepository.InsertRangeAsync(groups);
|
||||
}
|
||||
|
||||
if (projInput.LimitCount.HasValue)
|
||||
@ -406,8 +483,9 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
EventId = eventInfo.Id,
|
||||
ProjectId = project.Id,
|
||||
LimitCount = projInput.LimitCount.Value
|
||||
ProjectId = eventProject.Id,
|
||||
LimitCount = projInput.LimitCount.Value,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _projectLimitRepository.InsertAsync(projLimit);
|
||||
}
|
||||
@ -425,13 +503,23 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
}
|
||||
|
||||
// 5. 更新费用配置
|
||||
await _feeConfigRepository.DeleteAsync(x => x.EventId == input.Id);
|
||||
if (input.FeeConfig != null)
|
||||
{
|
||||
var feeConfig = input.FeeConfig.Adapt<EventFeeConfig>();
|
||||
feeConfig.Id = _idGenerator.NewLong();
|
||||
feeConfig.EventId = eventInfo.Id;
|
||||
await _feeConfigRepository.InsertAsync(feeConfig);
|
||||
// 满足 SaveFeeConfig 的前置状态要求
|
||||
if (eventInfo.ProcessStatus < ProcessStatus.ProjectConfigCompleted)
|
||||
{
|
||||
eventInfo.ProcessStatus = ProcessStatus.ProjectConfigCompleted;
|
||||
await _repository.UpdateAsync(eventInfo);
|
||||
}
|
||||
|
||||
var feeConfigInput = new SaveFeeConfigInput
|
||||
{
|
||||
EventId = eventInfo.Id,
|
||||
FeeConfig = input.FeeConfig,
|
||||
ProjectFees = projectFees
|
||||
};
|
||||
|
||||
await SaveFeeConfig(feeConfigInput);
|
||||
}
|
||||
}
|
||||
|
||||
@ -629,37 +717,47 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
}
|
||||
|
||||
// 1. 更新项目信息 (全量替换)
|
||||
var oldProjects = await _projectRepository.GetListAsync(x => x.EventId == input.EventId);
|
||||
var oldProjectIds = oldProjects.Select(x => x.Id).ToList();
|
||||
var oldEventProjects = await _eventProjectRepository.GetListAsync(x => x.EventId == input.EventId);
|
||||
var oldEventProjectIds = oldEventProjects.Select(x => x.Id).ToList();
|
||||
|
||||
if (oldProjectIds.Any())
|
||||
if (oldEventProjectIds.Any())
|
||||
{
|
||||
await _projectGroupRepository.DeleteAsync(x => oldProjectIds.Contains(x.ProjectId));
|
||||
await _projectLimitRepository.DeleteAsync(x => oldProjectIds.Contains(x.ProjectId));
|
||||
await _projectRepository.DeleteAsync(x => x.EventId == input.EventId);
|
||||
await _eventProjectGroupRepository.DeleteAsync(x => oldEventProjectIds.Contains(x.EventProjectId));
|
||||
await _projectLimitRepository.DeleteAsync(x => oldEventProjectIds.Contains(x.ProjectId));
|
||||
await _eventProjectRepository.DeleteAsync(x => x.EventId == input.EventId);
|
||||
}
|
||||
|
||||
if (input.Projects != null && input.Projects.Any())
|
||||
{
|
||||
foreach (var projInput in input.Projects)
|
||||
{
|
||||
var project = projInput.Adapt<YD_Event.Core.Entities.Project>();
|
||||
project.Id = _idGenerator.NewLong();
|
||||
project.EventId = input.EventId;
|
||||
project.Status = AvailabilityStatus.Enable;
|
||||
project.CreatedTime = DateTime.Now;
|
||||
await _projectRepository.InsertAsync(project);
|
||||
var eventProject = new EventProject
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
EventId = input.EventId,
|
||||
ProjectId = projInput.ProjectId,
|
||||
GenderType = projInput.GenderType,
|
||||
Price = (int)(projInput.Fee * 100),
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _eventProjectRepository.InsertAsync(eventProject);
|
||||
|
||||
if (projInput.Groups != null && projInput.Groups.Any())
|
||||
{
|
||||
var groups = projInput.Groups.Select(g =>
|
||||
{
|
||||
var group = g.Adapt<ProjectGroup>();
|
||||
group.Id = _idGenerator.NewLong();
|
||||
group.ProjectId = project.Id;
|
||||
var group = new EventProjectGroup
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
EventId = input.EventId,
|
||||
EventProjectId = eventProject.Id,
|
||||
ProjectId = projInput.ProjectId,
|
||||
ProjectGroupId = g.ProjectGroupId,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
return group;
|
||||
}).ToList();
|
||||
await _projectGroupRepository.InsertRangeAsync(groups);
|
||||
await _eventProjectGroupRepository.InsertRangeAsync(groups);
|
||||
}
|
||||
|
||||
if (projInput.LimitCount.HasValue)
|
||||
@ -668,8 +766,9 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
EventId = input.EventId,
|
||||
ProjectId = project.Id,
|
||||
LimitCount = projInput.LimitCount.Value
|
||||
ProjectId = eventProject.Id,
|
||||
LimitCount = projInput.LimitCount.Value,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _projectLimitRepository.InsertAsync(projLimit);
|
||||
}
|
||||
@ -711,6 +810,40 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
throw new InvalidOperationException("请先完成项目配置");
|
||||
}
|
||||
|
||||
// 验证单价(项目)模式下的项目单价
|
||||
if (input.FeeConfig != null && input.FeeConfig.ChargeMode == ChargeMode.UnitPriceProject)
|
||||
{
|
||||
if (input.ProjectFees == null || !input.ProjectFees.Any())
|
||||
{
|
||||
throw new InvalidOperationException("收费模式为“单价(项目)”时,必须提供项目单价信息");
|
||||
}
|
||||
|
||||
var projectIds = input.ProjectFees.Select(x => x.ProjectId).ToList();
|
||||
var eventProjects = await _eventProjectRepository.GetListAsync(x => x.EventId == input.EventId && projectIds.Contains(x.Id));
|
||||
|
||||
foreach (var feeInput in input.ProjectFees)
|
||||
{
|
||||
if (feeInput.Fee <= 0)
|
||||
{
|
||||
throw new InvalidOperationException("项目单价必须大于0");
|
||||
}
|
||||
|
||||
// 格式验证:最多保留两位小数
|
||||
if (Math.Round(feeInput.Fee, 2) != feeInput.Fee)
|
||||
{
|
||||
throw new InvalidOperationException("项目单价格式不正确,最多保留两位小数");
|
||||
}
|
||||
|
||||
var proj = eventProjects.FirstOrDefault(p => p.Id == feeInput.ProjectId);
|
||||
if (proj != null)
|
||||
{
|
||||
proj.Price = (int)(feeInput.Fee * 100);
|
||||
proj.UpdatedTime = DateTime.Now;
|
||||
await _eventProjectRepository.UpdateAsync(proj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新费用配置
|
||||
await _feeConfigRepository.DeleteAsync(x => x.EventId == input.EventId);
|
||||
if (input.FeeConfig != null)
|
||||
@ -719,6 +852,9 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
feeConfig.Id = _idGenerator.NewLong();
|
||||
feeConfig.EventId = input.EventId;
|
||||
await _feeConfigRepository.InsertAsync(feeConfig);
|
||||
|
||||
// 更新赛事的 ChargeMode
|
||||
eventInfo.ChargeMode = feeConfig.ChargeMode;
|
||||
}
|
||||
|
||||
// 生成二维码URL
|
||||
|
||||
@ -20,7 +20,10 @@ public class UserCompetitionService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly ISqlSugarRepository<EventInfo> _eventRepository;
|
||||
private readonly ISqlSugarRepository<EventUnit> _unitRepository;
|
||||
private readonly ISqlSugarRepository<EventProject> _eventProjectRepository;
|
||||
private readonly ISqlSugarRepository<EventProjectGroup> _eventProjectGroupRepository;
|
||||
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Project> _projectRepository;
|
||||
private readonly ISqlSugarRepository<ProjectGroup> _projectGroupRepository;
|
||||
private readonly ISqlSugarRepository<EventRegistration> _registrationRepository;
|
||||
private readonly ISqlSugarRepository<EventRegistrationItem> _registrationItemRepository;
|
||||
private readonly ISqlSugarRepository<EventRegistrationPerson> _registrationPersonRepository;
|
||||
@ -37,7 +40,10 @@ public class UserCompetitionService : IDynamicApiController, ITransient
|
||||
public UserCompetitionService(
|
||||
ISqlSugarRepository<EventInfo> eventRepository,
|
||||
ISqlSugarRepository<EventUnit> unitRepository,
|
||||
ISqlSugarRepository<EventProject> eventProjectRepository,
|
||||
ISqlSugarRepository<EventProjectGroup> eventProjectGroupRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.Project> projectRepository,
|
||||
ISqlSugarRepository<ProjectGroup> projectGroupRepository,
|
||||
ISqlSugarRepository<EventRegistration> registrationRepository,
|
||||
ISqlSugarRepository<EventRegistrationItem> registrationItemRepository,
|
||||
ISqlSugarRepository<EventRegistrationPerson> registrationPersonRepository,
|
||||
@ -53,7 +59,10 @@ public class UserCompetitionService : IDynamicApiController, ITransient
|
||||
{
|
||||
_eventRepository = eventRepository;
|
||||
_unitRepository = unitRepository;
|
||||
_eventProjectRepository = eventProjectRepository;
|
||||
_eventProjectGroupRepository = eventProjectGroupRepository;
|
||||
_projectRepository = projectRepository;
|
||||
_projectGroupRepository = projectGroupRepository;
|
||||
_registrationRepository = registrationRepository;
|
||||
_registrationItemRepository = registrationItemRepository;
|
||||
_registrationPersonRepository = registrationPersonRepository;
|
||||
@ -146,14 +155,21 @@ public class UserCompetitionService : IDynamicApiController, ITransient
|
||||
};
|
||||
}
|
||||
|
||||
var projects = await _projectRepository.GetListAsync(x => x.EventId == id && x.Status == AvailabilityStatus.Enable);
|
||||
output.Projects = projects.Select(p => new UserEventProjectListOutput
|
||||
var eventProjects = await _eventProjectRepository.GetListAsync(x => x.EventId == id);
|
||||
var projectIds = eventProjects.Select(x => x.ProjectId).Distinct().ToList();
|
||||
var baseProjects = await _projectRepository.GetListAsync(x => projectIds.Contains(x.Id) && x.Status == AvailabilityStatus.Enable);
|
||||
|
||||
output.Projects = eventProjects.Select(ep =>
|
||||
{
|
||||
Id = p.Id,
|
||||
Name = p.Name,
|
||||
Fee = p.Fee,
|
||||
CompletionCount = p.CompletionCount
|
||||
}).ToList();
|
||||
var p = baseProjects.FirstOrDefault(b => b.Id == ep.ProjectId);
|
||||
return new UserEventProjectListOutput
|
||||
{
|
||||
Id = ep.Id,
|
||||
Name = p?.Name ?? "",
|
||||
Fee = ep.Price / 100m,
|
||||
CompletionCount = p?.CompletionCount ?? 0
|
||||
};
|
||||
}).Where(x => !string.IsNullOrEmpty(x.Name)).ToList();
|
||||
|
||||
var userId = _authManager.UserId;
|
||||
var registration = await _registrationRepository.GetFirstAsync(x => x.EventId == id && x.CreatedUserId == userId && !x.DeleteMark);
|
||||
@ -178,16 +194,22 @@ public class UserCompetitionService : IDynamicApiController, ITransient
|
||||
[HttpGet("projects/{eventId}")]
|
||||
public async Task<List<UserEventProjectListOutput>> GetProjects([FromRoute] long eventId)
|
||||
{
|
||||
var projects = await _projectRepository.GetListAsync(x => x.EventId == eventId && x.Status == AvailabilityStatus.Enable);
|
||||
|
||||
return projects.Select(p => new UserEventProjectListOutput
|
||||
var eventProjects = await _eventProjectRepository.GetListAsync(x => x.EventId == eventId);
|
||||
var projectIds = eventProjects.Select(x => x.ProjectId).Distinct().ToList();
|
||||
var baseProjects = await _projectRepository.GetListAsync(x => projectIds.Contains(x.Id) && x.Status == AvailabilityStatus.Enable);
|
||||
|
||||
return eventProjects.Select(ep =>
|
||||
{
|
||||
Id = p.Id,
|
||||
Name = p.Name,
|
||||
Fee = p.Fee,
|
||||
TeamSize = 1, // 默认为1
|
||||
CompletionCount = p.CompletionCount
|
||||
}).ToList();
|
||||
var p = baseProjects.FirstOrDefault(b => b.Id == ep.ProjectId);
|
||||
return new UserEventProjectListOutput
|
||||
{
|
||||
Id = ep.Id,
|
||||
Name = p?.Name ?? "",
|
||||
Fee = ep.Price / 100m,
|
||||
TeamSize = 1, // 默认为1
|
||||
CompletionCount = p?.CompletionCount ?? 0
|
||||
};
|
||||
}).Where(x => !string.IsNullOrEmpty(x.Name)).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -269,23 +291,26 @@ public class UserCompetitionService : IDynamicApiController, ITransient
|
||||
await _registrationItemRepository.DeleteAsync(x => x.RegistrationId == registration.Id);
|
||||
await _registrationPersonRepository.DeleteAsync(x => x.RegistrationId == registration.Id);
|
||||
|
||||
var projects = await _projectRepository.GetListAsync(x => input.ProjectIds.Contains(x.Id));
|
||||
var eventProjects = await _eventProjectRepository.GetListAsync(x => input.ProjectIds.Contains(x.Id));
|
||||
var baseProjectIds = eventProjects.Select(x => x.ProjectId).ToList();
|
||||
var baseProjects = await _projectRepository.GetListAsync(x => baseProjectIds.Contains(x.Id));
|
||||
var members = await _userRepository.GetListAsync(x => input.MemberIds.Contains(x.Id));
|
||||
|
||||
decimal totalAmount = 0;
|
||||
int totalPersonCount = 0;
|
||||
|
||||
foreach (var project in projects)
|
||||
foreach (var eventProject in eventProjects)
|
||||
{
|
||||
var baseProject = baseProjects.FirstOrDefault(x => x.Id == eventProject.ProjectId);
|
||||
var item = new EventRegistrationItem
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
RegistrationId = registration.Id,
|
||||
ProjectId = project.Id,
|
||||
ProjectName = project.Name,
|
||||
UnitPrice = project.Fee,
|
||||
ProjectId = eventProject.Id,
|
||||
ProjectName = baseProject?.Name ?? "",
|
||||
UnitPrice = eventProject.Price / 100m,
|
||||
PersonCount = members.Count(),
|
||||
TotalPrice = project.Fee * members.Count(),
|
||||
TotalPrice = (eventProject.Price / 100m) * members.Count(),
|
||||
CreatedUserId = userId,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
@ -301,7 +326,7 @@ public class UserCompetitionService : IDynamicApiController, ITransient
|
||||
Id = _idGenerator.NewLong(),
|
||||
RegistrationId = registration.Id,
|
||||
RegistrationItemId = item.Id,
|
||||
ProjectId = project.Id,
|
||||
ProjectId = eventProject.Id,
|
||||
Name = member.Name,
|
||||
Gender = member.Gender,
|
||||
IdCard = member.IdCardNumber,
|
||||
|
||||
@ -10,11 +10,6 @@ namespace YD_Event.Application.Project.Dtos;
|
||||
/// </summary>
|
||||
public class ProjectQueryInput : Pagination
|
||||
{
|
||||
/// <summary>
|
||||
/// 赛事ID
|
||||
/// </summary>
|
||||
public long? EventId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目名称 (模糊查询)
|
||||
/// </summary>
|
||||
@ -28,12 +23,6 @@ public class ProjectQueryInput : Pagination
|
||||
|
||||
public class AddProjectInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 关联的赛事ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "赛事ID不能为空")]
|
||||
public long EventId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目名称
|
||||
/// </summary>
|
||||
@ -125,11 +114,6 @@ public class ProjectDto
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的赛事ID
|
||||
/// </summary>
|
||||
public long EventId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目名称
|
||||
/// </summary>
|
||||
|
||||
@ -35,7 +35,6 @@ public class ProjectService : BaseService<YD_Event.Core.Entities.Project>, ITran
|
||||
{
|
||||
var query = _repository.AsQueryable()
|
||||
.LeftJoin<ProjectType>((p, pt) => p.ProjectTypeId == pt.Id)
|
||||
.WhereIF(input.EventId.HasValue, (p, pt) => p.EventId == input.EventId)
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(input.ProjectName), (p, pt) => p.Name.Contains(input.ProjectName))
|
||||
.WhereIF(input.ProjectTypeId.HasValue, (p, pt) => p.ProjectTypeId == input.ProjectTypeId)
|
||||
.OrderByDescending((p, pt) => p.Id);
|
||||
@ -43,7 +42,6 @@ public class ProjectService : BaseService<YD_Event.Core.Entities.Project>, ITran
|
||||
var result = await query.Select((p, pt) => new ProjectDto
|
||||
{
|
||||
Id = p.Id,
|
||||
EventId = p.EventId,
|
||||
Name = p.Name,
|
||||
ProjectTypeId = p.ProjectTypeId,
|
||||
ProjectTypeName = pt.Name,
|
||||
@ -72,9 +70,9 @@ public class ProjectService : BaseService<YD_Event.Core.Entities.Project>, ITran
|
||||
[UnitOfWork]
|
||||
public async Task Add(AddProjectInput input)
|
||||
{
|
||||
// 检查项目名称在同一赛事中是否重复
|
||||
var isExist = await _repository.IsAnyAsync(x => x.EventId == input.EventId && x.Name == input.Name);
|
||||
if (isExist) throw new InvalidOperationException("该项目名称在当前赛事中已存在");
|
||||
// 检查项目名称是否重复
|
||||
var isExist = await _repository.IsAnyAsync(x => x.Name == input.Name);
|
||||
if (isExist) throw new InvalidOperationException("该项目名称已存在");
|
||||
|
||||
var entity = input.Adapt<YD_Event.Core.Entities.Project>();
|
||||
entity.Id = _idGenerator.NewLong();
|
||||
@ -109,8 +107,8 @@ public class ProjectService : BaseService<YD_Event.Core.Entities.Project>, ITran
|
||||
// 如果修改了名称,检查是否重复
|
||||
if (entity.Name != input.Name)
|
||||
{
|
||||
var isExist = await _repository.IsAnyAsync(x => x.EventId == input.EventId && x.Name == input.Name && x.Id != input.Id);
|
||||
if (isExist) throw new InvalidOperationException("该项目名称在当前赛事中已存在");
|
||||
var isExist = await _repository.IsAnyAsync(x => x.Name == input.Name && x.Id != input.Id);
|
||||
if (isExist) throw new InvalidOperationException("该项目名称已存在");
|
||||
}
|
||||
|
||||
input.Adapt(entity);
|
||||
|
||||
@ -3540,17 +3540,22 @@
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectInput.Id">
|
||||
<summary>
|
||||
项目ID (更新时使用)
|
||||
赛事项目ID (更新时使用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectInput.ProjectId">
|
||||
<summary>
|
||||
项目ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectInput.Name">
|
||||
<summary>
|
||||
项目名称
|
||||
项目名称 (显示用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectInput.ProjectTypeId">
|
||||
<summary>
|
||||
项目类型ID
|
||||
项目类型ID (显示用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectInput.ProjectTypeName">
|
||||
@ -3558,19 +3563,19 @@
|
||||
项目类型名称 (显示用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectInput.CompletionCount">
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectInput.GenderType">
|
||||
<summary>
|
||||
完成人数
|
||||
性别要求
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectInput.DurationMinutes">
|
||||
<summary>
|
||||
比赛时长(分)
|
||||
比赛时长(分) (显示用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectInput.DurationSeconds">
|
||||
<summary>
|
||||
比赛时长(秒)
|
||||
比赛时长(秒) (显示用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectInput.Fee">
|
||||
@ -3588,6 +3593,41 @@
|
||||
组别列表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Application.Event.Dtos.EventProjectGroupInput">
|
||||
<summary>
|
||||
赛事项目组别输入
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectGroupInput.Id">
|
||||
<summary>
|
||||
赛事项目组别ID (更新时使用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectGroupInput.ProjectGroupId">
|
||||
<summary>
|
||||
关联的项目组别ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectGroupInput.GroupName">
|
||||
<summary>
|
||||
组别名称 (显示用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectGroupInput.BirthDateStart">
|
||||
<summary>
|
||||
出生日期起始日期 (显示用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectGroupInput.BirthDateEnd">
|
||||
<summary>
|
||||
出生日期结束日期 (显示用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.EventProjectGroupInput.Gender">
|
||||
<summary>
|
||||
性别要求 (显示用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Application.Event.Dtos.EventRegistrationLimitInput">
|
||||
<summary>
|
||||
报名限制输入
|
||||
@ -3948,6 +3988,26 @@
|
||||
费用配置
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.SaveFeeConfigInput.ProjectFees">
|
||||
<summary>
|
||||
项目单价列表(当收费模式为“单价(项目)”时填写)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Application.Event.Dtos.ProjectFeeInput">
|
||||
<summary>
|
||||
项目费用输入
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.ProjectFeeInput.ProjectId">
|
||||
<summary>
|
||||
项目ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.ProjectFeeInput.Fee">
|
||||
<summary>
|
||||
项目单价
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Application.Event.Dtos.EventProgressOutput">
|
||||
<summary>
|
||||
赛事进度输出
|
||||
@ -7184,11 +7244,6 @@
|
||||
项目查询输入
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Project.Dtos.ProjectQueryInput.EventId">
|
||||
<summary>
|
||||
赛事ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Project.Dtos.ProjectQueryInput.ProjectName">
|
||||
<summary>
|
||||
项目名称 (模糊查询)
|
||||
@ -7199,11 +7254,6 @@
|
||||
项目类型ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Project.Dtos.AddProjectInput.EventId">
|
||||
<summary>
|
||||
关联的赛事ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Project.Dtos.AddProjectInput.Name">
|
||||
<summary>
|
||||
项目名称
|
||||
@ -7284,11 +7334,6 @@
|
||||
ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Project.Dtos.ProjectDto.EventId">
|
||||
<summary>
|
||||
关联的赛事ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Project.Dtos.ProjectDto.Name">
|
||||
<summary>
|
||||
项目名称
|
||||
|
||||
@ -149,7 +149,7 @@
|
||||
"ALiYunSMS": {
|
||||
"Endpoint": "dysmsapi.aliyuncs.com",
|
||||
"Sign": "oVpeH1PpDUnWTcBrUSSYkQNS4Fex8Y",
|
||||
"Template": "SMS_147140268"
|
||||
"Template": "SMS_254100608"
|
||||
},
|
||||
// 阿里云ORC识别
|
||||
"AliyunOCR": {
|
||||
|
||||
47
YD_Event.Core/Entities/EventProject.cs
Normal file
47
YD_Event.Core/Entities/EventProject.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using SqlSugar;
|
||||
using YD_Event.Core.Enum;
|
||||
|
||||
namespace YD_Event.Core.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// 赛事项目关联表
|
||||
/// </summary>
|
||||
public class EventProject : Entity<long>, ICreatedTime, IUpdatedTime
|
||||
{
|
||||
/// <summary>
|
||||
/// 赛事ID
|
||||
/// </summary>
|
||||
public long EventId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目ID
|
||||
/// </summary>
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 性别要求 (男/女/不限)
|
||||
/// </summary>
|
||||
public Gender GenderType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 价格(单位:分)
|
||||
/// </summary>
|
||||
public int Price { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 赛事项目组别列表(导航属性)
|
||||
/// </summary>
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public List<EventProjectGroup>? Groups { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? UpdatedTime { get; set; }
|
||||
}
|
||||
55
YD_Event.Core/Entities/EventProjectGroup.cs
Normal file
55
YD_Event.Core/Entities/EventProjectGroup.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using YD_Event.Core.Enum;
|
||||
|
||||
namespace YD_Event.Core.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// 赛事项目组别表
|
||||
/// </summary>
|
||||
[SugarTable("EventProjectGroup")]
|
||||
public class EventProjectGroup : Entity<long>, ISoftDelete, ICreatedUserId, ICreatedTime, IUpdatedUserId, IUpdatedTime
|
||||
{
|
||||
/// <summary>
|
||||
/// 赛事ID
|
||||
/// </summary>
|
||||
public long EventId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 赛事项目ID
|
||||
/// </summary>
|
||||
public long EventProjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的项目ID
|
||||
/// </summary>
|
||||
public long ProjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的项目组别ID
|
||||
/// </summary>
|
||||
public long ProjectGroupId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标记删除
|
||||
/// </summary>
|
||||
public bool DeleteMark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建人
|
||||
/// </summary>
|
||||
public long CreatedUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新人
|
||||
/// </summary>
|
||||
public long? UpdatedUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public DateTime? UpdatedTime { get; set; }
|
||||
}
|
||||
@ -9,11 +9,6 @@ namespace YD_Event.Core.Entities;
|
||||
[SugarTable("Project")]
|
||||
public class Project : Entity<long>, ISoftDelete, ICreatedUserId, ICreatedTime, IUpdatedUserId, IUpdatedTime, IAvailability
|
||||
{
|
||||
/// <summary>
|
||||
/// 关联的赛事ID
|
||||
/// </summary>
|
||||
public long EventId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目名称
|
||||
/// </summary>
|
||||
|
||||
@ -209,17 +209,6 @@
|
||||
高度
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Core.Domain.Certificate.CertificateDocument">
|
||||
<summary>
|
||||
证书文档
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:YD_Event.Core.Domain.Certificate.CertificateDocument.GeneratePdf">
|
||||
<summary>
|
||||
生成PDF
|
||||
</summary>
|
||||
<returns>PDF字节数组</returns>
|
||||
</member>
|
||||
<member name="T:YD_Event.Core.Domain.Certificate.DocxTemplateParser">
|
||||
<summary>
|
||||
DOCX模板解析器
|
||||
@ -805,81 +794,6 @@
|
||||
更新时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Core.Entities.CertificateElement">
|
||||
<summary>
|
||||
证书元素表 (CertificateElement)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.TemplateId">
|
||||
<summary>
|
||||
模板ID (关联 CertificateTemplate)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.Type">
|
||||
<summary>
|
||||
元素类型: Text, Image, QRCode
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.FieldName">
|
||||
<summary>
|
||||
字段名/标签 (维护用)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.BindingKey">
|
||||
<summary>
|
||||
绑定键 (业务数据字段)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.X">
|
||||
<summary>
|
||||
X坐标 (px)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.Y">
|
||||
<summary>
|
||||
Y坐标 (px)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.Width">
|
||||
<summary>
|
||||
宽度 (px)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.Height">
|
||||
<summary>
|
||||
高度 (px)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.FontFamily">
|
||||
<summary>
|
||||
字体
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.FontSize">
|
||||
<summary>
|
||||
字号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.Color">
|
||||
<summary>
|
||||
颜色代码 #RRGGBB
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.StyleJson">
|
||||
<summary>
|
||||
额外样式 JSON
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.Sort">
|
||||
<summary>
|
||||
排序
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.CertificateElement.DeleteMark">
|
||||
<summary>
|
||||
软删除
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Core.Entities.CertificatePlaceholder">
|
||||
<summary>
|
||||
证书占位符表 (CertificatePlaceholder)
|
||||
@ -1540,6 +1454,96 @@
|
||||
更新时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Core.Entities.EventProject">
|
||||
<summary>
|
||||
赛事项目关联表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProject.EventId">
|
||||
<summary>
|
||||
赛事ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProject.ProjectId">
|
||||
<summary>
|
||||
项目ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProject.GenderType">
|
||||
<summary>
|
||||
性别要求 (男/女/不限)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProject.Price">
|
||||
<summary>
|
||||
价格(单位:分)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProject.Groups">
|
||||
<summary>
|
||||
赛事项目组别列表(导航属性)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProject.CreatedTime">
|
||||
<summary>
|
||||
创建时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProject.UpdatedTime">
|
||||
<summary>
|
||||
更新时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Core.Entities.EventProjectGroup">
|
||||
<summary>
|
||||
赛事项目组别表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProjectGroup.EventId">
|
||||
<summary>
|
||||
赛事ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProjectGroup.EventProjectId">
|
||||
<summary>
|
||||
赛事项目ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProjectGroup.ProjectId">
|
||||
<summary>
|
||||
关联的项目ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProjectGroup.ProjectGroupId">
|
||||
<summary>
|
||||
关联的项目组别ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProjectGroup.DeleteMark">
|
||||
<summary>
|
||||
标记删除
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProjectGroup.CreatedUserId">
|
||||
<summary>
|
||||
创建人
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProjectGroup.CreatedTime">
|
||||
<summary>
|
||||
创建时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProjectGroup.UpdatedUserId">
|
||||
<summary>
|
||||
更新人
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.EventProjectGroup.UpdatedTime">
|
||||
<summary>
|
||||
更新时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Core.Entities.EventProjectRegistrationLimit">
|
||||
<summary>
|
||||
赛事项目报名限制表
|
||||
@ -2751,11 +2755,6 @@
|
||||
项目表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.Project.EventId">
|
||||
<summary>
|
||||
关联的赛事ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.Project.Name">
|
||||
<summary>
|
||||
项目名称
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user