diff --git a/SimpleAdmin.sln.DotSettings.user b/SimpleAdmin.sln.DotSettings.user
index 71de70b..c58fa73 100644
--- a/SimpleAdmin.sln.DotSettings.user
+++ b/SimpleAdmin.sln.DotSettings.user
@@ -1,4 +1,5 @@
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded
\ No newline at end of file
diff --git a/src/Oms.Application/Dtos/Orders/OrderExportInput.cs b/src/Oms.Application/Dtos/Orders/OrderExportInput.cs
index 60d80cb..8264eb0 100644
--- a/src/Oms.Application/Dtos/Orders/OrderExportInput.cs
+++ b/src/Oms.Application/Dtos/Orders/OrderExportInput.cs
@@ -1,12 +1,27 @@
namespace Oms.Application.Dtos.Orders;
+///
+/// 订单导出入参。
+///
public class OrderExportInput
{
+ ///
+ /// 订单状态,传 all 或空值时表示不过滤。
+ ///
public string? Status { get; set; }
+ ///
+ /// 关键词,可匹配运单号、客户单号、跟踪号。
+ ///
public string? Keyword { get; set; }
+ ///
+ /// 创建时间起始值。
+ ///
public DateTime? CreateTimeStart { get; set; }
+ ///
+ /// 创建时间结束值。
+ ///
public DateTime? CreateTimeEnd { get; set; }
}
diff --git a/src/Oms.Application/Dtos/Orders/OrderPaginatedInput.cs b/src/Oms.Application/Dtos/Orders/OrderPaginatedInput.cs
index 5cd22c1..4aacae7 100644
--- a/src/Oms.Application/Dtos/Orders/OrderPaginatedInput.cs
+++ b/src/Oms.Application/Dtos/Orders/OrderPaginatedInput.cs
@@ -1,16 +1,37 @@
namespace Oms.Application.Dtos.Orders;
+///
+/// 订单列表分页查询入参。
+///
public class OrderPaginatedInput
{
+ ///
+ /// 页码,从 1 开始。
+ ///
public int Page { get; set; } = 1;
+ ///
+ /// 每页条数。
+ ///
public int PageSize { get; set; } = 20;
+ ///
+ /// 订单状态,传 all 或空值时表示不过滤。
+ ///
public string? Status { get; set; }
+ ///
+ /// 关键词,可匹配运单号、客户单号、跟踪号。
+ ///
public string? Keyword { get; set; }
+ ///
+ /// 创建时间起始值。
+ ///
public DateTime? CreateTimeStart { get; set; }
+ ///
+ /// 创建时间结束值。
+ ///
public DateTime? CreateTimeEnd { get; set; }
}
diff --git a/src/Oms.Application/Dtos/Recharge/RechargeExportInput.cs b/src/Oms.Application/Dtos/Recharge/RechargeExportInput.cs
index 4075f57..b4815ea 100644
--- a/src/Oms.Application/Dtos/Recharge/RechargeExportInput.cs
+++ b/src/Oms.Application/Dtos/Recharge/RechargeExportInput.cs
@@ -1,10 +1,22 @@
namespace Oms.Application.Dtos.Recharge;
+///
+/// 充值记录导出入参。
+///
public class RechargeExportInput
{
+ ///
+ /// 客户 ID,空值表示不过滤。
+ ///
public long? CustomerId { get; set; }
+ ///
+ /// 充值时间起始值。
+ ///
public DateTime? StartTime { get; set; }
+ ///
+ /// 充值时间结束值。
+ ///
public DateTime? EndTime { get; set; }
}
diff --git a/src/Oms.Application/Dtos/Recharge/RechargeRecordPaginatedInput.cs b/src/Oms.Application/Dtos/Recharge/RechargeRecordPaginatedInput.cs
index 77c7d45..27041e0 100644
--- a/src/Oms.Application/Dtos/Recharge/RechargeRecordPaginatedInput.cs
+++ b/src/Oms.Application/Dtos/Recharge/RechargeRecordPaginatedInput.cs
@@ -2,19 +2,43 @@ using Oms.Domain.RechargeAggregate.Enums;
namespace Oms.Application.Dtos.Recharge;
+///
+/// 充值记录分页查询入参。
+///
public class RechargeRecordPaginatedInput
{
+ ///
+ /// 页码,从 1 开始。
+ ///
public int Page { get; set; } = 1;
+ ///
+ /// 每页条数。
+ ///
public int PageSize { get; set; } = 20;
+ ///
+ /// 客户 ID,空值表示不过滤。
+ ///
public long? CustomerId { get; set; }
+ ///
+ /// 充值流水号,支持模糊匹配。
+ ///
public string? SerialNumber { get; set; }
+ ///
+ /// 充值审核状态,空值表示不过滤。
+ ///
public RechargeStatus? RechargeStatus { get; set; }
+ ///
+ /// 充值时间起始值。
+ ///
public DateTime? StartTime { get; set; }
+ ///
+ /// 充值时间结束值。
+ ///
public DateTime? EndTime { get; set; }
}
diff --git a/src/Oms.Application/Services/Orders/OrderService.cs b/src/Oms.Application/Services/Orders/OrderService.cs
index 1580586..63ee798 100644
--- a/src/Oms.Application/Services/Orders/OrderService.cs
+++ b/src/Oms.Application/Services/Orders/OrderService.cs
@@ -25,6 +25,17 @@ public partial class OrderService : ApplicationService
private ISalesProductRepository SalesProductRepository => LazyServiceProvider.GetRequiredService();
private IWebHostEnvironment WebHostEnvironment => LazyServiceProvider.GetRequiredService();
+ ///
+ /// 分页查询订单列表。
+ ///
+ /// 入参:分页信息、订单状态、关键词、创建时间起止。
+ /// 出参:订单分页结果,包含当前页订单集合和总记录数。
+ ///
+ /// 核心业务逻辑:
+ /// 1. 统一归一化页码和页大小;
+ /// 2. 根据状态、关键词、创建时间区间构造筛选表达式;
+ /// 3. 查询分页数据后补齐订单展示所需的映射字段。
+ ///
[HttpPost("/order/list")]
public async Task> GetPaginatedListAsync(OrderPaginatedInput input)
{
@@ -97,6 +108,14 @@ public partial class OrderService : ApplicationService
return new OrderPrintOutput { PrintUrl = printUrl };
}
+ ///
+ /// 导出订单列表。
+ ///
+ /// 入参:订单状态、关键词、创建时间起止。
+ /// 出参:导出文件下载地址及失效时间。
+ ///
+ /// 核心业务逻辑:先清理过期文件,再按筛选条件查询订单,最后生成 Excel 并返回下载信息。
+ ///
[HttpPost("/order/export")]
public async Task ExportAsync(OrderExportInput input)
{
@@ -159,16 +178,41 @@ public partial class OrderService : ApplicationService
return await CreateParcelCoreAsync(input);
}
+ ///
+ /// 将订单列表请求对象转换为仓储可执行的查询表达式。
+ ///
+ /// 入参:分页查询条件对象。
+ /// 出参:订单查询表达式。
private Expression> BuildPaginatedPredicate(OrderPaginatedInput input)
{
return BuildOrderPredicate(input.Status, input.Keyword, input.CreateTimeStart, input.CreateTimeEnd);
}
+ ///
+ /// 将订单导出请求对象转换为仓储可执行的查询表达式。
+ ///
+ /// 入参:导出筛选条件对象。
+ /// 出参:订单查询表达式。
private Expression> BuildExportPredicate(OrderExportInput input)
{
return BuildOrderPredicate(input.Status, input.Keyword, input.CreateTimeStart, input.CreateTimeEnd);
}
+ ///
+ /// 统一构造订单查询条件。
+ ///
+ /// 入参:订单状态,传入 all 或空值时表示不按状态过滤。
+ /// 入参:关键词,可匹配运单号、客户单号、跟踪号。
+ /// 入参:创建时间开始值。
+ /// 入参:创建时间结束值。
+ /// 出参:可直接交给 SqlSugar 仓储执行的订单筛选表达式。
+ ///
+ /// 核心业务逻辑:
+ /// 1. 先把状态和关键词做统一清洗;
+ /// 2. 再按时间区间是否存在拆分成不同表达式;
+ /// 3. 避免把 / 放进可翻译 SQL 的表达式中,
+ /// 从而规避 MySQL 下时间条件被错误翻译的问题。
+ ///
private static Expression> BuildOrderPredicate(
string? status,
string? keyword,
@@ -180,6 +224,7 @@ public partial class OrderService : ApplicationService
var hasStatusFilter = !string.IsNullOrWhiteSpace(status) && status != "all";
var hasKeywordFilter = !string.IsNullOrWhiteSpace(keyword);
+ // 显式拆开时间分支,避免 SqlSugar 在翻译 Nullable 判空时生成异常 SQL。
if (createTimeStart.HasValue && createTimeEnd.HasValue)
{
var start = createTimeStart.Value;
diff --git a/src/Oms.Application/Services/Recharge/RechargeService.cs b/src/Oms.Application/Services/Recharge/RechargeService.cs
index 07e96dd..75a458b 100644
--- a/src/Oms.Application/Services/Recharge/RechargeService.cs
+++ b/src/Oms.Application/Services/Recharge/RechargeService.cs
@@ -106,6 +106,17 @@ public class RechargeService : ApplicationService
await RechargeRecordRepository.UpdateAsync(record);
}
+ ///
+ /// 分页查询充值记录列表。
+ ///
+ /// 入参:分页信息、客户、充值流水号、审核状态、充值时间区间。
+ /// 出参:充值记录分页结果,包含列表数据和总记录数。
+ ///
+ /// 核心业务逻辑:
+ /// 1. 先根据筛选条件查询充值记录;
+ /// 2. 再批量补齐客户编码和手机号等展示字段;
+ /// 3. 最后返回前端可直接渲染的分页结果。
+ ///
[HttpGet("/recharge/recharge-record/list")]
public async Task> GetPaginatedListAsync([FromQuery] RechargeRecordPaginatedInput input)
{
@@ -127,6 +138,7 @@ public class RechargeService : ApplicationService
: await CustomerRepository.GetListAsync(x => !x.IsDeleted && customerIds.Contains(x.Id));
var customerMap = customers.ToDictionary(x => x.Id);
+ // 列表返回时补齐客户信息,避免前端为了展示字段额外发起关联查询。
foreach (var entity in entities)
{
var output = ObjectMapper.Map(entity);
@@ -149,6 +161,14 @@ public class RechargeService : ApplicationService
};
}
+ ///
+ /// 导出充值记录。
+ ///
+ /// 入参:客户和充值时间区间。
+ /// 出参:Excel 文件内容。
+ ///
+ /// 核心业务逻辑:根据导出条件查询充值记录,补齐客户展示字段后直接生成 Excel 文件流。
+ ///
[HttpGet("/recharge/export")]
public async Task ExportAsync([FromQuery] RechargeExportInput input)
{
@@ -189,6 +209,11 @@ public class RechargeService : ApplicationService
};
}
+ ///
+ /// 将充值分页请求对象转换为仓储可执行的查询表达式。
+ ///
+ /// 入参:充值分页查询条件对象。
+ /// 出参:充值记录查询表达式。
private Expression> BuildPaginatedPredicate(RechargeRecordPaginatedInput input)
{
var serialNumber = input.SerialNumber?.Trim();
@@ -241,11 +266,31 @@ public class RechargeService : ApplicationService
};
}
+ ///
+ /// 将充值导出请求对象转换为仓储可执行的查询表达式。
+ ///
+ /// 入参:充值导出筛选条件对象。
+ /// 出参:充值记录查询表达式。
private Expression> BuildExportPredicate(RechargeExportInput input)
{
return BuildRechargePredicate(input.CustomerId, null, null, input.StartTime, input.EndTime);
}
+ ///
+ /// 统一构造充值记录查询条件。
+ ///
+ /// 入参:客户 ID,空值表示不过滤。
+ /// 入参:充值状态,空值表示不过滤。
+ /// 入参:充值流水号关键词,空值表示不过滤。
+ /// 入参:充值时间开始值。
+ /// 入参:充值时间结束值。
+ /// 出参:可直接交给 SqlSugar 仓储执行的充值记录筛选表达式。
+ ///
+ /// 核心业务逻辑:
+ /// 1. 将可选筛选条件先转换成布尔开关和值;
+ /// 2. 根据时间区间是否存在拆分表达式;
+ /// 3. 避免在 SQL 翻译阶段混用 Nullable 时间判空和比较,降低生成异常 SQL 的风险。
+ ///
private static Expression> BuildRechargePredicate(
long? customerId,
RechargeStatus? rechargeStatus,
@@ -259,6 +304,7 @@ public class RechargeService : ApplicationService
var rechargeStatusValue = rechargeStatus.GetValueOrDefault();
var hasSerialNumberFilter = !string.IsNullOrWhiteSpace(serialNumber);
+ // 显式拆开时间分支,保证 ORM 只翻译纯比较表达式。
if (startTime.HasValue && endTime.HasValue)
{
var start = startTime.Value;
diff --git a/src/SimpleAdmin.Api/SimpleAdmin.Api.csproj b/src/SimpleAdmin.Api/SimpleAdmin.Api.csproj
index 3b0de97..dba2e2d 100644
--- a/src/SimpleAdmin.Api/SimpleAdmin.Api.csproj
+++ b/src/SimpleAdmin.Api/SimpleAdmin.Api.csproj
@@ -4,7 +4,6 @@
net8.0
enable
enable
- e3d506cf-f5ce-4ba5-bc8e-ab2c179f3034
Linux