From 5abbae9e6c6737d97d7c68a812e3717a8fbc9c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=A2=93=E5=BD=AD?= Date: Tue, 31 Mar 2026 17:38:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD=E5=90=88?= =?UTF-8?q?=E5=B9=B6=EF=BC=8C=E9=A1=B9=E7=9B=AE=E5=8F=82=E4=B8=8E=E4=BA=BA?= =?UTF-8?q?=E6=95=B0=E9=87=8D=E6=96=B0=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppUser/AppUserService.cs | 4 +- .../Event/EventArrangementService.cs | 141 +++++++--------- .../Event/UserEventRegistrationService.cs | 30 +++- .../Project/ProjectService.cs | 158 +++++++++++++++++- YD_Event.Application/YD_Event.Application.xml | 36 ++++ .../Domain/Export/ExcelExportBase.cs | 146 ++++++++++++++++ .../Entities/EventParticipationRecord.cs | 4 +- YD_Event.Core/Enum/ParticipationStatus.cs | 33 ++++ YD_Event.Core/YD_Event.Core.csproj | 1 + YD_Event.Core/YD_Event.Core.xml | 82 ++++++++- 10 files changed, 540 insertions(+), 95 deletions(-) create mode 100644 YD_Event.Core/Domain/Export/ExcelExportBase.cs create mode 100644 YD_Event.Core/Enum/ParticipationStatus.cs diff --git a/YD_Event.Application/AppUser/AppUserService.cs b/YD_Event.Application/AppUser/AppUserService.cs index 5ece55a..b1faba7 100644 --- a/YD_Event.Application/AppUser/AppUserService.cs +++ b/YD_Event.Application/AppUser/AppUserService.cs @@ -137,8 +137,8 @@ public class AppUserService : BaseService, ITransient [DisplayName("统一新增/编辑成员")] public async Task SaveUnifiedMember(CreateOrUpdateMemberInput input) { - // 仅在新增领队/教练时验证验证码 - if (!input.Id.HasValue && (input.PersonType == PersonType.Leader || input.PersonType == PersonType.Coach)) + // 仅在新增运动员时验证验证码 + if (!input.Id.HasValue && input.PersonType == PersonType.Athlete) { if (string.IsNullOrWhiteSpace(input.VerificationCode)) { diff --git a/YD_Event.Application/Event/EventArrangementService.cs b/YD_Event.Application/Event/EventArrangementService.cs index 19007ca..39b1aa2 100644 --- a/YD_Event.Application/Event/EventArrangementService.cs +++ b/YD_Event.Application/Event/EventArrangementService.cs @@ -1,4 +1,5 @@ using YD_Event.Application.Event.Dtos; +using YD_Event.Core.Domain.Export; using YD_Event.Core.Entities; using MiniExcelLibs; using SqlSugar; @@ -154,9 +155,10 @@ public class EventArrangementService : BaseService 0 ? proj.VenueCount : 1; // 获取参赛人员(排序:组别 -> ID) + // 放宽查询条件,只要不是取消状态的报名都包含进来 var persons = await _personRepository.AsQueryable() .InnerJoin((p, r) => p.RegistrationId == r.Id) - .Where((p, r) => p.ProjectId == eventProj.Id && (r.PaymentStatus == 1 || r.RegistrationStatus == 2)) + .Where((p, r) => p.ProjectId == eventProj.Id && r.RegistrationStatus != 4) .OrderBy(p => p.GroupName) .OrderBy(p => p.Id) .Select((p, r) => new { @@ -205,92 +207,67 @@ public class EventArrangementService : BaseService x.Id == eventId); var data = await Preview(eventId); - // 设置 EPPlus 许可证上下文 - ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial; - - using var package = new ExcelPackage(); - var worksheet = package.Workbook.Worksheets.Add("编排表"); - - // 第一行:赛事标题(合并单元格 A1:G1) - worksheet.Cells["A1:G1"].Merge = true; - worksheet.Cells["A1"].Value = eventInfo?.EventName ?? "赛事编排表"; - - // 设置标题样式 - var titleStyle = worksheet.Cells["A1:G1"].Style; - titleStyle.Font.Bold = true; - titleStyle.Font.Size = 14; - titleStyle.HorizontalAlignment = ExcelHorizontalAlignment.Center; - titleStyle.VerticalAlignment = ExcelVerticalAlignment.Center; - titleStyle.Fill.PatternType = ExcelFillStyle.Solid; - titleStyle.Fill.BackgroundColor.SetColor(Color.FromArgb(255, 217, 179)); // 浅橙色 - - // 第二行:列标题 - string[] headers = { "时间", "参赛项目", "参赛组别", "参赛队伍", "运动员姓名", "场次", "场地" }; - for (int i = 0; i < headers.Length; i++) + var exporter = new ArrangementExporter(data, eventInfo); + return await exporter.ExportAsync(); + } + + /// + /// 编排导出器 + /// + private class ArrangementExporter : ExcelExportBase + { + private readonly List _data; + private readonly EventInfo _eventInfo; + + public ArrangementExporter(List data, EventInfo eventInfo) { - worksheet.Cells[2, i + 1].Value = headers[i]; + _data = data ?? new List(); + _eventInfo = eventInfo; } - - // 设置列标题样式 - var headerStyle = worksheet.Cells["A2:G2"].Style; - headerStyle.Font.Bold = true; - headerStyle.Font.Size = 11; - headerStyle.HorizontalAlignment = ExcelHorizontalAlignment.Center; - headerStyle.VerticalAlignment = ExcelVerticalAlignment.Center; - headerStyle.Fill.PatternType = ExcelFillStyle.Solid; - headerStyle.Fill.BackgroundColor.SetColor(Color.FromArgb(204, 255, 204)); // 浅绿色 - headerStyle.Border.Top.Style = ExcelBorderStyle.Thin; - headerStyle.Border.Bottom.Style = ExcelBorderStyle.Thin; - headerStyle.Border.Left.Style = ExcelBorderStyle.Thin; - headerStyle.Border.Right.Style = ExcelBorderStyle.Thin; - - // 填充数据行 - for (int i = 0; i < data.Count; i++) + + public override async Task ExportAsync() { - var item = data[i]; - int rowIndex = i + 3; - - worksheet.Cells[rowIndex, 1].Value = item.TimeRange; - worksheet.Cells[rowIndex, 2].Value = item.ProjectName; - worksheet.Cells[rowIndex, 3].Value = item.GroupName; - worksheet.Cells[rowIndex, 4].Value = item.TeamName ?? ""; - worksheet.Cells[rowIndex, 5].Value = item.AthleteName; - worksheet.Cells[rowIndex, 6].Value = item.SessionIndex; - worksheet.Cells[rowIndex, 7].Value = item.VenueIndex; - - // 设置数据行样式 - var rowStyle = worksheet.Cells[$"A{rowIndex}:G{rowIndex}"].Style; - rowStyle.HorizontalAlignment = ExcelHorizontalAlignment.Center; - rowStyle.VerticalAlignment = ExcelVerticalAlignment.Center; - rowStyle.Border.Top.Style = ExcelBorderStyle.Thin; - rowStyle.Border.Bottom.Style = ExcelBorderStyle.Thin; - rowStyle.Border.Left.Style = ExcelBorderStyle.Thin; - rowStyle.Border.Right.Style = ExcelBorderStyle.Thin; - - // 交替行颜色 - if (i % 2 == 1) + CreateWorksheet("编排表"); + + // 第一行:赛事标题(合并单元格 A1:G1) + var titleColor = Color.FromArgb(255, 217, 179); + SetMergeTitle(_eventInfo?.EventName ?? "赛事编排表", 1, 1, 1, 7, titleColor, 14); + + // 第二行:列标题 + var headers = new[] { "时间", "参赛项目", "参赛组别", "参赛队伍", "运动员姓名", "场次", "场地" }; + var headerColor = Color.FromArgb(204, 255, 204); + SetHeaders(headers, 2, headerColor, 11); + + // 填充数据行 + var alternateBgColor = Color.FromArgb(240, 255, 240); + for (int i = 0; i < _data.Count; i++) { - rowStyle.Fill.PatternType = ExcelFillStyle.Solid; - rowStyle.Fill.BackgroundColor.SetColor(Color.FromArgb(240, 255, 240)); // 更浅的绿色 + var item = _data[i]; + int rowIndex = i + 3; + + Worksheet.Cells[rowIndex, 1].Value = item.TimeRange; + Worksheet.Cells[rowIndex, 2].Value = item.ProjectName; + Worksheet.Cells[rowIndex, 3].Value = item.GroupName; + Worksheet.Cells[rowIndex, 4].Value = item.TeamName ?? ""; + Worksheet.Cells[rowIndex, 5].Value = item.AthleteName; + Worksheet.Cells[rowIndex, 6].Value = item.SessionIndex; + Worksheet.Cells[rowIndex, 7].Value = item.VenueIndex; + + SetDataRowStyle(rowIndex, 7, alternateBgColor, i % 2 == 1); } + + // 设置列宽 + var widths = new double[] { 12, 18, 15, 25, 15, 8, 8 }; + SetColumnWidths(widths); + + // 设置行高 + SetRowHeight(1, 30); + SetRowHeight(2, 25); + + // 冻结首行和首列 + FreezePanes(3, 1); + + return await GetAsByteArrayAsync(); } - - // 设置列宽 - worksheet.Column(1).Width = 12; // 时间 - worksheet.Column(2).Width = 18; // 参赛项目 - worksheet.Column(3).Width = 15; // 参赛组别 - worksheet.Column(4).Width = 25; // 参赛队伍 - worksheet.Column(5).Width = 15; // 运动员姓名 - worksheet.Column(6).Width = 8; // 场次 - worksheet.Column(7).Width = 8; // 场地 - - // 设置行高 - worksheet.Row(1).Height = 30; // 标题行 - worksheet.Row(2).Height = 25; // 列标题行 - - // 冻结首行和首列 - worksheet.View.FreezePanes(3, 1); - - return await package.GetAsByteArrayAsync(); } } diff --git a/YD_Event.Application/Event/UserEventRegistrationService.cs b/YD_Event.Application/Event/UserEventRegistrationService.cs index 2088d19..003d42e 100644 --- a/YD_Event.Application/Event/UserEventRegistrationService.cs +++ b/YD_Event.Application/Event/UserEventRegistrationService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using YD_Event.Application.Event.Dtos; +using YD_Event.Application.Project; using YD_Event.Core.Entities; using YD_Event.Core.Enum; using SqlSugar; @@ -49,6 +50,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient private readonly WeChatPayService _weChatPayService; private readonly IOptionsMonitor _wechatTenpayClientOptionsMonitor; private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ProjectService _projectService; public UserEventRegistrationService( ISqlSugarRepository eventRepository, @@ -70,7 +72,8 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient IIdGenerator idGenerator, WeChatPayService weChatPayService, IOptionsMonitor wechatTenpayClientOptionsMonitor, - IHttpContextAccessor httpContextAccessor) + IHttpContextAccessor httpContextAccessor, + ProjectService projectService) { _eventRepository = eventRepository; _unitRepository = unitRepository; @@ -92,6 +95,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient _weChatPayService = weChatPayService; _wechatTenpayClientOptionsMonitor = wechatTenpayClientOptionsMonitor; _httpContextAccessor = httpContextAccessor; + _projectService = projectService; } /// @@ -188,15 +192,24 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient var projectIds = eventProjects.Select(x => x.ProjectId).Distinct().ToList(); var baseProjects = await _projectRepository.GetListAsync(x => projectIds.Contains(x.Id) && x.Status == AvailabilityStatus.Enable); + var completionStats = await _projectService.GetProjectStatisticsBatchAsync( + projectIds, + ProjectService.ProjectStatisticType.CompletionCount); + output.Projects = eventProjects.Select(ep => { var p = baseProjects.FirstOrDefault(b => b.Id == ep.ProjectId); + var completionCount = 0; + if (p != null && completionStats.TryGetValue(p.Id, out var count)) + { + completionCount = count; + } return new UserEventProjectListOutput { Id = ep.Id, Name = p?.Name ?? "", Fee = ep.Price / 100m, - CompletionCount = p?.CompletionCount ?? 0 + CompletionCount = completionCount }; }).Where(x => !string.IsNullOrEmpty(x.Name)).ToList(); @@ -227,16 +240,25 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient var projectIds = eventProjects.Select(x => x.ProjectId).Distinct().ToList(); var baseProjects = await _projectRepository.GetListAsync(x => projectIds.Contains(x.Id) && x.Status == AvailabilityStatus.Enable); + var completionStats = await _projectService.GetProjectStatisticsBatchAsync( + projectIds, + ProjectService.ProjectStatisticType.CompletionCount); + return eventProjects.Select(ep => { var p = baseProjects.FirstOrDefault(b => b.Id == ep.ProjectId); + var completionCount = 0; + if (p != null && completionStats.TryGetValue(p.Id, out var count)) + { + completionCount = count; + } return new UserEventProjectListOutput { Id = ep.Id, Name = p?.Name ?? "", Fee = ep.Price / 100m, - TeamSize = 1, // 默认为1 - CompletionCount = p?.CompletionCount ?? 0 + TeamSize = 1, + CompletionCount = completionCount }; }).Where(x => !string.IsNullOrEmpty(x.Name)).ToList(); } diff --git a/YD_Event.Application/Project/ProjectService.cs b/YD_Event.Application/Project/ProjectService.cs index 1f635c3..f89dca5 100644 --- a/YD_Event.Application/Project/ProjectService.cs +++ b/YD_Event.Application/Project/ProjectService.cs @@ -2,6 +2,7 @@ using YD_Event.Application.Project.Dtos; using YD_Event.Core.Entities; using Mapster; using SqlSugar; +using Microsoft.Extensions.Logging; namespace YD_Event.Application.Project; @@ -13,18 +14,27 @@ public class ProjectService : BaseService, ITran private readonly ISqlSugarRepository _repository; private readonly ISqlSugarRepository _groupRepository; private readonly ISqlSugarRepository _typeRepository; + private readonly ISqlSugarRepository _eventProjectRepository; + private readonly ISqlSugarRepository _participationRecordRepository; private readonly IIdGenerator _idGenerator; + private readonly ILogger _logger; public ProjectService( ISqlSugarRepository repository, ISqlSugarRepository groupRepository, ISqlSugarRepository typeRepository, - IIdGenerator idGenerator) : base(repository) + ISqlSugarRepository eventProjectRepository, + ISqlSugarRepository participationRecordRepository, + IIdGenerator idGenerator, + ILogger logger) : base(repository) { _repository = repository; _groupRepository = groupRepository; _typeRepository = typeRepository; + _eventProjectRepository = eventProjectRepository; + _participationRecordRepository = participationRecordRepository; _idGenerator = idGenerator; + _logger = logger; } /// @@ -60,6 +70,19 @@ public class ProjectService : BaseService, ITran }) .ToPagedListAsync(input); + var projectIds = result.Rows.Select(x => x.Id).ToList(); + if (projectIds.Any()) + { + var stats = await GetProjectStatisticsBatchAsync(projectIds, ProjectStatisticType.CompletionCount); + foreach (var item in result.Rows) + { + if (stats.TryGetValue(item.Id, out var count)) + { + item.CompletionCount = count; + } + } + } + return result; } @@ -70,7 +93,6 @@ public class ProjectService : BaseService, ITran [UnitOfWork] public async Task Add(AddProjectInput input) { - // 检查项目名称是否重复 var isExist = await _repository.IsAnyAsync(x => x.Name == input.Name); if (isExist) throw new InvalidOperationException("该项目名称已存在"); @@ -104,7 +126,6 @@ public class ProjectService : BaseService, ITran var entity = await _repository.GetByIdAsync(input.Id); if (entity == null) throw new InvalidOperationException("项目不存在"); - // 如果修改了名称,检查是否重复 if (entity.Name != input.Name) { var isExist = await _repository.IsAnyAsync(x => x.Name == input.Name && x.Id != input.Id); @@ -115,7 +136,6 @@ public class ProjectService : BaseService, ITran entity.UpdatedTime = DateTime.Now; await _repository.UpdateAsync(entity); - // Update groups: Delete old, Insert new await _groupRepository.DeleteAsync(x => x.ProjectId == entity.Id); if (input.Groups != null && input.Groups.Any()) @@ -161,7 +181,137 @@ public class ProjectService : BaseService, ITran var groups = await _groupRepository.GetListAsync(x => x.ProjectId == id); dto.Groups = groups.Adapt>(); + + dto.CompletionCount = await GetProjectStatisticAsync(id, ProjectStatisticType.CompletionCount); return dto; } + + /// + /// 项目统计类型 + /// + public enum ProjectStatisticType + { + /// + /// 参赛人数 + /// + ParticipationCount = 1, + + /// + /// 完成人数 + /// + CompletionCount = 2 + } + + /// + /// 获取项目统计数据(单个项目) + /// + /// 项目ID + /// 统计类型 + /// 统计数值 + [DisplayName("获取项目统计数据")] + public async Task GetProjectStatisticAsync(long projectId, ProjectStatisticType statisticType) + { + if (projectId <= 0) + { + _logger.LogWarning("Invalid projectId: {ProjectId}", projectId); + return 0; + } + + var eventProjectIds = await _eventProjectRepository.AsQueryable() + .Where(ep => ep.ProjectId == projectId) + .Select(ep => ep.Id) + .ToListAsync(); + + if (!eventProjectIds.Any()) + { + return 0; + } + + var query = _participationRecordRepository.AsQueryable() + .Where(pr => eventProjectIds.Contains(pr.ProjectId) && !pr.DeleteMark); + + switch (statisticType) + { + case ProjectStatisticType.ParticipationCount: + query = query.Where(pr => pr.ParticipationStatus == ParticipationStatus.Participated || pr.ParticipationStatus == ParticipationStatus.Completed); + break; + + case ProjectStatisticType.CompletionCount: + query = query.Where(pr => pr.ParticipationStatus == ParticipationStatus.Completed); + break; + + default: + _logger.LogWarning("Unknown statistic type: {StatisticType}", statisticType); + return 0; + } + + var count = await query.CountAsync(); + return count; + } + + /// + /// 批量获取项目统计数据(性能优化,避免N+1查询) + /// + /// 项目ID列表 + /// 统计类型 + /// 字典,Key为项目ID,Value为统计数值 + [DisplayName("批量获取项目统计数据")] + public async Task> GetProjectStatisticsBatchAsync(List projectIds, ProjectStatisticType statisticType) + { + var result = new Dictionary(); + + if (projectIds == null || !projectIds.Any()) + { + return result; + } + + foreach (var projectId in projectIds) + { + result[projectId] = 0; + } + + var eventProjects = await _eventProjectRepository.AsQueryable() + .Where(ep => projectIds.Contains(ep.ProjectId)) + .Select(ep => new { ep.Id, ep.ProjectId }) + .ToListAsync(); + + if (!eventProjects.Any()) + { + return result; + } + + var eventProjectIds = eventProjects.Select(ep => ep.Id).ToList(); + + var query = _participationRecordRepository.AsQueryable() + .Where(pr => eventProjectIds.Contains(pr.ProjectId) && !pr.DeleteMark); + + switch (statisticType) + { + case ProjectStatisticType.ParticipationCount: + query = query.Where(pr => pr.ParticipationStatus == ParticipationStatus.Participated || pr.ParticipationStatus == ParticipationStatus.Completed); + break; + + case ProjectStatisticType.CompletionCount: + query = query.Where(pr => pr.ParticipationStatus == ParticipationStatus.Completed); + break; + + default: + _logger.LogWarning("Unknown statistic type: {StatisticType}", statisticType); + return result; + } + + var records = await query.ToListAsync(); + + foreach (var record in records) + { + var projectId = eventProjects.FirstOrDefault(ep => ep.Id == record.ProjectId)?.ProjectId; + if (projectId.HasValue && result.ContainsKey(projectId.Value)) + { + result[projectId.Value]++; + } + } + + return result; + } } diff --git a/YD_Event.Application/YD_Event.Application.xml b/YD_Event.Application/YD_Event.Application.xml index 86d3699..eabde81 100644 --- a/YD_Event.Application/YD_Event.Application.xml +++ b/YD_Event.Application/YD_Event.Application.xml @@ -4965,6 +4965,11 @@ 导出编排 + + + 编排导出器 + + 参赛记录管理 @@ -7634,6 +7639,37 @@ 获取项目详情 + + + 项目统计类型 + + + + + 参赛人数 + + + + + 完成人数 + + + + + 获取项目统计数据(单个项目) + + 项目ID + 统计类型 + 统计数值 + + + + 批量获取项目统计数据(性能优化,避免N+1查询) + + 项目ID列表 + 统计类型 + 字典,Key为项目ID,Value为统计数值 + 项目类型管理 diff --git a/YD_Event.Core/Domain/Export/ExcelExportBase.cs b/YD_Event.Core/Domain/Export/ExcelExportBase.cs new file mode 100644 index 0000000..ed44631 --- /dev/null +++ b/YD_Event.Core/Domain/Export/ExcelExportBase.cs @@ -0,0 +1,146 @@ +using OfficeOpenXml; +using OfficeOpenXml.Style; +using System.Drawing; + +namespace YD_Event.Core.Domain.Export; + +/// +/// Excel 导出基类 +/// +public abstract class ExcelExportBase +{ + protected ExcelPackage Package { get; private set; } + protected ExcelWorksheet Worksheet { get; private set; } + + protected ExcelExportBase() + { + ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial; + Package = new ExcelPackage(); + } + + /// + /// 创建工作表 + /// + protected void CreateWorksheet(string sheetName) + { + Worksheet = Package.Workbook.Worksheets.Add(sheetName); + } + + /// + /// 设置合并单元格标题 + /// + protected void SetMergeTitle(string title, int startRow, int startCol, int endRow, int endCol, Color? bgColor = null, int fontSize = 14) + { + var range = Worksheet.Cells[startRow, startCol, endRow, endCol]; + range.Merge = true; + range.Value = title; + + var style = range.Style; + style.Font.Bold = true; + style.Font.Size = fontSize; + style.HorizontalAlignment = ExcelHorizontalAlignment.Center; + style.VerticalAlignment = ExcelVerticalAlignment.Center; + + if (bgColor.HasValue) + { + style.Fill.PatternType = ExcelFillStyle.Solid; + style.Fill.BackgroundColor.SetColor(bgColor.Value); + } + } + + /// + /// 设置列标题 + /// + protected void SetHeaders(string[] headers, int rowIndex, Color? bgColor = null, int fontSize = 11) + { + for (int i = 0; i < headers.Length; i++) + { + Worksheet.Cells[rowIndex, i + 1].Value = headers[i]; + } + + var headerRange = Worksheet.Cells[rowIndex, 1, rowIndex, headers.Length]; + var style = headerRange.Style; + style.Font.Bold = true; + style.Font.Size = fontSize; + style.HorizontalAlignment = ExcelHorizontalAlignment.Center; + style.VerticalAlignment = ExcelVerticalAlignment.Center; + + if (bgColor.HasValue) + { + style.Fill.PatternType = ExcelFillStyle.Solid; + style.Fill.BackgroundColor.SetColor(bgColor.Value); + } + + SetCellBorders(headerRange, ExcelBorderStyle.Thin); + } + + /// + /// 设置单元格边框 + /// + protected void SetCellBorders(ExcelRange range, ExcelBorderStyle borderStyle) + { + range.Style.Border.Top.Style = borderStyle; + range.Style.Border.Bottom.Style = borderStyle; + range.Style.Border.Left.Style = borderStyle; + range.Style.Border.Right.Style = borderStyle; + } + + /// + /// 设置数据行样式 + /// + protected void SetDataRowStyle(int rowIndex, int colCount, Color? alternateBgColor = null, bool isAlternate = false) + { + var range = Worksheet.Cells[rowIndex, 1, rowIndex, colCount]; + var style = range.Style; + style.HorizontalAlignment = ExcelHorizontalAlignment.Center; + style.VerticalAlignment = ExcelVerticalAlignment.Center; + + SetCellBorders(range, ExcelBorderStyle.Thin); + + if (isAlternate && alternateBgColor.HasValue) + { + style.Fill.PatternType = ExcelFillStyle.Solid; + style.Fill.BackgroundColor.SetColor(alternateBgColor.Value); + } + } + + /// + /// 设置列宽 + /// + protected void SetColumnWidths(double[] widths) + { + for (int i = 0; i < widths.Length; i++) + { + Worksheet.Column(i + 1).Width = widths[i]; + } + } + + /// + /// 设置行高 + /// + protected void SetRowHeight(int rowIndex, double height) + { + Worksheet.Row(rowIndex).Height = height; + } + + /// + /// 冻结窗格 + /// + protected void FreezePanes(int rowOffset, int colOffset) + { + Worksheet.View.FreezePanes(rowOffset, colOffset); + } + + /// + /// 生成字节数组 + /// + protected async Task GetAsByteArrayAsync() + { + return await Package.GetAsByteArrayAsync(); + } + + /// + /// 执行导出 + /// + public abstract Task ExportAsync(); +} diff --git a/YD_Event.Core/Entities/EventParticipationRecord.cs b/YD_Event.Core/Entities/EventParticipationRecord.cs index 3cb81df..baa2050 100644 --- a/YD_Event.Core/Entities/EventParticipationRecord.cs +++ b/YD_Event.Core/Entities/EventParticipationRecord.cs @@ -46,9 +46,9 @@ public class EventParticipationRecord : Entity, ISoftDelete, ICreatedUserI public string GroupName { get; set; } /// - /// 参赛状态:0-未参赛,1-已参赛,2-已完赛,3-退赛 + /// 参赛状态 /// - public int ParticipationStatus { get; set; } + public ParticipationStatus ParticipationStatus { get; set; } /// /// 参赛时间 diff --git a/YD_Event.Core/Enum/ParticipationStatus.cs b/YD_Event.Core/Enum/ParticipationStatus.cs new file mode 100644 index 0000000..4b947ad --- /dev/null +++ b/YD_Event.Core/Enum/ParticipationStatus.cs @@ -0,0 +1,33 @@ +using System.ComponentModel; + +namespace YD_Event.Core.Enum; + +/// +/// 参赛状态枚举 +/// +public enum ParticipationStatus +{ + /// + /// 未参赛 + /// + [Description("未参赛")] + NotParticipated = 0, + + /// + /// 已参赛 + /// + [Description("已参赛")] + Participated = 1, + + /// + /// 已完赛 + /// + [Description("已完赛")] + Completed = 2, + + /// + /// 退赛 + /// + [Description("退赛")] + Withdrawn = 3 +} diff --git a/YD_Event.Core/YD_Event.Core.csproj b/YD_Event.Core/YD_Event.Core.csproj index 271707e..940b6c1 100644 --- a/YD_Event.Core/YD_Event.Core.csproj +++ b/YD_Event.Core/YD_Event.Core.csproj @@ -27,6 +27,7 @@ + diff --git a/YD_Event.Core/YD_Event.Core.xml b/YD_Event.Core/YD_Event.Core.xml index c87086c..3c74b0d 100644 --- a/YD_Event.Core/YD_Event.Core.xml +++ b/YD_Event.Core/YD_Event.Core.xml @@ -433,6 +433,61 @@ 是否绘制静区 + + + Excel 导出基类 + + + + + 创建工作表 + + + + + 设置合并单元格标题 + + + + + 设置列标题 + + + + + 设置单元格边框 + + + + + 设置数据行样式 + + + + + 设置列宽 + + + + + 设置行高 + + + + + 冻结窗格 + + + + + 生成字节数组 + + + + + 执行导出 + + 表实体继承 @@ -1341,7 +1396,7 @@ - 参赛状态:0-未参赛,1-已参赛,2-已完赛,3-退赛 + 参赛状态 @@ -4297,6 +4352,31 @@ 已完成 + + + 参赛状态枚举 + + + + + 未参赛 + + + + + 已参赛 + + + + + 已完赛 + + + + + 退赛 + + 人员角色类型