566 lines
25 KiB
C#
Raw Normal View History

using System.Text;
2026-04-05 20:58:17 +08:00
using OfficeOpenXml;
using OfficeOpenXml.Style;
using System.Drawing;
2026-03-10 16:54:18 +08:00
using YD_Event.Application.Auth;
using YD_Event.Application.Order.Dtos;
using YD_Event.Core.Entities;
using YD_Event.Core.Enum;
2026-03-02 09:54:52 +08:00
using YD_Event.Application.Refund;
namespace YD_Event.Application.Order;
/// <summary>
/// 订单管理服务
/// </summary>
2026-03-07 23:47:13 +08:00
public class OrderService : BaseService<YD_Event.Core.Entities.Order>, ITransient
{
2026-03-07 23:47:13 +08:00
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Order> _orderRepository;
private readonly ISqlSugarRepository<EventRegistration> _registrationRepository;
private readonly ISqlSugarRepository<EventRegistrationItem> _itemRepository;
private readonly ISqlSugarRepository<EventRegistrationPerson> _personRepository;
private readonly ISqlSugarRepository<EventRegistrationPayment> _paymentRepository;
2026-03-02 09:54:52 +08:00
private readonly ISqlSugarRepository<EventInfo> _eventRepository;
2026-03-07 23:47:13 +08:00
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Merchant> _merchantRepository;
2026-03-02 09:54:52 +08:00
private readonly RefundConfigService _refundConfigService;
private readonly IIdGenerator _idGenerator;
2026-03-10 16:54:18 +08:00
private readonly AuthManager _authManager;
2026-03-30 17:06:12 +08:00
private readonly ISqlSugarClient _db;
2026-03-07 23:47:13 +08:00
public OrderService(
ISqlSugarRepository<YD_Event.Core.Entities.Order> orderRepository,
ISqlSugarRepository<EventRegistration> registrationRepository,
ISqlSugarRepository<EventRegistrationItem> itemRepository,
ISqlSugarRepository<EventRegistrationPerson> personRepository,
ISqlSugarRepository<EventRegistrationPayment> paymentRepository,
2026-03-02 09:54:52 +08:00
ISqlSugarRepository<EventInfo> eventRepository,
2026-03-07 23:47:13 +08:00
ISqlSugarRepository<YD_Event.Core.Entities.Merchant> merchantRepository,
2026-03-02 09:54:52 +08:00
RefundConfigService refundConfigService,
2026-03-10 16:54:18 +08:00
IIdGenerator idGenerator,
2026-03-30 17:06:12 +08:00
AuthManager authManager,
ISqlSugarClient db) : base(orderRepository)
{
2026-03-07 23:47:13 +08:00
_orderRepository = orderRepository;
_registrationRepository = registrationRepository;
_itemRepository = itemRepository;
_personRepository = personRepository;
_paymentRepository = paymentRepository;
2026-03-02 09:54:52 +08:00
_eventRepository = eventRepository;
2026-03-07 23:47:13 +08:00
_merchantRepository = merchantRepository;
2026-03-02 09:54:52 +08:00
_refundConfigService = refundConfigService;
_idGenerator = idGenerator;
2026-03-10 16:54:18 +08:00
_authManager = authManager;
2026-03-30 17:06:12 +08:00
_db = db;
}
/// <summary>
/// 创建订单
/// </summary>
[DisplayName("创建订单")]
[HttpPost("create")]
[UnitOfWork]
public async Task<string> Create(CreateOrderInput input)
{
// 1. Create Registration
var entity = input.Adapt<EventRegistration>();
entity.Id = _idGenerator.NextId();
entity.OrderNo = DateTime.Now.ToString("yyyyMMdd") + new Random().Next(1000, 9999); // Simple generation
entity.RegistrationStatus = 0; // Pending
entity.PaymentStatus = 0; // Unpaid
entity.RegistrationTime = DateTime.Now;
// Calculate Total
decimal totalAmount = 0;
int totalPerson = 0;
if (input.Items != null)
{
foreach (var item in input.Items)
{
totalAmount += item.UnitPrice * item.PersonCount;
totalPerson += item.PersonCount;
}
}
entity.TotalAmount = totalAmount;
entity.TotalPersonCount = totalPerson;
2026-03-07 23:47:13 +08:00
await _registrationRepository.InsertAsync(entity);
// 2. Create Items
2026-03-11 16:00:09 +08:00
var createdItems = new List<EventRegistrationItem>();
if (input.Items != null && input.Items.Any())
{
var items = input.Items.Adapt<List<EventRegistrationItem>>();
items.ForEach(x =>
{
x.Id = _idGenerator.NextId();
x.RegistrationId = entity.Id;
x.TotalPrice = x.UnitPrice * x.PersonCount;
});
await _itemRepository.InsertRangeAsync(items);
2026-03-11 16:00:09 +08:00
createdItems = items;
}
// 3. Create Persons
if (input.Persons != null && input.Persons.Any())
{
var persons = input.Persons.Adapt<List<EventRegistrationPerson>>();
persons.ForEach(x =>
{
x.Id = _idGenerator.NextId();
x.RegistrationId = entity.Id;
2026-03-11 16:00:09 +08:00
// Link to Item based on ProjectId and GroupName
var linkedItem = createdItems.FirstOrDefault(i => i.ProjectId == x.ProjectId && i.GroupName == x.GroupName);
if (linkedItem != null)
{
x.RegistrationItemId = linkedItem.Id;
}
// Ensure GroupName is not null (DB Constraint)
if (string.IsNullOrEmpty(x.GroupName)) x.GroupName = "";
});
await _personRepository.InsertRangeAsync(persons);
}
2026-03-07 23:47:13 +08:00
// 4. Create Order (Income)
2026-03-11 16:00:09 +08:00
// 获取赛事关联的商户ID
var eventInfo = await _eventRepository.GetByIdAsync(input.EventId);
2026-03-30 17:06:12 +08:00
// 获取当前用户的单位认证ID
var certification = await _db.Queryable<MerchantCertification>()
.FirstAsync(c => c.UserId == entity.CreatedUserId && c.AuditStatus == AuditStatus.Pass && !c.DeleteMark);
2026-03-07 23:47:13 +08:00
var order = new YD_Event.Core.Entities.Order
{
Id = _idGenerator.NextId(),
OrderNo = entity.OrderNo,
OrderType = 1, // Income
PaymentMethod = 1, // Default Online? Or unknown yet.
RegistrationMode = input.RegistrationMode,
2026-03-30 17:06:12 +08:00
MerchantId = eventInfo?.MerchantId, // 设置商户ID(支付商户)
MerchantCertificationId = certification?.Id, // 设置单位认证ID
2026-03-07 23:47:13 +08:00
EventId = input.EventId,
RegistrationId = entity.Id,
OriginalAmount = totalAmount,
ActualAmount = totalAmount, // Before discount
DiscountAmount = 0,
OrderStatus = OrderStatus.Pending, // Pending
CreatedTime = DateTime.Now,
CreatedUserId = entity.CreatedUserId
};
await _orderRepository.InsertAsync(order);
return entity.OrderNo;
}
/// <summary>
/// 订单分页查询
/// </summary>
[DisplayName("订单分页查询")]
2026-03-07 23:47:13 +08:00
[HttpGet("page")]
public async Task<PageResult<OrderListOutput>> Page([FromQuery] OrderQueryInput input)
{
2026-03-10 16:54:18 +08:00
var userId = _authManager.UserId;
2026-03-30 17:06:12 +08:00
// 判断是否是单位认证账号
var certification = await _db.Queryable<MerchantCertification>()
.FirstAsync(c => c.UserId == userId && c.AuditStatus == AuditStatus.Pass && !c.DeleteMark);
2026-03-10 16:54:18 +08:00
2026-03-07 23:47:13 +08:00
var query = _orderRepository.AsQueryable()
.LeftJoin<EventInfo>((o, e) => o.EventId == e.Id)
.LeftJoin<YD_Event.Core.Entities.Merchant>((o, e, m) => o.MerchantId == m.Id)
.LeftJoin<EventRegistration>((o, e, m, r) => o.RegistrationId == r.Id)
.LeftJoin<YD_Event.Core.Entities.Order>((o, e, m, r, ro) => o.RelatedOrderId == ro.Id) // Join self for Related Order No
2026-04-05 20:58:17 +08:00
// 默认只显示已完成支付流程的订单(已支付、已发货、已完成、已退款)
.WhereIF(!input.OrderStatus.HasValue, (o, e, m, r, ro) =>
o.OrderStatus == OrderStatus.Paid ||
o.OrderStatus == OrderStatus.Shipped ||
o.OrderStatus == OrderStatus.Completed ||
o.OrderStatus == OrderStatus.Refunded)
2026-03-07 23:47:13 +08:00
.WhereIF(!string.IsNullOrWhiteSpace(input.OrderNo), (o, e, m, r, ro) => o.OrderNo.Contains(input.OrderNo))
.WhereIF(!string.IsNullOrWhiteSpace(input.EventName), (o, e, m, r, ro) => e.EventName.Contains(input.EventName))
.WhereIF(input.OrderType.HasValue, (o, e, m, r, ro) => o.OrderType == input.OrderType)
.WhereIF(input.OrderStatus.HasValue, (o, e, m, r, ro) => o.OrderStatus == input.OrderStatus)
.WhereIF(input.PaymentMethod.HasValue, (o, e, m, r, ro) => o.PaymentMethod == input.PaymentMethod)
.WhereIF(input.RegistrationMode.HasValue, (o, e, m, r, ro) => o.RegistrationMode == input.RegistrationMode)
.WhereIF(!string.IsNullOrWhiteSpace(input.ContactPhone), (o, e, m, r, ro) => r.ContactPhone.Contains(input.ContactPhone))
2026-03-10 16:54:18 +08:00
.WhereIF(input.StartTime.HasValue, (o, e, m, r, ro) => o.PaymentTime >= input.StartTime) // 支付时间筛选
.WhereIF(input.EndTime.HasValue, (o, e, m, r, ro) => o.PaymentTime <= input.EndTime)
.OrderByDescending((o, e, m, r, ro) => o.CreatedTime);
2026-03-30 17:06:12 +08:00
// 权限判断:如果是单位认证用户,只能查看自己单位认证的订单
if (certification != null && !_authManager.IsSuperAdmin)
2026-03-10 16:54:18 +08:00
{
2026-03-30 17:06:12 +08:00
query = query.Where((o, e, m, r, ro) => o.MerchantCertificationId == certification.Id);
2026-03-10 16:54:18 +08:00
}
var result = await query.Select((o, e, m, r, ro) => new OrderListOutput
2026-03-07 23:47:13 +08:00
{
Id = o.Id,
OrderNo = o.OrderNo,
UnitName = SqlFunc.IsNullOrEmpty(m.MerchantName) ? "/" : m.MerchantName,
EventName = e.EventName,
OrderType = o.OrderType == 1 ? "收入" : "退款",
RelatedOrderNo = ro.OrderNo,
PaymentMethod = o.PaymentMethod == 1 ? "线上" : "线下",
PaymentProofUrl = o.PaymentProofUrl,
RegistrationMode = o.RegistrationMode == 1 ? "个人" : "团队",
ContactName = r.ContactName,
ContactPhone = r.ContactPhone,
OriginalAmount = o.OriginalAmount,
DiscountAmount = o.DiscountAmount,
ActualAmount = o.ActualAmount,
OrderStatus = o.OrderStatus,
OrderStatusText =
o.OrderStatus == OrderStatus.Pending ? "待支付" :
o.OrderStatus == OrderStatus.Paid ? "已支付" :
o.OrderStatus == OrderStatus.Cancelled ? "已取消" :
o.OrderStatus == OrderStatus.Refunded ? "已退款" :
o.OrderStatus == OrderStatus.Shipped ? "已发货" :
o.OrderStatus == OrderStatus.Completed ? "已完成" : "",
2026-03-10 16:54:18 +08:00
CreatedTime = o.CreatedTime,
PaymentTime = o.PaymentTime,
RefundAmount = o.OrderType == 2 ? o.ActualAmount : 0, // 如果是退款订单,ActualAmount即为退款金额
RefundTime = o.OrderType == 2 ? o.PaymentTime : null // 退款时间
})
.ToPagedListAsync(input);
2026-03-07 23:47:13 +08:00
2026-03-10 16:54:18 +08:00
return result;
}
/// <summary>
/// 获取订单详情
/// </summary>
[DisplayName("获取订单详情")]
[HttpGet("detail")]
2026-03-07 23:47:13 +08:00
public async Task<OrderDetailOutput> Detail([FromQuery] long id)
{
2026-03-07 23:47:13 +08:00
var order = await _orderRepository.AsQueryable()
.LeftJoin<EventInfo>((o, e) => o.EventId == e.Id)
.Where(o => o.Id == id)
.Select((o, e) => new { Order = o, EventName = e.EventName })
.FirstAsync();
2026-03-07 23:47:13 +08:00
if (order == null) throw Oops.Bah("订单不存在");
var registrationId = order.Order.RegistrationId;
var items = await _itemRepository.AsQueryable().Where(x => x.RegistrationId == registrationId).ToListAsync();
var persons = await _personRepository.AsQueryable().Where(x => x.RegistrationId == registrationId).ToListAsync();
// Convert items and persons to Dto
var itemDtos = items.Select(x => new OrderItemDto
{
ProjectName = x.ProjectName, // Assume stored or join
GroupName = x.GroupName,
Fee = x.TotalPrice
}).ToList();
var personDtos = persons.Select(x => new OrderPersonDto
{
Name = x.Name,
GroupName = x.GroupName
}).ToList();
return new OrderDetailOutput
{
Id = order.Order.Id,
OrderNo = order.Order.OrderNo,
OrderType = order.Order.OrderType,
OrderStatus = order.Order.OrderStatus,
EventName = order.EventName,
ProjectNames = string.Join(",", items.Select(x => x.ProjectName).Distinct()),
GroupNames = string.Join(",", items.Select(x => x.GroupName).Distinct()),
Items = itemDtos,
Persons = personDtos,
PaymentMethod = order.Order.PaymentMethod == 1 ? "线上" : "线下",
PaymentProofUrl = order.Order.PaymentProofUrl,
OriginalAmount = order.Order.OriginalAmount,
DiscountAmount = order.Order.DiscountAmount,
ActualAmount = order.Order.ActualAmount,
CreatedTime = order.Order.CreatedTime
};
}
/// <summary>
/// 更新订单状态
/// </summary>
[DisplayName("更新订单状态")]
[HttpPut("status")]
public async Task UpdateStatus(UpdateOrderStatusInput input)
{
2026-03-07 23:47:13 +08:00
var order = await _orderRepository.GetByIdAsync(input.Id);
if (order == null) throw Oops.Bah("订单不存在");
2026-03-07 23:47:13 +08:00
// Update Order
order.OrderStatus = input.PaymentStatus == 1 ? OrderStatus.Paid : OrderStatus.Pending; // Assuming 1 is paid/success
if (input.PaymentStatus == 1)
{
2026-03-07 23:47:13 +08:00
order.PaymentTime = DateTime.Now;
}
await _orderRepository.UpdateAsync(order);
// Update Registration sync
var reg = await _registrationRepository.GetByIdAsync(order.RegistrationId);
if (reg != null)
{
reg.PaymentStatus = input.PaymentStatus;
reg.PaymentTime = order.PaymentTime;
await _registrationRepository.UpdateAsync(reg);
}
}
2026-03-02 09:54:52 +08:00
/// <summary>
/// 获取建议退款金额
/// </summary>
[DisplayName("获取建议退款金额")]
[HttpGet("refund-amount")]
public async Task<decimal> GetRefundAmount([FromQuery] long orderId)
{
2026-03-07 23:47:13 +08:00
var order = await _orderRepository.GetByIdAsync(orderId);
2026-03-02 09:54:52 +08:00
if (order == null) throw Oops.Bah("订单不存在");
var eventInfo = await _eventRepository.GetByIdAsync(order.EventId);
2026-03-07 23:47:13 +08:00
if (eventInfo == null) return order.ActualAmount;
2026-03-02 09:54:52 +08:00
2026-03-07 23:47:13 +08:00
return await _refundConfigService.CalculateRefundAmount(order.ActualAmount, eventInfo.MatchStartTime);
2026-03-02 09:54:52 +08:00
}
/// <summary>
/// 订单退款
/// </summary>
[DisplayName("订单退款")]
[HttpPost("refund")]
[UnitOfWork]
public async Task Refund(RefundOrderInput input)
{
2026-03-07 23:47:13 +08:00
var order = await _orderRepository.GetByIdAsync(input.Id);
if (order == null) throw Oops.Bah("订单不存在");
2026-03-07 23:47:13 +08:00
if (order.OrderStatus != OrderStatus.Paid) throw Oops.Bah("订单未支付,无法退款");
2026-03-07 23:47:13 +08:00
// 1. Create Refund Order
var refundOrder = new YD_Event.Core.Entities.Order
{
2026-03-07 23:47:13 +08:00
Id = _idGenerator.NextId(),
OrderNo = "REF" + DateTime.Now.ToString("yyyyMMddHHmmss"),
OrderType = 2, // Refund
PaymentMethod = order.PaymentMethod,
RegistrationMode = order.RegistrationMode,
MerchantId = order.MerchantId,
2026-03-30 17:06:12 +08:00
MerchantCertificationId = order.MerchantCertificationId, // 继承原订单的单位认证ID
2026-03-07 23:47:13 +08:00
EventId = order.EventId,
RegistrationId = order.RegistrationId,
RelatedOrderId = order.Id, // Link to original
OriginalAmount = order.ActualAmount,
ActualAmount = input.RefundAmount, // Refund Amount
OrderStatus = OrderStatus.Refunded, // Success (Refunded)
PaymentTime = DateTime.Now,
Remark = input.Reason,
CreatedTime = DateTime.Now,
CreatedUserId = _idGenerator.NewLong() // System or current user
};
await _orderRepository.InsertAsync(refundOrder);
// 2. Update Registration Status
var reg = await _registrationRepository.GetByIdAsync(order.RegistrationId);
if (reg != null)
{
2026-03-07 23:47:13 +08:00
reg.PaymentStatus = 3; // Refunded
await _registrationRepository.UpdateAsync(reg);
}
}
/// <summary>
/// 删除订单
/// </summary>
[DisplayName("删除订单")]
[HttpPost("delete")]
public async Task Delete([FromBody] List<long> ids)
{
2026-03-07 23:47:13 +08:00
await _orderRepository.DeleteAsync(x => ids.Contains(x.Id));
}
/// <summary>
/// 导出订单
/// </summary>
[DisplayName("导出订单")]
[HttpGet("export")]
public async Task<IActionResult> Export([FromQuery] OrderQueryInput input)
{
2026-03-07 23:47:13 +08:00
var list = await _orderRepository.AsQueryable()
.LeftJoin<EventInfo>((o, e) => o.EventId == e.Id)
.LeftJoin<YD_Event.Core.Entities.Merchant>((o, e, m) => o.MerchantId == m.Id)
.LeftJoin<EventRegistration>((o, e, m, r) => o.RegistrationId == r.Id)
.LeftJoin<YD_Event.Core.Entities.Order>((o, e, m, r, ro) => o.RelatedOrderId == ro.Id)
2026-04-05 20:58:17 +08:00
// 默认只导出已完成支付流程的订单(已支付、已发货、已完成、已退款)
.WhereIF(!input.OrderStatus.HasValue, (o, e, m, r, ro) =>
o.OrderStatus == OrderStatus.Paid ||
o.OrderStatus == OrderStatus.Shipped ||
o.OrderStatus == OrderStatus.Completed ||
o.OrderStatus == OrderStatus.Refunded)
2026-03-07 23:47:13 +08:00
.WhereIF(!string.IsNullOrWhiteSpace(input.OrderNo), (o, e, m, r, ro) => o.OrderNo.Contains(input.OrderNo))
.WhereIF(!string.IsNullOrWhiteSpace(input.EventName), (o, e, m, r, ro) => e.EventName.Contains(input.EventName))
.WhereIF(input.OrderType.HasValue, (o, e, m, r, ro) => o.OrderType == input.OrderType)
.WhereIF(input.OrderStatus.HasValue, (o, e, m, r, ro) => o.OrderStatus == input.OrderStatus)
.WhereIF(input.PaymentMethod.HasValue, (o, e, m, r, ro) => o.PaymentMethod == input.PaymentMethod)
.WhereIF(input.RegistrationMode.HasValue, (o, e, m, r, ro) => o.RegistrationMode == input.RegistrationMode)
.WhereIF(!string.IsNullOrWhiteSpace(input.ContactPhone), (o, e, m, r, ro) => r.ContactPhone.Contains(input.ContactPhone))
.WhereIF(input.StartTime.HasValue, (o, e, m, r, ro) => o.CreatedTime >= input.StartTime)
.WhereIF(input.EndTime.HasValue, (o, e, m, r, ro) => o.CreatedTime <= input.EndTime)
.OrderByDescending((o, e, m, r, ro) => o.CreatedTime)
.Select((o, e, m, r, ro) => new OrderListOutput
{
OrderNo = o.OrderNo,
UnitName = SqlFunc.IsNullOrEmpty(m.MerchantName) ? "/" : m.MerchantName,
EventName = e.EventName,
OrderType = o.OrderType == 1 ? "收入" : "退款",
RelatedOrderNo = ro.OrderNo,
PaymentMethod = o.PaymentMethod == 1 ? "线上" : "线下",
RegistrationMode = o.RegistrationMode == 1 ? "个人" : "团队",
ContactName = r.ContactName,
ContactPhone = r.ContactPhone,
OriginalAmount = o.OriginalAmount,
DiscountAmount = o.DiscountAmount,
ActualAmount = o.ActualAmount,
OrderStatus = o.OrderStatus,
OrderStatusText =
o.OrderStatus == OrderStatus.Pending ? "待支付" :
o.OrderStatus == OrderStatus.Paid ? "已支付" :
o.OrderStatus == OrderStatus.Cancelled ? "已取消" :
o.OrderStatus == OrderStatus.Refunded ? "已退款" :
o.OrderStatus == OrderStatus.Shipped ? "已发货" :
o.OrderStatus == OrderStatus.Completed ? "已完成" : "",
2026-03-07 23:47:13 +08:00
CreatedTime = o.CreatedTime
})
.ToListAsync();
2026-04-05 20:58:17 +08:00
var bytes = await GenerateOrderExcelAsync(list);
return new FileContentResult(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileDownloadName = $"订单列表_{DateTime.Now:yyyyMMddHHmmss}.xlsx"
};
}
2026-03-07 23:47:13 +08:00
2026-04-05 20:58:17 +08:00
/// <summary>
/// 生成订单Excel文件
/// </summary>
private async Task<byte[]> GenerateOrderExcelAsync(List<OrderListOutput> orders)
{
ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
2026-03-07 23:47:13 +08:00
2026-04-05 20:58:17 +08:00
using var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("订单列表");
var rowIndex = 1;
// 计算汇总数据
var totalOriginal = orders.Sum(x => x.OriginalAmount);
var totalDiscount = orders.Sum(x => x.DiscountAmount);
var totalRefund = orders.Where(x => x.OrderType == "退款").Sum(x => x.ActualAmount);
var totalActual = orders.Where(x => x.OrderType == "收入").Sum(x => x.ActualAmount);
// 汇总信息行
var summaryRange = worksheet.Cells[rowIndex, 1, rowIndex, 14];
summaryRange.Merge = true;
summaryRange.Value = $"汇总信息: 原金额:{totalOriginal}, 优惠金额:{totalDiscount}, 退款金额:{totalRefund}, 实付金额:{totalActual}";
var summaryStyle = summaryRange.Style;
summaryStyle.Font.Bold = true;
summaryStyle.Font.Size = 12;
summaryStyle.HorizontalAlignment = ExcelHorizontalAlignment.Center;
summaryStyle.VerticalAlignment = ExcelVerticalAlignment.Center;
summaryStyle.Fill.PatternType = ExcelFillStyle.Solid;
summaryStyle.Fill.BackgroundColor.SetColor(Color.LightGray);
rowIndex++;
// 列标题
var headers = new[]
{
"订单编号", "单位名称", "所属赛事", "订单类型", "关联订单",
"支付方式", "报名方式", "报名用户", "报名账号", "原金额(元)",
"优惠金额(元)", "退款金额(元)", "实付金额(元)", "生成时间"
};
for (int i = 0; i < headers.Length; i++)
{
2026-04-05 20:58:17 +08:00
worksheet.Cells[rowIndex, i + 1].Value = headers[i];
}
2026-04-05 20:58:17 +08:00
var headerRange = worksheet.Cells[rowIndex, 1, rowIndex, headers.Length];
var headerStyle = headerRange.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.LightBlue);
SetCellBorders(headerRange, ExcelBorderStyle.Thin);
rowIndex++;
// 数据行
foreach (var item in orders)
{
2026-04-05 20:58:17 +08:00
var refundAmount = item.OrderType == "退款" ? item.ActualAmount : 0;
var actualPayAmount = item.OrderType == "收入" ? item.ActualAmount : 0;
worksheet.Cells[rowIndex, 1].Value = item.OrderNo;
worksheet.Cells[rowIndex, 2].Value = item.UnitName;
worksheet.Cells[rowIndex, 3].Value = item.EventName;
worksheet.Cells[rowIndex, 4].Value = item.OrderType;
worksheet.Cells[rowIndex, 5].Value = item.RelatedOrderNo;
worksheet.Cells[rowIndex, 6].Value = item.PaymentMethod;
worksheet.Cells[rowIndex, 7].Value = item.RegistrationMode;
worksheet.Cells[rowIndex, 8].Value = item.ContactName;
worksheet.Cells[rowIndex, 9].Value = item.ContactPhone;
worksheet.Cells[rowIndex, 10].Value = item.OriginalAmount;
worksheet.Cells[rowIndex, 11].Value = item.DiscountAmount;
worksheet.Cells[rowIndex, 12].Value = refundAmount;
worksheet.Cells[rowIndex, 13].Value = actualPayAmount;
worksheet.Cells[rowIndex, 14].Value = item.CreatedTime.ToString("yyyy-MM-dd HH:mm:ss");
// 设置金额格式
worksheet.Cells[rowIndex, 10].Style.Numberformat.Format = "0.00";
worksheet.Cells[rowIndex, 11].Style.Numberformat.Format = "0.00";
worksheet.Cells[rowIndex, 12].Style.Numberformat.Format = "0.00";
worksheet.Cells[rowIndex, 13].Style.Numberformat.Format = "0.00";
SetDataRowStyle(worksheet, rowIndex, 14);
rowIndex++;
}
// 设置列宽
var columnWidths = new double[] { 18, 15, 15, 10, 12, 10, 10, 12, 14, 12, 14, 14, 12, 18 };
for (int i = 0; i < columnWidths.Length; i++)
{
worksheet.Column(i + 1).Width = columnWidths[i];
}
// 冻结表头
worksheet.View.FreezePanes(3, 1);
return await package.GetAsByteArrayAsync();
}
/// <summary>
/// 设置单元格边框
/// </summary>
private 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;
}
/// <summary>
/// 设置数据行样式
/// </summary>
private void SetDataRowStyle(ExcelWorksheet worksheet, int rowIndex, int colCount)
{
var range = worksheet.Cells[rowIndex, 1, rowIndex, colCount];
var style = range.Style;
style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
style.VerticalAlignment = ExcelVerticalAlignment.Center;
SetCellBorders(range, ExcelBorderStyle.Thin);
}
}