feat: remarks
This commit is contained in:
parent
91a8ccdecb
commit
b912c5b159
@ -1,4 +1,5 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AClient_002Ecs_002Fl_003AC_0021_003FUsers_003FBSI_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fc7d66b24252bb52da52d1262d99fd654ffc18aedde818f147c3daf6aee3e63_003FClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIAggregateRoot_002Ecs_002Fl_003AC_0021_003FUsers_003FBSI_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6015bad29db142679ead208ae4ecd55c7800_003F0e_003F66feb813_003FIAggregateRoot_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIAggregateRoot_002Ecs_002Fl_003AC_0021_003FUsers_003FBSI_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6015bad29db142679ead208ae4ecd55c7800_003F0e_003F66feb813_003FIAggregateRoot_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIAggregateRoot_00601_002Ecs_002Fl_003AC_0021_003FUsers_003FBSI_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6015bad29db142679ead208ae4ecd55c7800_003F9a_003Fea4337c7_003FIAggregateRoot_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIAggregateRoot_00601_002Ecs_002Fl_003AC_0021_003FUsers_003FBSI_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6015bad29db142679ead208ae4ecd55c7800_003F9a_003Fea4337c7_003FIAggregateRoot_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIRepository_00601_002Ecs_002Fl_003AC_0021_003FUsers_003FBSI_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6015bad29db142679ead208ae4ecd55c7800_003F85_003Fa6db724e_003FIRepository_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIRepository_00601_002Ecs_002Fl_003AC_0021_003FUsers_003FBSI_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6015bad29db142679ead208ae4ecd55c7800_003F85_003Fa6db724e_003FIRepository_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
||||||
@ -1,12 +1,27 @@
|
|||||||
namespace Oms.Application.Dtos.Orders;
|
namespace Oms.Application.Dtos.Orders;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订单导出入参。
|
||||||
|
/// </summary>
|
||||||
public class OrderExportInput
|
public class OrderExportInput
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 订单状态,传 <c>all</c> 或空值时表示不过滤。
|
||||||
|
/// </summary>
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 关键词,可匹配运单号、客户单号、跟踪号。
|
||||||
|
/// </summary>
|
||||||
public string? Keyword { get; set; }
|
public string? Keyword { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建时间起始值。
|
||||||
|
/// </summary>
|
||||||
public DateTime? CreateTimeStart { get; set; }
|
public DateTime? CreateTimeStart { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建时间结束值。
|
||||||
|
/// </summary>
|
||||||
public DateTime? CreateTimeEnd { get; set; }
|
public DateTime? CreateTimeEnd { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,37 @@
|
|||||||
namespace Oms.Application.Dtos.Orders;
|
namespace Oms.Application.Dtos.Orders;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订单列表分页查询入参。
|
||||||
|
/// </summary>
|
||||||
public class OrderPaginatedInput
|
public class OrderPaginatedInput
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 页码,从 1 开始。
|
||||||
|
/// </summary>
|
||||||
public int Page { get; set; } = 1;
|
public int Page { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每页条数。
|
||||||
|
/// </summary>
|
||||||
public int PageSize { get; set; } = 20;
|
public int PageSize { get; set; } = 20;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订单状态,传 <c>all</c> 或空值时表示不过滤。
|
||||||
|
/// </summary>
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 关键词,可匹配运单号、客户单号、跟踪号。
|
||||||
|
/// </summary>
|
||||||
public string? Keyword { get; set; }
|
public string? Keyword { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建时间起始值。
|
||||||
|
/// </summary>
|
||||||
public DateTime? CreateTimeStart { get; set; }
|
public DateTime? CreateTimeStart { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建时间结束值。
|
||||||
|
/// </summary>
|
||||||
public DateTime? CreateTimeEnd { get; set; }
|
public DateTime? CreateTimeEnd { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,22 @@
|
|||||||
namespace Oms.Application.Dtos.Recharge;
|
namespace Oms.Application.Dtos.Recharge;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 充值记录导出入参。
|
||||||
|
/// </summary>
|
||||||
public class RechargeExportInput
|
public class RechargeExportInput
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 客户 ID,空值表示不过滤。
|
||||||
|
/// </summary>
|
||||||
public long? CustomerId { get; set; }
|
public long? CustomerId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 充值时间起始值。
|
||||||
|
/// </summary>
|
||||||
public DateTime? StartTime { get; set; }
|
public DateTime? StartTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 充值时间结束值。
|
||||||
|
/// </summary>
|
||||||
public DateTime? EndTime { get; set; }
|
public DateTime? EndTime { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,19 +2,43 @@ using Oms.Domain.RechargeAggregate.Enums;
|
|||||||
|
|
||||||
namespace Oms.Application.Dtos.Recharge;
|
namespace Oms.Application.Dtos.Recharge;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 充值记录分页查询入参。
|
||||||
|
/// </summary>
|
||||||
public class RechargeRecordPaginatedInput
|
public class RechargeRecordPaginatedInput
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 页码,从 1 开始。
|
||||||
|
/// </summary>
|
||||||
public int Page { get; set; } = 1;
|
public int Page { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每页条数。
|
||||||
|
/// </summary>
|
||||||
public int PageSize { get; set; } = 20;
|
public int PageSize { get; set; } = 20;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 客户 ID,空值表示不过滤。
|
||||||
|
/// </summary>
|
||||||
public long? CustomerId { get; set; }
|
public long? CustomerId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 充值流水号,支持模糊匹配。
|
||||||
|
/// </summary>
|
||||||
public string? SerialNumber { get; set; }
|
public string? SerialNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 充值审核状态,空值表示不过滤。
|
||||||
|
/// </summary>
|
||||||
public RechargeStatus? RechargeStatus { get; set; }
|
public RechargeStatus? RechargeStatus { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 充值时间起始值。
|
||||||
|
/// </summary>
|
||||||
public DateTime? StartTime { get; set; }
|
public DateTime? StartTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 充值时间结束值。
|
||||||
|
/// </summary>
|
||||||
public DateTime? EndTime { get; set; }
|
public DateTime? EndTime { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,17 @@ public partial class OrderService : ApplicationService
|
|||||||
private ISalesProductRepository SalesProductRepository => LazyServiceProvider.GetRequiredService<ISalesProductRepository>();
|
private ISalesProductRepository SalesProductRepository => LazyServiceProvider.GetRequiredService<ISalesProductRepository>();
|
||||||
private IWebHostEnvironment WebHostEnvironment => LazyServiceProvider.GetRequiredService<IWebHostEnvironment>();
|
private IWebHostEnvironment WebHostEnvironment => LazyServiceProvider.GetRequiredService<IWebHostEnvironment>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 分页查询订单列表。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">入参:分页信息、订单状态、关键词、创建时间起止。</param>
|
||||||
|
/// <returns>出参:订单分页结果,包含当前页订单集合和总记录数。</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// 核心业务逻辑:
|
||||||
|
/// 1. 统一归一化页码和页大小;
|
||||||
|
/// 2. 根据状态、关键词、创建时间区间构造筛选表达式;
|
||||||
|
/// 3. 查询分页数据后补齐订单展示所需的映射字段。
|
||||||
|
/// </remarks>
|
||||||
[HttpPost("/order/list")]
|
[HttpPost("/order/list")]
|
||||||
public async Task<OmsPageResult<OrderOutput>> GetPaginatedListAsync(OrderPaginatedInput input)
|
public async Task<OmsPageResult<OrderOutput>> GetPaginatedListAsync(OrderPaginatedInput input)
|
||||||
{
|
{
|
||||||
@ -97,6 +108,14 @@ public partial class OrderService : ApplicationService
|
|||||||
return new OrderPrintOutput { PrintUrl = printUrl };
|
return new OrderPrintOutput { PrintUrl = printUrl };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导出订单列表。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">入参:订单状态、关键词、创建时间起止。</param>
|
||||||
|
/// <returns>出参:导出文件下载地址及失效时间。</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// 核心业务逻辑:先清理过期文件,再按筛选条件查询订单,最后生成 Excel 并返回下载信息。
|
||||||
|
/// </remarks>
|
||||||
[HttpPost("/order/export")]
|
[HttpPost("/order/export")]
|
||||||
public async Task<OrderExportOutput> ExportAsync(OrderExportInput input)
|
public async Task<OrderExportOutput> ExportAsync(OrderExportInput input)
|
||||||
{
|
{
|
||||||
@ -159,16 +178,41 @@ public partial class OrderService : ApplicationService
|
|||||||
return await CreateParcelCoreAsync(input);
|
return await CreateParcelCoreAsync(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将订单列表请求对象转换为仓储可执行的查询表达式。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">入参:分页查询条件对象。</param>
|
||||||
|
/// <returns>出参:订单查询表达式。</returns>
|
||||||
private Expression<Func<Order, bool>> BuildPaginatedPredicate(OrderPaginatedInput input)
|
private Expression<Func<Order, bool>> BuildPaginatedPredicate(OrderPaginatedInput input)
|
||||||
{
|
{
|
||||||
return BuildOrderPredicate(input.Status, input.Keyword, input.CreateTimeStart, input.CreateTimeEnd);
|
return BuildOrderPredicate(input.Status, input.Keyword, input.CreateTimeStart, input.CreateTimeEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将订单导出请求对象转换为仓储可执行的查询表达式。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">入参:导出筛选条件对象。</param>
|
||||||
|
/// <returns>出参:订单查询表达式。</returns>
|
||||||
private Expression<Func<Order, bool>> BuildExportPredicate(OrderExportInput input)
|
private Expression<Func<Order, bool>> BuildExportPredicate(OrderExportInput input)
|
||||||
{
|
{
|
||||||
return BuildOrderPredicate(input.Status, input.Keyword, input.CreateTimeStart, input.CreateTimeEnd);
|
return BuildOrderPredicate(input.Status, input.Keyword, input.CreateTimeStart, input.CreateTimeEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 统一构造订单查询条件。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="status">入参:订单状态,传入 <c>all</c> 或空值时表示不按状态过滤。</param>
|
||||||
|
/// <param name="keyword">入参:关键词,可匹配运单号、客户单号、跟踪号。</param>
|
||||||
|
/// <param name="createTimeStart">入参:创建时间开始值。</param>
|
||||||
|
/// <param name="createTimeEnd">入参:创建时间结束值。</param>
|
||||||
|
/// <returns>出参:可直接交给 SqlSugar 仓储执行的订单筛选表达式。</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// 核心业务逻辑:
|
||||||
|
/// 1. 先把状态和关键词做统一清洗;
|
||||||
|
/// 2. 再按时间区间是否存在拆分成不同表达式;
|
||||||
|
/// 3. 避免把 <see cref="Nullable{T}.HasValue"/> / <see cref="Nullable{T}.Value"/> 放进可翻译 SQL 的表达式中,
|
||||||
|
/// 从而规避 MySQL 下时间条件被错误翻译的问题。
|
||||||
|
/// </remarks>
|
||||||
private static Expression<Func<Order, bool>> BuildOrderPredicate(
|
private static Expression<Func<Order, bool>> BuildOrderPredicate(
|
||||||
string? status,
|
string? status,
|
||||||
string? keyword,
|
string? keyword,
|
||||||
@ -180,6 +224,7 @@ public partial class OrderService : ApplicationService
|
|||||||
var hasStatusFilter = !string.IsNullOrWhiteSpace(status) && status != "all";
|
var hasStatusFilter = !string.IsNullOrWhiteSpace(status) && status != "all";
|
||||||
var hasKeywordFilter = !string.IsNullOrWhiteSpace(keyword);
|
var hasKeywordFilter = !string.IsNullOrWhiteSpace(keyword);
|
||||||
|
|
||||||
|
// 显式拆开时间分支,避免 SqlSugar 在翻译 Nullable<DateTime> 判空时生成异常 SQL。
|
||||||
if (createTimeStart.HasValue && createTimeEnd.HasValue)
|
if (createTimeStart.HasValue && createTimeEnd.HasValue)
|
||||||
{
|
{
|
||||||
var start = createTimeStart.Value;
|
var start = createTimeStart.Value;
|
||||||
|
|||||||
@ -106,6 +106,17 @@ public class RechargeService : ApplicationService
|
|||||||
await RechargeRecordRepository.UpdateAsync(record);
|
await RechargeRecordRepository.UpdateAsync(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 分页查询充值记录列表。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">入参:分页信息、客户、充值流水号、审核状态、充值时间区间。</param>
|
||||||
|
/// <returns>出参:充值记录分页结果,包含列表数据和总记录数。</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// 核心业务逻辑:
|
||||||
|
/// 1. 先根据筛选条件查询充值记录;
|
||||||
|
/// 2. 再批量补齐客户编码和手机号等展示字段;
|
||||||
|
/// 3. 最后返回前端可直接渲染的分页结果。
|
||||||
|
/// </remarks>
|
||||||
[HttpGet("/recharge/recharge-record/list")]
|
[HttpGet("/recharge/recharge-record/list")]
|
||||||
public async Task<OmsPageResult<RechargeRecordPaginatedOutput>> GetPaginatedListAsync([FromQuery] RechargeRecordPaginatedInput input)
|
public async Task<OmsPageResult<RechargeRecordPaginatedOutput>> GetPaginatedListAsync([FromQuery] RechargeRecordPaginatedInput input)
|
||||||
{
|
{
|
||||||
@ -127,6 +138,7 @@ public class RechargeService : ApplicationService
|
|||||||
: await CustomerRepository.GetListAsync(x => !x.IsDeleted && customerIds.Contains(x.Id));
|
: await CustomerRepository.GetListAsync(x => !x.IsDeleted && customerIds.Contains(x.Id));
|
||||||
var customerMap = customers.ToDictionary(x => x.Id);
|
var customerMap = customers.ToDictionary(x => x.Id);
|
||||||
|
|
||||||
|
// 列表返回时补齐客户信息,避免前端为了展示字段额外发起关联查询。
|
||||||
foreach (var entity in entities)
|
foreach (var entity in entities)
|
||||||
{
|
{
|
||||||
var output = ObjectMapper.Map<RechargeRecord, RechargeRecordPaginatedOutput>(entity);
|
var output = ObjectMapper.Map<RechargeRecord, RechargeRecordPaginatedOutput>(entity);
|
||||||
@ -149,6 +161,14 @@ public class RechargeService : ApplicationService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导出充值记录。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">入参:客户和充值时间区间。</param>
|
||||||
|
/// <returns>出参:Excel 文件内容。</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// 核心业务逻辑:根据导出条件查询充值记录,补齐客户展示字段后直接生成 Excel 文件流。
|
||||||
|
/// </remarks>
|
||||||
[HttpGet("/recharge/export")]
|
[HttpGet("/recharge/export")]
|
||||||
public async Task<FileContentResult> ExportAsync([FromQuery] RechargeExportInput input)
|
public async Task<FileContentResult> ExportAsync([FromQuery] RechargeExportInput input)
|
||||||
{
|
{
|
||||||
@ -189,6 +209,11 @@ public class RechargeService : ApplicationService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将充值分页请求对象转换为仓储可执行的查询表达式。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">入参:充值分页查询条件对象。</param>
|
||||||
|
/// <returns>出参:充值记录查询表达式。</returns>
|
||||||
private Expression<Func<RechargeRecord, bool>> BuildPaginatedPredicate(RechargeRecordPaginatedInput input)
|
private Expression<Func<RechargeRecord, bool>> BuildPaginatedPredicate(RechargeRecordPaginatedInput input)
|
||||||
{
|
{
|
||||||
var serialNumber = input.SerialNumber?.Trim();
|
var serialNumber = input.SerialNumber?.Trim();
|
||||||
@ -241,11 +266,31 @@ public class RechargeService : ApplicationService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将充值导出请求对象转换为仓储可执行的查询表达式。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">入参:充值导出筛选条件对象。</param>
|
||||||
|
/// <returns>出参:充值记录查询表达式。</returns>
|
||||||
private Expression<Func<RechargeRecord, bool>> BuildExportPredicate(RechargeExportInput input)
|
private Expression<Func<RechargeRecord, bool>> BuildExportPredicate(RechargeExportInput input)
|
||||||
{
|
{
|
||||||
return BuildRechargePredicate(input.CustomerId, null, null, input.StartTime, input.EndTime);
|
return BuildRechargePredicate(input.CustomerId, null, null, input.StartTime, input.EndTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 统一构造充值记录查询条件。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="customerId">入参:客户 ID,空值表示不过滤。</param>
|
||||||
|
/// <param name="rechargeStatus">入参:充值状态,空值表示不过滤。</param>
|
||||||
|
/// <param name="serialNumber">入参:充值流水号关键词,空值表示不过滤。</param>
|
||||||
|
/// <param name="startTime">入参:充值时间开始值。</param>
|
||||||
|
/// <param name="endTime">入参:充值时间结束值。</param>
|
||||||
|
/// <returns>出参:可直接交给 SqlSugar 仓储执行的充值记录筛选表达式。</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// 核心业务逻辑:
|
||||||
|
/// 1. 将可选筛选条件先转换成布尔开关和值;
|
||||||
|
/// 2. 根据时间区间是否存在拆分表达式;
|
||||||
|
/// 3. 避免在 SQL 翻译阶段混用 Nullable 时间判空和比较,降低生成异常 SQL 的风险。
|
||||||
|
/// </remarks>
|
||||||
private static Expression<Func<RechargeRecord, bool>> BuildRechargePredicate(
|
private static Expression<Func<RechargeRecord, bool>> BuildRechargePredicate(
|
||||||
long? customerId,
|
long? customerId,
|
||||||
RechargeStatus? rechargeStatus,
|
RechargeStatus? rechargeStatus,
|
||||||
@ -259,6 +304,7 @@ public class RechargeService : ApplicationService
|
|||||||
var rechargeStatusValue = rechargeStatus.GetValueOrDefault();
|
var rechargeStatusValue = rechargeStatus.GetValueOrDefault();
|
||||||
var hasSerialNumberFilter = !string.IsNullOrWhiteSpace(serialNumber);
|
var hasSerialNumberFilter = !string.IsNullOrWhiteSpace(serialNumber);
|
||||||
|
|
||||||
|
// 显式拆开时间分支,保证 ORM 只翻译纯比较表达式。
|
||||||
if (startTime.HasValue && endTime.HasValue)
|
if (startTime.HasValue && endTime.HasValue)
|
||||||
{
|
{
|
||||||
var start = startTime.Value;
|
var start = startTime.Value;
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<UserSecretsId>e3d506cf-f5ce-4ba5-bc8e-ab2c179f3034</UserSecretsId>
|
|
||||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user