From b912c5b159b8e726e79b32b2f828c12cf75c81f2 Mon Sep 17 00:00:00 2001 From: xiaolipro <2357729423@qq.com> Date: Wed, 15 Apr 2026 16:50:57 +0800 Subject: [PATCH] feat: remarks --- SimpleAdmin.sln.DotSettings.user | 1 + .../Dtos/Orders/OrderExportInput.cs | 15 ++++++ .../Dtos/Orders/OrderPaginatedInput.cs | 21 +++++++++ .../Dtos/Recharge/RechargeExportInput.cs | 12 +++++ .../Recharge/RechargeRecordPaginatedInput.cs | 24 ++++++++++ .../Services/Orders/OrderService.cs | 45 ++++++++++++++++++ .../Services/Recharge/RechargeService.cs | 46 +++++++++++++++++++ src/SimpleAdmin.Api/SimpleAdmin.Api.csproj | 1 - 8 files changed, 164 insertions(+), 1 deletion(-) 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