2026-02-08 18:09:05 +08:00
|
|
|
|
using YD_Event.Application.Event.Dtos;
|
2026-03-01 22:32:44 +08:00
|
|
|
|
using YD_Event.Application.Project.Dtos;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
using YD_Event.Core.Entities;
|
2026-03-01 22:32:44 +08:00
|
|
|
|
using YD_Event.Core.Enum;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
using MiniExcelLibs;
|
2026-03-01 22:32:44 +08:00
|
|
|
|
using SqlSugar;
|
2026-03-08 15:46:19 +08:00
|
|
|
|
using Mapster;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
|
|
|
|
|
|
namespace YD_Event.Application.Event;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 赛事管理服务
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class EventService : BaseService<EventInfo>, ITransient
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly ISqlSugarRepository<EventInfo> _repository;
|
2026-03-08 15:46:19 +08:00
|
|
|
|
private readonly ISqlSugarRepository<EventUnit> _unitRepository;
|
2026-03-14 09:30:01 +08:00
|
|
|
|
private readonly ISqlSugarRepository<SysProvince> _provinceRepository;
|
|
|
|
|
|
private readonly ISqlSugarRepository<SysCity> _cityRepository;
|
|
|
|
|
|
private readonly ISqlSugarRepository<SysDistrict> _districtRepository;
|
2026-03-01 22:32:44 +08:00
|
|
|
|
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Project> _projectRepository;
|
|
|
|
|
|
private readonly ISqlSugarRepository<ProjectGroup> _projectGroupRepository;
|
|
|
|
|
|
private readonly ISqlSugarRepository<ProjectType> _projectTypeRepository;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
private readonly ISqlSugarRepository<EventRegistrationLimit> _registrationLimitRepository;
|
|
|
|
|
|
private readonly ISqlSugarRepository<EventProjectRegistrationLimit> _projectLimitRepository;
|
|
|
|
|
|
private readonly ISqlSugarRepository<EventFeeConfig> _feeConfigRepository;
|
|
|
|
|
|
private readonly ISqlSugarRepository<EventRegistration> _registrationRepository;
|
|
|
|
|
|
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Merchant> _merchantRepository;
|
|
|
|
|
|
private readonly IIdGenerator _idGenerator;
|
2026-02-28 20:59:18 +08:00
|
|
|
|
private readonly YD_Event.Application.Menu.SysMenuService _sysMenuService;
|
|
|
|
|
|
private readonly YD_Event.Application.Auth.AuthManager _authManager;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
|
|
|
|
|
|
public EventService(
|
|
|
|
|
|
ISqlSugarRepository<EventInfo> repository,
|
2026-03-08 15:46:19 +08:00
|
|
|
|
ISqlSugarRepository<EventUnit> unitRepository,
|
2026-03-14 09:30:01 +08:00
|
|
|
|
ISqlSugarRepository<SysProvince> provinceRepository,
|
|
|
|
|
|
ISqlSugarRepository<SysCity> cityRepository,
|
|
|
|
|
|
ISqlSugarRepository<SysDistrict> districtRepository,
|
2026-03-01 22:32:44 +08:00
|
|
|
|
ISqlSugarRepository<YD_Event.Core.Entities.Project> projectRepository,
|
|
|
|
|
|
ISqlSugarRepository<ProjectGroup> projectGroupRepository,
|
|
|
|
|
|
ISqlSugarRepository<ProjectType> projectTypeRepository,
|
2026-02-08 18:09:05 +08:00
|
|
|
|
ISqlSugarRepository<EventRegistrationLimit> registrationLimitRepository,
|
|
|
|
|
|
ISqlSugarRepository<EventProjectRegistrationLimit> projectLimitRepository,
|
|
|
|
|
|
ISqlSugarRepository<EventFeeConfig> feeConfigRepository,
|
|
|
|
|
|
ISqlSugarRepository<EventRegistration> registrationRepository,
|
|
|
|
|
|
ISqlSugarRepository<YD_Event.Core.Entities.Merchant> merchantRepository,
|
2026-02-28 20:59:18 +08:00
|
|
|
|
IIdGenerator idGenerator,
|
|
|
|
|
|
YD_Event.Application.Menu.SysMenuService sysMenuService,
|
|
|
|
|
|
YD_Event.Application.Auth.AuthManager authManager) : base(repository)
|
2026-02-08 18:09:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
_repository = repository;
|
2026-03-08 15:46:19 +08:00
|
|
|
|
_unitRepository = unitRepository;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
_provinceRepository = provinceRepository;
|
|
|
|
|
|
_cityRepository = cityRepository;
|
|
|
|
|
|
_districtRepository = districtRepository;
|
|
|
|
|
|
_projectRepository = projectRepository;
|
|
|
|
|
|
_projectGroupRepository = projectGroupRepository;
|
2026-03-01 22:32:44 +08:00
|
|
|
|
_projectTypeRepository = projectTypeRepository;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
_registrationLimitRepository = registrationLimitRepository;
|
|
|
|
|
|
_projectLimitRepository = projectLimitRepository;
|
|
|
|
|
|
_feeConfigRepository = feeConfigRepository;
|
|
|
|
|
|
_registrationRepository = registrationRepository;
|
|
|
|
|
|
_merchantRepository = merchantRepository;
|
|
|
|
|
|
_idGenerator = idGenerator;
|
2026-02-28 20:59:18 +08:00
|
|
|
|
_sysMenuService = sysMenuService;
|
|
|
|
|
|
_authManager = authManager;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 分页查询赛事
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
[DisplayName("分页查询赛事")]
|
|
|
|
|
|
public async Task<PageResult<EventListOutput>> Page(EventQueryInput input)
|
|
|
|
|
|
{
|
|
|
|
|
|
var query = _repository.AsQueryable()
|
2026-03-08 15:46:19 +08:00
|
|
|
|
.LeftJoin<EventFeeConfig>((x, f) => x.Id == f.EventId)
|
|
|
|
|
|
.LeftJoin<YD_Event.Core.Entities.Merchant>((x, f, m) => f.MerchantId == m.Id)
|
2026-02-08 18:09:05 +08:00
|
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(input.EventName), x => x.EventName.Contains(input.EventName))
|
|
|
|
|
|
.WhereIF(input.EventType.HasValue, x => x.EventType == input.EventType)
|
|
|
|
|
|
.WhereIF(input.ChargeMode.HasValue, x => x.ChargeMode == input.ChargeMode)
|
|
|
|
|
|
.WhereIF(input.EventStatus.HasValue, x => x.EventStatus == input.EventStatus)
|
|
|
|
|
|
.WhereIF(input.RegistrationStartTime.HasValue, x => x.RegistrationStartTime >= input.RegistrationStartTime)
|
|
|
|
|
|
.WhereIF(input.RegistrationEndTime.HasValue, x => x.RegistrationEndTime <= input.RegistrationEndTime)
|
|
|
|
|
|
.WhereIF(input.MatchStartTime.HasValue, x => x.MatchStartTime >= input.MatchStartTime)
|
|
|
|
|
|
.WhereIF(input.MatchEndTime.HasValue, x => x.MatchEndTime <= input.MatchEndTime)
|
2026-02-28 20:59:18 +08:00
|
|
|
|
.OrderByDescending(x => x.CreatedTime);
|
|
|
|
|
|
|
|
|
|
|
|
// 数据权限过滤
|
|
|
|
|
|
if (!_authManager.IsSuperAdmin)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 检查全部数据权限
|
|
|
|
|
|
var hasAllData = await _sysMenuService.CheckPermission("event:data:all");
|
|
|
|
|
|
if (!hasAllData)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 检查个人数据权限
|
|
|
|
|
|
var hasPersonalData = await _sysMenuService.CheckPermission("event:data:personal");
|
|
|
|
|
|
if (hasPersonalData)
|
|
|
|
|
|
{
|
|
|
|
|
|
var userId = _authManager.UserId;
|
|
|
|
|
|
query = query.Where(x => x.CreatedUserId == userId);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// 无权限,返回空
|
|
|
|
|
|
return new PageResult<EventListOutput>();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var resultQuery = query.OrderByDescending(x => x.CreatedTime)
|
2026-03-08 15:46:19 +08:00
|
|
|
|
.Select((x, f, m) => new EventListOutput
|
2026-02-08 18:09:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
|
EventName = x.EventName,
|
|
|
|
|
|
CoverImage = x.CoverImage,
|
|
|
|
|
|
EventType = x.EventType,
|
|
|
|
|
|
RegistrationType = x.RegistrationType,
|
|
|
|
|
|
ChargeMode = x.ChargeMode,
|
2026-03-08 15:46:19 +08:00
|
|
|
|
MerchantName = m.MerchantName,
|
2026-02-08 18:09:05 +08:00
|
|
|
|
EventStatus = x.EventStatus,
|
|
|
|
|
|
RegistrationStartTime = x.RegistrationStartTime,
|
|
|
|
|
|
RegistrationEndTime = x.RegistrationEndTime,
|
|
|
|
|
|
MatchStartTime = x.MatchStartTime,
|
|
|
|
|
|
MatchEndTime = x.MatchEndTime,
|
2026-03-08 15:46:19 +08:00
|
|
|
|
QrCodeUrl = x.QrCodeUrl
|
2026-02-08 18:09:05 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-02-28 20:59:18 +08:00
|
|
|
|
return await resultQuery.ToPagedListAsync(input);
|
2026-02-08 18:09:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取赛事详情
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="id"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
[DisplayName("获取赛事详情")]
|
|
|
|
|
|
public async Task<EventDetailOutput> GetDetail(long id)
|
|
|
|
|
|
{
|
|
|
|
|
|
var eventInfo = await _repository.GetByIdAsync(id);
|
|
|
|
|
|
if (eventInfo == null) throw new InvalidOperationException("赛事不存在");
|
|
|
|
|
|
|
|
|
|
|
|
var output = eventInfo.Adapt<EventDetailOutput>();
|
|
|
|
|
|
|
|
|
|
|
|
// 1. 获取参与单位
|
2026-03-08 15:46:19 +08:00
|
|
|
|
var units = await _unitRepository.GetListAsync(x => x.EventId == id);
|
|
|
|
|
|
if (units.Any())
|
2026-02-08 18:09:05 +08:00
|
|
|
|
{
|
2026-03-08 15:46:19 +08:00
|
|
|
|
output.Units = units.OrderBy(x => x.Sort).Select(x => x.Adapt<EventUnitDto>()).ToList();
|
2026-02-08 18:09:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-08 15:46:19 +08:00
|
|
|
|
// 2. 自定义字段配置 (JSON)
|
|
|
|
|
|
// output.CustomConfigJson 已自动映射
|
2026-02-08 18:09:05 +08:00
|
|
|
|
|
|
|
|
|
|
// 3. 获取区域名称
|
|
|
|
|
|
if (output.ProvinceId > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var p = await _provinceRepository.GetFirstAsync(x => x.ProvinceId == output.ProvinceId);
|
|
|
|
|
|
output.ProvinceName = p?.ProvinceName;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (output.CityId > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var c = await _cityRepository.GetFirstAsync(x => x.CityId == output.CityId);
|
|
|
|
|
|
output.CityName = c?.CityName;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (output.DistrictId > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var d = await _districtRepository.GetFirstAsync(x => x.DistrictId == output.DistrictId);
|
|
|
|
|
|
output.DistrictName = d?.DistrictName;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 获取项目列表 (Step 3)
|
|
|
|
|
|
var projects = await _projectRepository.GetListAsync(x => x.EventId == id);
|
|
|
|
|
|
if (projects.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));
|
2026-03-01 22:32:44 +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
|
|
|
|
|
|
|
|
|
|
output.Projects = projects.Select(p =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var dto = p.Adapt<EventProjectInput>();
|
2026-03-01 22:32:44 +08:00
|
|
|
|
var type = types.FirstOrDefault(x => x.Id == p.ProjectTypeId);
|
|
|
|
|
|
if (type != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
dto.ProjectTypeName = type.Name;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dto.Groups = groups.Where(g => g.ProjectId == p.Id).Select(g => g.Adapt<ProjectGroupInput>()).ToList();
|
2026-02-08 18:09:05 +08:00
|
|
|
|
var limit = projectLimits.FirstOrDefault(l => l.ProjectId == p.Id);
|
|
|
|
|
|
if (limit != null) dto.LimitCount = limit.LimitCount;
|
|
|
|
|
|
return dto;
|
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 获取报名限制 (Step 3)
|
|
|
|
|
|
var registrationLimit = await _registrationLimitRepository.GetFirstAsync(x => x.EventId == id);
|
|
|
|
|
|
if (registrationLimit != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
output.RegistrationLimit = registrationLimit.Adapt<EventRegistrationLimitInput>();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 6. 获取费用配置 (Step 4)
|
|
|
|
|
|
var feeConfig = await _feeConfigRepository.GetFirstAsync(x => x.EventId == id);
|
|
|
|
|
|
if (feeConfig != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
output.FeeConfig = feeConfig.Adapt<EventFeeConfigInput>();
|
|
|
|
|
|
// 获取商户详情
|
2026-03-08 15:46:19 +08:00
|
|
|
|
if (feeConfig.MerchantId.HasValue && feeConfig.MerchantId.Value > 0)
|
2026-02-08 18:09:05 +08:00
|
|
|
|
{
|
2026-03-08 15:46:19 +08:00
|
|
|
|
var merchant = await _merchantRepository.GetByIdAsync(feeConfig.MerchantId.Value);
|
2026-02-08 18:09:05 +08:00
|
|
|
|
if (merchant != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
output.FeeConfig.MerchantName = merchant.MerchantName;
|
|
|
|
|
|
output.FeeConfig.CreditCode = merchant.CreditCode;
|
|
|
|
|
|
output.FeeConfig.BankName = merchant.BankName;
|
|
|
|
|
|
output.FeeConfig.AccountNumber = merchant.AccountNumber;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return output;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-03-08 15:46:19 +08:00
|
|
|
|
/// 新增赛事 (旧接口,保留兼容)
|
2026-02-08 18:09:05 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
[UnitOfWork]
|
|
|
|
|
|
[DisplayName("新增赛事")]
|
|
|
|
|
|
public async Task Add(AddEventInput input)
|
|
|
|
|
|
{
|
|
|
|
|
|
var eventInfo = input.Adapt<EventInfo>();
|
|
|
|
|
|
eventInfo.Id = _idGenerator.NewLong();
|
|
|
|
|
|
eventInfo.CreatedTime = DateTime.Now;
|
|
|
|
|
|
eventInfo.Status = AvailabilityStatus.Enable;
|
|
|
|
|
|
|
2026-03-08 15:46:19 +08:00
|
|
|
|
// 自动生成二维码URL (模拟)
|
|
|
|
|
|
eventInfo.QrCodeUrl = $"/pages/event/detail?id={eventInfo.Id}";
|
|
|
|
|
|
|
2026-02-08 18:09:05 +08:00
|
|
|
|
var now = DateTime.Now;
|
2026-03-08 15:46:19 +08:00
|
|
|
|
if (now < eventInfo.RegistrationStartTime) eventInfo.EventStatus = EventStatus.Enrolling; // Logic might need adjustment
|
2026-02-08 18:09:05 +08:00
|
|
|
|
else if (now > eventInfo.MatchEndTime) eventInfo.EventStatus = EventStatus.Ended;
|
|
|
|
|
|
else if (now >= eventInfo.MatchStartTime) eventInfo.EventStatus = EventStatus.Ongoing;
|
|
|
|
|
|
else eventInfo.EventStatus = EventStatus.Enrolling;
|
|
|
|
|
|
|
|
|
|
|
|
await _repository.InsertAsync(eventInfo);
|
|
|
|
|
|
|
|
|
|
|
|
// 1. 保存参与单位
|
2026-03-08 15:46:19 +08:00
|
|
|
|
if (input.Units != null && input.Units.Any())
|
2026-02-08 18:09:05 +08:00
|
|
|
|
{
|
2026-03-08 15:46:19 +08:00
|
|
|
|
var units = input.Units.Select(u => {
|
|
|
|
|
|
var entity = u.Adapt<EventUnit>();
|
|
|
|
|
|
entity.Id = _idGenerator.NewLong();
|
|
|
|
|
|
entity.EventId = eventInfo.Id;
|
|
|
|
|
|
return entity;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
}).ToList();
|
2026-03-08 15:46:19 +08:00
|
|
|
|
await _unitRepository.InsertRangeAsync(units);
|
2026-02-08 18:09:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-08 15:46:19 +08:00
|
|
|
|
// 2. 自定义字段 (JSON) - Already in eventInfo
|
|
|
|
|
|
|
2026-02-08 18:09:05 +08:00
|
|
|
|
// 3. 保存项目信息 (Step 3)
|
|
|
|
|
|
if (input.Projects != null && input.Projects.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var projInput in input.Projects)
|
|
|
|
|
|
{
|
2026-03-01 22:32:44 +08:00
|
|
|
|
var project = projInput.Adapt<YD_Event.Core.Entities.Project>();
|
2026-02-08 18:09:05 +08:00
|
|
|
|
project.Id = _idGenerator.NewLong();
|
|
|
|
|
|
project.EventId = eventInfo.Id;
|
|
|
|
|
|
project.Status = AvailabilityStatus.Enable;
|
|
|
|
|
|
project.CreatedTime = DateTime.Now;
|
|
|
|
|
|
await _projectRepository.InsertAsync(project);
|
|
|
|
|
|
|
|
|
|
|
|
// 保存项目分组
|
|
|
|
|
|
if (projInput.Groups != null && projInput.Groups.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
var groups = projInput.Groups.Select(g =>
|
|
|
|
|
|
{
|
2026-03-01 22:32:44 +08:00
|
|
|
|
var group = g.Adapt<ProjectGroup>();
|
2026-02-08 18:09:05 +08:00
|
|
|
|
group.Id = _idGenerator.NewLong();
|
|
|
|
|
|
group.ProjectId = project.Id;
|
|
|
|
|
|
return group;
|
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
await _projectGroupRepository.InsertRangeAsync(groups);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 保存项目报名限制 (Step 3 - Project Limit)
|
|
|
|
|
|
if (projInput.LimitCount.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
var projLimit = new EventProjectRegistrationLimit
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = _idGenerator.NewLong(),
|
|
|
|
|
|
EventId = eventInfo.Id,
|
|
|
|
|
|
ProjectId = project.Id,
|
|
|
|
|
|
LimitCount = projInput.LimitCount.Value
|
|
|
|
|
|
};
|
|
|
|
|
|
await _projectLimitRepository.InsertAsync(projLimit);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 保存报名限制 (Step 3 - Individual/Team Limit)
|
|
|
|
|
|
if (input.RegistrationLimit != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var limit = input.RegistrationLimit.Adapt<EventRegistrationLimit>();
|
|
|
|
|
|
limit.Id = _idGenerator.NewLong();
|
|
|
|
|
|
limit.EventId = eventInfo.Id;
|
|
|
|
|
|
await _registrationLimitRepository.InsertAsync(limit);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-03-08 15:46:19 +08:00
|
|
|
|
/// 更新赛事 (旧接口,保留兼容)
|
2026-02-08 18:09:05 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
[UnitOfWork]
|
|
|
|
|
|
[DisplayName("更新赛事")]
|
|
|
|
|
|
public async Task Update(UpdateEventInput input)
|
|
|
|
|
|
{
|
|
|
|
|
|
var eventInfo = await _repository.GetByIdAsync(input.Id);
|
|
|
|
|
|
if (eventInfo == null) throw new InvalidOperationException("赛事不存在");
|
|
|
|
|
|
|
|
|
|
|
|
var oldEventName = eventInfo.EventName;
|
|
|
|
|
|
input.Adapt(eventInfo);
|
|
|
|
|
|
eventInfo.EventName = oldEventName; // 赛事名称不允许修改
|
|
|
|
|
|
|
|
|
|
|
|
eventInfo.UpdatedTime = DateTime.Now;
|
|
|
|
|
|
|
2026-03-08 15:46:19 +08:00
|
|
|
|
// 更新状态逻辑
|
2026-02-08 18:09:05 +08:00
|
|
|
|
var now = DateTime.Now;
|
|
|
|
|
|
if (now > eventInfo.MatchEndTime) eventInfo.EventStatus = EventStatus.Ended;
|
|
|
|
|
|
else if (now >= eventInfo.MatchStartTime) eventInfo.EventStatus = EventStatus.Ongoing;
|
|
|
|
|
|
else eventInfo.EventStatus = EventStatus.Enrolling;
|
|
|
|
|
|
|
|
|
|
|
|
await _repository.UpdateAsync(eventInfo);
|
|
|
|
|
|
|
|
|
|
|
|
// 1. 更新参与单位
|
2026-03-08 15:46:19 +08:00
|
|
|
|
await _unitRepository.DeleteAsync(x => x.EventId == input.Id);
|
|
|
|
|
|
if (input.Units != null && input.Units.Any())
|
2026-02-08 18:09:05 +08:00
|
|
|
|
{
|
2026-03-08 15:46:19 +08:00
|
|
|
|
var units = input.Units.Select(u => {
|
|
|
|
|
|
var entity = u.Adapt<EventUnit>();
|
|
|
|
|
|
entity.Id = _idGenerator.NewLong();
|
|
|
|
|
|
entity.EventId = eventInfo.Id;
|
|
|
|
|
|
return entity;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
}).ToList();
|
2026-03-08 15:46:19 +08:00
|
|
|
|
await _unitRepository.InsertRangeAsync(units);
|
2026-02-08 18:09:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-08 15:46:19 +08:00
|
|
|
|
// 2. 更新自定义字段 (JSON) - Updated in eventInfo
|
|
|
|
|
|
|
2026-02-08 18:09:05 +08:00
|
|
|
|
// 3. 更新项目信息
|
|
|
|
|
|
var oldProjects = await _projectRepository.GetListAsync(x => x.EventId == input.Id);
|
|
|
|
|
|
var oldProjectIds = oldProjects.Select(x => x.Id).ToList();
|
|
|
|
|
|
|
|
|
|
|
|
if (oldProjectIds.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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (input.Projects != null && input.Projects.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var projInput in input.Projects)
|
|
|
|
|
|
{
|
2026-03-01 22:32:44 +08:00
|
|
|
|
var project = projInput.Adapt<YD_Event.Core.Entities.Project>();
|
2026-02-08 18:09:05 +08:00
|
|
|
|
project.Id = _idGenerator.NewLong();
|
|
|
|
|
|
project.EventId = eventInfo.Id;
|
|
|
|
|
|
project.Status = AvailabilityStatus.Enable;
|
|
|
|
|
|
project.CreatedTime = DateTime.Now;
|
|
|
|
|
|
await _projectRepository.InsertAsync(project);
|
|
|
|
|
|
|
|
|
|
|
|
if (projInput.Groups != null && projInput.Groups.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
var groups = projInput.Groups.Select(g =>
|
|
|
|
|
|
{
|
2026-03-01 22:32:44 +08:00
|
|
|
|
var group = g.Adapt<ProjectGroup>();
|
2026-02-08 18:09:05 +08:00
|
|
|
|
group.Id = _idGenerator.NewLong();
|
|
|
|
|
|
group.ProjectId = project.Id;
|
|
|
|
|
|
return group;
|
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
await _projectGroupRepository.InsertRangeAsync(groups);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (projInput.LimitCount.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
var projLimit = new EventProjectRegistrationLimit
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = _idGenerator.NewLong(),
|
|
|
|
|
|
EventId = eventInfo.Id,
|
|
|
|
|
|
ProjectId = project.Id,
|
|
|
|
|
|
LimitCount = projInput.LimitCount.Value
|
|
|
|
|
|
};
|
|
|
|
|
|
await _projectLimitRepository.InsertAsync(projLimit);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 更新报名限制
|
|
|
|
|
|
await _registrationLimitRepository.DeleteAsync(x => x.EventId == input.Id);
|
|
|
|
|
|
if (input.RegistrationLimit != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var limit = input.RegistrationLimit.Adapt<EventRegistrationLimit>();
|
|
|
|
|
|
limit.Id = _idGenerator.NewLong();
|
|
|
|
|
|
limit.EventId = eventInfo.Id;
|
|
|
|
|
|
await _registrationLimitRepository.InsertAsync(limit);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 导出赛事
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
[DisplayName("导出赛事")]
|
|
|
|
|
|
public async Task<byte[]> Export(EventExportInput input)
|
|
|
|
|
|
{
|
|
|
|
|
|
var query = _repository.AsQueryable()
|
2026-03-08 15:46:19 +08:00
|
|
|
|
.LeftJoin<EventFeeConfig>((e, f) => e.Id == f.EventId)
|
|
|
|
|
|
.LeftJoin<YD_Event.Core.Entities.Merchant>((e, f, m) => f.MerchantId == m.Id)
|
2026-02-08 18:09:05 +08:00
|
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(input.EventName), e => e.EventName.Contains(input.EventName))
|
|
|
|
|
|
.WhereIF(input.EventType.HasValue, e => e.EventType == input.EventType)
|
|
|
|
|
|
.WhereIF(input.ChargeMode.HasValue, e => e.ChargeMode == input.ChargeMode)
|
|
|
|
|
|
.WhereIF(input.EventStatus.HasValue, e => e.EventStatus == input.EventStatus)
|
|
|
|
|
|
.WhereIF(input.RegistrationStartTime.HasValue, e => e.RegistrationStartTime >= input.RegistrationStartTime)
|
|
|
|
|
|
.WhereIF(input.RegistrationEndTime.HasValue, e => e.RegistrationEndTime <= input.RegistrationEndTime)
|
|
|
|
|
|
.WhereIF(input.MatchStartTime.HasValue, e => e.MatchStartTime >= input.MatchStartTime)
|
|
|
|
|
|
.WhereIF(input.MatchEndTime.HasValue, e => e.MatchEndTime <= input.MatchEndTime)
|
2026-03-08 15:46:19 +08:00
|
|
|
|
.Select((e, f, m) => new
|
2026-02-08 18:09:05 +08:00
|
|
|
|
{
|
2026-03-08 15:46:19 +08:00
|
|
|
|
e.Id,
|
2026-02-08 18:09:05 +08:00
|
|
|
|
e.EventName,
|
|
|
|
|
|
e.EventType,
|
|
|
|
|
|
e.ChargeMode,
|
|
|
|
|
|
e.RegistrationType,
|
|
|
|
|
|
e.EventStatus,
|
|
|
|
|
|
e.RegistrationStartTime,
|
|
|
|
|
|
e.RegistrationEndTime,
|
|
|
|
|
|
e.MaterialUploadEndTime,
|
|
|
|
|
|
e.MatchStartTime,
|
|
|
|
|
|
e.MatchEndTime,
|
|
|
|
|
|
e.DetailAddress,
|
|
|
|
|
|
MerchantName = m.MerchantName
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
var list = await query.ToListAsync();
|
2026-03-08 15:46:19 +08:00
|
|
|
|
var eventIds = list.Select(x => x.Id).ToList();
|
|
|
|
|
|
var units = await _unitRepository.GetListAsync(x => eventIds.Contains(x.EventId));
|
2026-02-08 18:09:05 +08:00
|
|
|
|
|
|
|
|
|
|
var exportData = new List<Dictionary<string, object>>();
|
|
|
|
|
|
foreach (var item in list)
|
|
|
|
|
|
{
|
|
|
|
|
|
var row = new Dictionary<string, object>();
|
|
|
|
|
|
var fields = input.ExportFields ?? new List<string>();
|
|
|
|
|
|
bool all = fields.Count == 0;
|
2026-03-08 15:46:19 +08:00
|
|
|
|
|
|
|
|
|
|
var eventUnits = units.Where(u => u.EventId == item.Id).ToList();
|
|
|
|
|
|
var hostNames = string.Join(",", eventUnits.Where(u => u.UnitType == UnitType.Host).Select(u => u.UnitName));
|
|
|
|
|
|
var organizerNames = string.Join(",", eventUnits.Where(u => u.UnitType == UnitType.Organizer).Select(u => u.UnitName));
|
|
|
|
|
|
var coOrganizerNames = string.Join(",", eventUnits.Where(u => u.UnitType == UnitType.CoOrganizer).Select(u => u.UnitName));
|
|
|
|
|
|
var sponsorNames = string.Join(",", eventUnits.Where(u => u.UnitType == UnitType.Sponsor).Select(u => u.UnitName));
|
2026-02-08 18:09:05 +08:00
|
|
|
|
|
|
|
|
|
|
if (all || fields.Contains("赛事名称")) row["赛事名称"] = item.EventName;
|
|
|
|
|
|
if (all || fields.Contains("赛事类型")) row["赛事类型"] = item.EventType.ToString(); // TODO: Enum Description
|
|
|
|
|
|
if (all || fields.Contains("收费模式")) row["收费模式"] = item.ChargeMode.ToString();
|
|
|
|
|
|
if (all || fields.Contains("收款商户")) row["收款商户"] = item.MerchantName;
|
|
|
|
|
|
if (all || fields.Contains("报名方式")) row["报名方式"] = item.RegistrationType.ToString();
|
|
|
|
|
|
if (all || fields.Contains("赛事状态")) row["赛事状态"] = item.EventStatus.ToString();
|
|
|
|
|
|
if (all || fields.Contains("报名起止时间")) row["报名起止时间"] = $"{item.RegistrationStartTime:yyyy-MM-dd HH:mm} - {item.RegistrationEndTime:yyyy-MM-dd HH:mm}";
|
|
|
|
|
|
if (all || fields.Contains("上传素材截至时间")) row["上传素材截至时间"] = item.MaterialUploadEndTime?.ToString("yyyy-MM-dd HH:mm");
|
|
|
|
|
|
if (all || fields.Contains("比赛起止时间")) row["比赛起止时间"] = $"{item.MatchStartTime:yyyy-MM-dd HH:mm} - {item.MatchEndTime:yyyy-MM-dd HH:mm}";
|
|
|
|
|
|
if (all || fields.Contains("赛事地址")) row["赛事地址"] = item.DetailAddress;
|
2026-03-08 15:46:19 +08:00
|
|
|
|
if (all || fields.Contains("主办单位")) row["主办单位"] = hostNames;
|
|
|
|
|
|
if (all || fields.Contains("承办单位")) row["承办单位"] = organizerNames;
|
|
|
|
|
|
if (all || fields.Contains("协办单位")) row["协办单位"] = coOrganizerNames;
|
|
|
|
|
|
if (all || fields.Contains("赞助单位")) row["赞助单位"] = sponsorNames;
|
2026-02-08 18:09:05 +08:00
|
|
|
|
|
|
|
|
|
|
exportData.Add(row);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
using var stream = new MemoryStream();
|
|
|
|
|
|
stream.SaveAs(exportData);
|
|
|
|
|
|
return stream.ToArray();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 删除赛事
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="dto"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
[DisplayName("删除赛事")]
|
|
|
|
|
|
public override async Task Delete(KeyDto dto)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (await _registrationRepository.IsAnyAsync(x => x.EventId == dto.Id))
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new InvalidOperationException("已有人员报名此赛事,暂不支持删除");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 软删除 EventInfo
|
|
|
|
|
|
await base.Delete(dto);
|
|
|
|
|
|
// 关联表物理删除或保留?通常保留。如果需要清理:
|
2026-03-08 15:46:19 +08:00
|
|
|
|
// await _unitRepository.DeleteAsync(x => x.EventId == dto.Id);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 阶段1:保存基本信息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
/// <returns>EventId</returns>
|
|
|
|
|
|
[UnitOfWork]
|
|
|
|
|
|
[DisplayName("保存基本信息")]
|
|
|
|
|
|
public async Task<long> SaveBasicInfo(SaveBasicInfoInput input)
|
|
|
|
|
|
{
|
|
|
|
|
|
EventInfo eventInfo;
|
|
|
|
|
|
if (input.EventId.HasValue && input.EventId.Value > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
eventInfo = await _repository.GetByIdAsync(input.EventId.Value);
|
|
|
|
|
|
if (eventInfo == null) throw new InvalidOperationException("赛事不存在");
|
|
|
|
|
|
input.Adapt(eventInfo);
|
|
|
|
|
|
eventInfo.UpdatedTime = DateTime.Now;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
eventInfo = input.Adapt<EventInfo>();
|
|
|
|
|
|
eventInfo.Id = _idGenerator.NewLong();
|
|
|
|
|
|
eventInfo.CreatedTime = DateTime.Now;
|
|
|
|
|
|
eventInfo.Status = AvailabilityStatus.Enable; // 默认启用
|
|
|
|
|
|
eventInfo.ProcessStatus = ProcessStatus.BasicInfoCompleted;
|
|
|
|
|
|
|
|
|
|
|
|
// 初始状态计算
|
|
|
|
|
|
var now = DateTime.Now;
|
|
|
|
|
|
if (now > eventInfo.MatchEndTime) eventInfo.EventStatus = EventStatus.Ended;
|
|
|
|
|
|
else if (now >= eventInfo.MatchStartTime) eventInfo.EventStatus = EventStatus.Ongoing;
|
|
|
|
|
|
else eventInfo.EventStatus = EventStatus.Enrolling;
|
|
|
|
|
|
|
|
|
|
|
|
await _repository.InsertAsync(eventInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态
|
|
|
|
|
|
if (eventInfo.ProcessStatus == ProcessStatus.NotStarted)
|
|
|
|
|
|
{
|
|
|
|
|
|
eventInfo.ProcessStatus = ProcessStatus.BasicInfoCompleted;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await _repository.UpdateAsync(eventInfo);
|
|
|
|
|
|
return eventInfo.Id;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 阶段2:保存参与单位
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
[UnitOfWork]
|
|
|
|
|
|
[DisplayName("保存参与单位")]
|
|
|
|
|
|
public async Task SaveUnits(SaveUnitsInput input)
|
|
|
|
|
|
{
|
|
|
|
|
|
var eventInfo = await _repository.GetByIdAsync(input.EventId);
|
|
|
|
|
|
if (eventInfo == null) throw new InvalidOperationException("赛事不存在");
|
|
|
|
|
|
|
|
|
|
|
|
if (eventInfo.ProcessStatus < ProcessStatus.BasicInfoCompleted)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new InvalidOperationException("请先完成基本信息配置");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 全量更新单位
|
|
|
|
|
|
await _unitRepository.DeleteAsync(x => x.EventId == input.EventId);
|
|
|
|
|
|
|
|
|
|
|
|
if (input.Units != null && input.Units.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
var units = input.Units.Select(u => {
|
|
|
|
|
|
var entity = u.Adapt<EventUnit>();
|
|
|
|
|
|
entity.Id = _idGenerator.NewLong();
|
|
|
|
|
|
entity.EventId = input.EventId;
|
|
|
|
|
|
return entity;
|
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
await _unitRepository.InsertRangeAsync(units);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新流程状态
|
|
|
|
|
|
if (eventInfo.ProcessStatus < ProcessStatus.ParticipantsCompleted)
|
|
|
|
|
|
{
|
|
|
|
|
|
eventInfo.ProcessStatus = ProcessStatus.ParticipantsCompleted;
|
|
|
|
|
|
await _repository.UpdateAsync(eventInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 阶段3:保存项目与限报配置
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
[UnitOfWork]
|
|
|
|
|
|
[DisplayName("保存项目与限报配置")]
|
|
|
|
|
|
public async Task SaveProjects(SaveProjectsInput input)
|
|
|
|
|
|
{
|
|
|
|
|
|
var eventInfo = await _repository.GetByIdAsync(input.EventId);
|
|
|
|
|
|
if (eventInfo == null) throw new InvalidOperationException("赛事不存在");
|
|
|
|
|
|
|
|
|
|
|
|
if (eventInfo.ProcessStatus < ProcessStatus.ParticipantsCompleted)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new InvalidOperationException("请先完成参与单位配置");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 1. 更新项目信息 (全量替换)
|
|
|
|
|
|
var oldProjects = await _projectRepository.GetListAsync(x => x.EventId == input.EventId);
|
|
|
|
|
|
var oldProjectIds = oldProjects.Select(x => x.Id).ToList();
|
|
|
|
|
|
|
|
|
|
|
|
if (oldProjectIds.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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
return group;
|
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
await _projectGroupRepository.InsertRangeAsync(groups);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (projInput.LimitCount.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
var projLimit = new EventProjectRegistrationLimit
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = _idGenerator.NewLong(),
|
|
|
|
|
|
EventId = input.EventId,
|
|
|
|
|
|
ProjectId = project.Id,
|
|
|
|
|
|
LimitCount = projInput.LimitCount.Value
|
|
|
|
|
|
};
|
|
|
|
|
|
await _projectLimitRepository.InsertAsync(projLimit);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 更新报名限制
|
|
|
|
|
|
await _registrationLimitRepository.DeleteAsync(x => x.EventId == input.EventId);
|
|
|
|
|
|
if (input.RegistrationLimit != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var limit = input.RegistrationLimit.Adapt<EventRegistrationLimit>();
|
|
|
|
|
|
limit.Id = _idGenerator.NewLong();
|
|
|
|
|
|
limit.EventId = input.EventId;
|
|
|
|
|
|
await _registrationLimitRepository.InsertAsync(limit);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新流程状态
|
|
|
|
|
|
if (eventInfo.ProcessStatus < ProcessStatus.ProjectConfigCompleted)
|
|
|
|
|
|
{
|
|
|
|
|
|
eventInfo.ProcessStatus = ProcessStatus.ProjectConfigCompleted;
|
|
|
|
|
|
await _repository.UpdateAsync(eventInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 阶段4:保存费用与账户配置
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
/// <returns>二维码URL</returns>
|
|
|
|
|
|
[UnitOfWork]
|
|
|
|
|
|
[DisplayName("保存费用与账户配置")]
|
|
|
|
|
|
public async Task<string> SaveFeeConfig(SaveFeeConfigInput input)
|
|
|
|
|
|
{
|
|
|
|
|
|
var eventInfo = await _repository.GetByIdAsync(input.EventId);
|
|
|
|
|
|
if (eventInfo == null) throw new InvalidOperationException("赛事不存在");
|
|
|
|
|
|
|
|
|
|
|
|
if (eventInfo.ProcessStatus < ProcessStatus.ProjectConfigCompleted)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new InvalidOperationException("请先完成项目配置");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新费用配置
|
|
|
|
|
|
await _feeConfigRepository.DeleteAsync(x => x.EventId == input.EventId);
|
|
|
|
|
|
if (input.FeeConfig != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var feeConfig = input.FeeConfig.Adapt<EventFeeConfig>();
|
|
|
|
|
|
feeConfig.Id = _idGenerator.NewLong();
|
|
|
|
|
|
feeConfig.EventId = input.EventId;
|
|
|
|
|
|
await _feeConfigRepository.InsertAsync(feeConfig);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 生成二维码URL
|
|
|
|
|
|
var qrCodeUrl = $"/pages/event/detail?id={eventInfo.Id}";
|
|
|
|
|
|
eventInfo.QrCodeUrl = qrCodeUrl;
|
|
|
|
|
|
|
|
|
|
|
|
// 更新流程状态和赛事状态
|
|
|
|
|
|
eventInfo.ProcessStatus = ProcessStatus.FeeConfigCompleted;
|
|
|
|
|
|
|
|
|
|
|
|
// 重新计算并确认赛事状态
|
|
|
|
|
|
var now = DateTime.Now;
|
|
|
|
|
|
if (now > eventInfo.MatchEndTime) eventInfo.EventStatus = EventStatus.Ended;
|
|
|
|
|
|
else if (now >= eventInfo.MatchStartTime) eventInfo.EventStatus = EventStatus.Ongoing;
|
|
|
|
|
|
else eventInfo.EventStatus = EventStatus.Enrolling;
|
|
|
|
|
|
|
|
|
|
|
|
await _repository.UpdateAsync(eventInfo);
|
|
|
|
|
|
|
|
|
|
|
|
return qrCodeUrl;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取赛事填报进度
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="eventId"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
[DisplayName("获取赛事填报进度")]
|
|
|
|
|
|
public async Task<EventProgressOutput> GetProgress(long eventId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var eventInfo = await _repository.GetByIdAsync(eventId);
|
|
|
|
|
|
if (eventInfo == null) throw new InvalidOperationException("赛事不存在");
|
|
|
|
|
|
|
|
|
|
|
|
var completedStages = new List<string>();
|
|
|
|
|
|
if (eventInfo.ProcessStatus >= ProcessStatus.BasicInfoCompleted) completedStages.Add("basic");
|
|
|
|
|
|
if (eventInfo.ProcessStatus >= ProcessStatus.ParticipantsCompleted) completedStages.Add("units");
|
|
|
|
|
|
if (eventInfo.ProcessStatus >= ProcessStatus.ProjectConfigCompleted) completedStages.Add("projects");
|
|
|
|
|
|
if (eventInfo.ProcessStatus >= ProcessStatus.FeeConfigCompleted) completedStages.Add("fee");
|
|
|
|
|
|
|
|
|
|
|
|
return new EventProgressOutput
|
|
|
|
|
|
{
|
|
|
|
|
|
EventId = eventInfo.Id,
|
|
|
|
|
|
ProcessStatus = eventInfo.ProcessStatus,
|
|
|
|
|
|
CompletedStages = completedStages
|
|
|
|
|
|
};
|
2026-02-08 18:09:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|