feat: 卖价/买价列表支持按需加载明细,缩短切换卡顿
All checks were successful
Build and Deploy / deploy (push) Successful in 1m6s
All checks were successful
Build and Deploy / deploy (push) Successful in 1m6s
列表接口增加 includeDetails,并新增单条 price/get,供编辑弹窗按需拉取完整矩阵。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
6faadcf2a1
commit
a164d8c837
@ -101,17 +101,20 @@ public partial class SalesProductService
|
||||
|
||||
/// <summary>
|
||||
/// 一次性装配价格项、因子和明细,避免接口层 N+1 查询。
|
||||
/// includeDetails=false 时跳过明细(列表页首屏),显著减小载荷。
|
||||
/// </summary>
|
||||
private async Task<List<SalesProductPriceListOutput>> GetPriceOutputsAsync(int salesProductId)
|
||||
private async Task<List<SalesProductPriceListOutput>> GetPriceOutputsAsync(int salesProductId, bool includeDetails = true)
|
||||
{
|
||||
var prices = await SalesProductRepository.GetPricesAsync(salesProductId);
|
||||
var priceIds = prices.Select(x => x.Id).ToArray();
|
||||
var factorMap = (await SalesProductRepository.GetPriceFactorsAsync(priceIds))
|
||||
.GroupBy(x => x.PriceId)
|
||||
.ToDictionary(x => x.Key, x => x.OrderBy(item => item.SerialNumber).ToList());
|
||||
var detailMap = (await SalesProductRepository.GetPriceDetailsAsync(priceIds))
|
||||
var detailMap = includeDetails
|
||||
? (await SalesProductRepository.GetPriceDetailsAsync(priceIds))
|
||||
.GroupBy(x => x.PriceId)
|
||||
.ToDictionary(x => x.Key, x => x.OrderBy(item => item.Id).ToList());
|
||||
.ToDictionary(x => x.Key, x => x.OrderBy(item => item.Id).ToList())
|
||||
: new Dictionary<int, List<SalesProductPriceDetail>>();
|
||||
|
||||
var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
|
||||
prices.SelectMany(x => new[] { x.CreateUserId, x.UpdateUserId }));
|
||||
@ -128,7 +131,9 @@ public partial class SalesProductService
|
||||
Currency = price.Currency,
|
||||
ChargingCondition = price.ChargingCondition,
|
||||
Factors = factorMap.TryGetValue(price.Id, out var factors) ? factors.Select(MapPriceFactorOutput).ToList() : [],
|
||||
Details = detailMap.TryGetValue(price.Id, out var details) ? details.Select(MapPriceDetailOutput).ToList() : [],
|
||||
Details = includeDetails && detailMap.TryGetValue(price.Id, out var details)
|
||||
? details.Select(MapPriceDetailOutput).ToList()
|
||||
: [],
|
||||
CreateTime = price.CreateTime,
|
||||
CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(price.CreateUserId, auditUserNameMap),
|
||||
UpdateTime = OmsDocHelper.NullIfDefault(price.UpdateTime),
|
||||
@ -136,6 +141,38 @@ public partial class SalesProductService
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单条价格项(含因子+明细),供编辑弹窗按需加载。
|
||||
/// </summary>
|
||||
private async Task<SalesProductPriceListOutput> GetPriceOutputByIdAsync(int priceId)
|
||||
{
|
||||
var price = await GetPriceOrThrowAsync(priceId);
|
||||
var priceIds = new[] { price.Id };
|
||||
var factors = await SalesProductRepository.GetPriceFactorsAsync(priceIds);
|
||||
var details = await SalesProductRepository.GetPriceDetailsAsync(priceIds);
|
||||
var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
|
||||
[price.CreateUserId, price.UpdateUserId]);
|
||||
|
||||
return new SalesProductPriceListOutput
|
||||
{
|
||||
Id = price.Id,
|
||||
SalesProductId = price.SalesProductId,
|
||||
SerialNumber = price.SerialNumber,
|
||||
Status = (byte)price.Status,
|
||||
PriceName = price.PriceName,
|
||||
CostItem = price.CostItem,
|
||||
CostUnit = price.CostUnit,
|
||||
Currency = price.Currency,
|
||||
ChargingCondition = price.ChargingCondition,
|
||||
Factors = factors.OrderBy(item => item.SerialNumber).Select(MapPriceFactorOutput).ToList(),
|
||||
Details = details.OrderBy(item => item.Id).Select(MapPriceDetailOutput).ToList(),
|
||||
CreateTime = price.CreateTime,
|
||||
CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(price.CreateUserId, auditUserNameMap),
|
||||
UpdateTime = OmsDocHelper.NullIfDefault(price.UpdateTime),
|
||||
UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(price.UpdateUserId, auditUserNameMap)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取排货方案,并补充服务渠道名称。
|
||||
/// </summary>
|
||||
|
||||
@ -169,17 +169,29 @@ public partial class SalesProductService : ApplicationService
|
||||
/// 查询销售产品价格项列表。
|
||||
/// </summary>
|
||||
/// <param name="salesProductId">入参:销售产品主键。</param>
|
||||
/// <param name="includeDetails">是否返回价格明细矩阵;列表页建议 false。</param>
|
||||
/// <returns>销售产品价格项列表结果。</returns>
|
||||
[HttpGet("/channel/sales-product/price/list")]
|
||||
public async Task<OmsItemsResult<SalesProductPriceListOutput>> GetPriceListAsync([FromQuery] int salesProductId)
|
||||
public async Task<OmsItemsResult<SalesProductPriceListOutput>> GetPriceListAsync(
|
||||
[FromQuery] int salesProductId,
|
||||
[FromQuery] bool includeDetails = true)
|
||||
{
|
||||
await GetProductOrThrowAsync(salesProductId);
|
||||
return new OmsItemsResult<SalesProductPriceListOutput>
|
||||
{
|
||||
Items = await GetPriceOutputsAsync(salesProductId)
|
||||
Items = await GetPriceOutputsAsync(salesProductId, includeDetails)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取单条销售产品价格项(含计费因子与价格明细)。
|
||||
/// </summary>
|
||||
[HttpGet("/channel/sales-product/price/get")]
|
||||
public async Task<SalesProductPriceListOutput> GetPriceAsync([FromQuery] int id)
|
||||
{
|
||||
return await GetPriceOutputByIdAsync(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增销售产品价格项。
|
||||
/// </summary>
|
||||
|
||||
@ -146,17 +146,22 @@ public partial class ServiceChannelService
|
||||
|
||||
/// <summary>
|
||||
/// 一次性装配买价项、因子和明细,避免接口层 N+1 查询。
|
||||
/// includeDetails=false 时跳过明细(列表页首屏),显著减小载荷。
|
||||
/// </summary>
|
||||
private async Task<List<ServiceChannelPriceListOutput>> GetPriceOutputsAsync(int serviceChannelId)
|
||||
private async Task<List<ServiceChannelPriceListOutput>> GetPriceOutputsAsync(
|
||||
int serviceChannelId,
|
||||
bool includeDetails = true)
|
||||
{
|
||||
var prices = await ServiceChannelRepository.GetPricesAsync(serviceChannelId);
|
||||
var priceIds = prices.Select(x => x.Id).ToArray();
|
||||
var factorMap = (await ServiceChannelRepository.GetPriceFactorsAsync(priceIds))
|
||||
.GroupBy(x => x.PriceId)
|
||||
.ToDictionary(x => x.Key, x => x.OrderBy(item => item.SerialNumber).ToList());
|
||||
var detailMap = (await ServiceChannelRepository.GetPriceDetailsAsync(priceIds))
|
||||
var detailMap = includeDetails
|
||||
? (await ServiceChannelRepository.GetPriceDetailsAsync(priceIds))
|
||||
.GroupBy(x => x.PriceId)
|
||||
.ToDictionary(x => x.Key, x => x.OrderBy(item => item.Id).ToList());
|
||||
.ToDictionary(x => x.Key, x => x.OrderBy(item => item.Id).ToList())
|
||||
: new Dictionary<int, List<ServiceChannelPriceDetail>>();
|
||||
|
||||
return prices.Select(price => new ServiceChannelPriceListOutput
|
||||
{
|
||||
@ -170,12 +175,42 @@ public partial class ServiceChannelService
|
||||
Currency = price.Currency,
|
||||
ChargingCondition = price.ChargingCondition,
|
||||
Factors = factorMap.TryGetValue(price.Id, out var factors) ? factors.Select(MapPriceFactorOutput).ToList() : [],
|
||||
Details = detailMap.TryGetValue(price.Id, out var details) ? details.Select(MapPriceDetailOutput).ToList() : [],
|
||||
Details = includeDetails && detailMap.TryGetValue(price.Id, out var details)
|
||||
? details.Select(MapPriceDetailOutput).ToList()
|
||||
: [],
|
||||
CreateTime = price.CreateTime,
|
||||
UpdateTime = OmsDocHelper.NullIfDefault(price.UpdateTime)
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单条买价项(含因子+明细),供编辑弹窗按需加载。
|
||||
/// </summary>
|
||||
private async Task<ServiceChannelPriceListOutput> GetPriceOutputByIdAsync(int priceId)
|
||||
{
|
||||
var price = await GetPriceOrThrowAsync(priceId);
|
||||
var priceIds = new[] { price.Id };
|
||||
var factors = await ServiceChannelRepository.GetPriceFactorsAsync(priceIds);
|
||||
var details = await ServiceChannelRepository.GetPriceDetailsAsync(priceIds);
|
||||
|
||||
return new ServiceChannelPriceListOutput
|
||||
{
|
||||
Id = price.Id,
|
||||
ServiceChannelId = price.ServiceChannelId,
|
||||
SerialNumber = price.SerialNumber,
|
||||
Status = (byte)price.Status,
|
||||
PriceName = price.PriceName,
|
||||
CostItem = price.CostItem,
|
||||
CostUnit = price.CostUnit,
|
||||
Currency = price.Currency,
|
||||
ChargingCondition = price.ChargingCondition,
|
||||
Factors = factors.OrderBy(item => item.SerialNumber).Select(MapPriceFactorOutput).ToList(),
|
||||
Details = details.OrderBy(item => item.Id).Select(MapPriceDetailOutput).ToList(),
|
||||
CreateTime = price.CreateTime,
|
||||
UpdateTime = OmsDocHelper.NullIfDefault(price.UpdateTime)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定类型的发布记录。
|
||||
/// </summary>
|
||||
|
||||
@ -215,17 +215,29 @@ public partial class ServiceChannelService : ApplicationService
|
||||
/// 查询服务渠道价格项列表。
|
||||
/// </summary>
|
||||
/// <param name="serviceChannelId">入参:serviceChannelId。</param>
|
||||
/// <param name="includeDetails">是否返回价格明细矩阵;列表页建议 false。</param>
|
||||
/// <returns>服务渠道价格项列表结果。</returns>
|
||||
[HttpGet("/channel/service-channel/price/list")]
|
||||
public async Task<OmsItemsResult<ServiceChannelPriceListOutput>> GetPriceListAsync([FromQuery] int serviceChannelId)
|
||||
public async Task<OmsItemsResult<ServiceChannelPriceListOutput>> GetPriceListAsync(
|
||||
[FromQuery] int serviceChannelId,
|
||||
[FromQuery] bool includeDetails = true)
|
||||
{
|
||||
await GetEntityOrThrowAsync(serviceChannelId);
|
||||
return new OmsItemsResult<ServiceChannelPriceListOutput>
|
||||
{
|
||||
Items = await GetPriceOutputsAsync(serviceChannelId)
|
||||
Items = await GetPriceOutputsAsync(serviceChannelId, includeDetails)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取单条服务渠道价格项(含计费因子与价格明细)。
|
||||
/// </summary>
|
||||
[HttpGet("/channel/service-channel/price/get")]
|
||||
public async Task<ServiceChannelPriceListOutput> GetPriceAsync([FromQuery] int id)
|
||||
{
|
||||
return await GetPriceOutputByIdAsync(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增服务渠道价格项。
|
||||
/// </summary>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user