feat: 销售产品页签按需加载版本头和渠道下拉,避免分页拉取整份快照
All checks were successful
Build and Deploy / deploy (push) Successful in 1m1s
All checks were successful
Build and Deploy / deploy (push) Successful in 1m1s
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
a164d8c837
commit
b38499963d
@ -19,4 +19,9 @@ public class SalesProductPublishListInput
|
|||||||
/// 每页条数。
|
/// 每页条数。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int PageSize { get; set; }
|
public int PageSize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否返回发布快照正文。版本头只展示版本号和时间时传 false,避免传输并反序列化整份价格矩阵。
|
||||||
|
/// </summary>
|
||||||
|
public bool IncludeContent { get; set; } = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
namespace Oms.Application.Dtos.Channels;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务渠道下拉项。只含展示所需字段,不分页。
|
||||||
|
/// </summary>
|
||||||
|
public class ServiceChannelOptionOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 主键。
|
||||||
|
/// </summary>
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 分组名称。
|
||||||
|
/// </summary>
|
||||||
|
public string? GroupName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 渠道名称。
|
||||||
|
/// </summary>
|
||||||
|
public string ChannelName { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
@ -213,32 +213,65 @@ public partial class SalesProductService
|
|||||||
private async Task<OmsPageResult<SalesProductPublishRecordOutput>> GetPublishListAsync(SalesProductPublishListInput input, string operatorType)
|
private async Task<OmsPageResult<SalesProductPublishRecordOutput>> GetPublishListAsync(SalesProductPublishListInput input, string operatorType)
|
||||||
{
|
{
|
||||||
await GetProductOrThrowAsync(input.SalesProductId);
|
await GetProductOrThrowAsync(input.SalesProductId);
|
||||||
|
// 版本列表不传正文时一次返回全部版本头,页面没有分页。
|
||||||
|
if (!input.IncludeContent)
|
||||||
|
{
|
||||||
|
var headers = await SalesProductRepository.GetAllPublishRecordHeadersAsync(input.SalesProductId, operatorType);
|
||||||
|
return new OmsPageResult<SalesProductPublishRecordOutput>
|
||||||
|
{
|
||||||
|
Items = headers.Select(entity => MapPublishRecordOutput(entity, includeContent: false)).ToList(),
|
||||||
|
Total = headers.Count
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var pageIndex = OmsDocHelper.NormalizePage(input.Page);
|
var pageIndex = OmsDocHelper.NormalizePage(input.Page);
|
||||||
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
|
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
|
||||||
var entities = await SalesProductRepository.GetPublishRecordsAsync(input.SalesProductId, operatorType, pageIndex, pageSize);
|
var entities = await SalesProductRepository.GetPublishRecordsAsync(input.SalesProductId, operatorType, pageIndex, pageSize);
|
||||||
var total = await SalesProductRepository.CountPublishRecordsAsync(input.SalesProductId, operatorType);
|
var total = await SalesProductRepository.CountPublishRecordsAsync(input.SalesProductId, operatorType);
|
||||||
return new OmsPageResult<SalesProductPublishRecordOutput>
|
return new OmsPageResult<SalesProductPublishRecordOutput>
|
||||||
{
|
{
|
||||||
Items = entities.Select(entity => new SalesProductPublishRecordOutput
|
Items = entities.Select(entity => MapPublishRecordOutput(entity, includeContent: true)).ToList(),
|
||||||
{
|
|
||||||
Id = entity.Id,
|
|
||||||
SalesProductId = entity.SalesProductId,
|
|
||||||
Version = entity.Version,
|
|
||||||
OperatorType = entity.OperatorType,
|
|
||||||
Status = EnumDisplayNames.Of(entity.Status),
|
|
||||||
PublishUser = entity.PublishUser,
|
|
||||||
PublishTime = entity.PublishTime,
|
|
||||||
Description = entity.Description,
|
|
||||||
AiAnalysisReport = entity.AiAnalysisReport,
|
|
||||||
Content = operatorType == PriceOperatorType
|
|
||||||
? OmsDocHelper.ParseSalesProductPricePublishContentForApi(entity.Content)
|
|
||||||
: OmsDocHelper.ToSnapshotApiContent(OmsDocHelper.DeserializeRulesSnapshot(entity.Content)),
|
|
||||||
CreateTime = entity.CreateTime
|
|
||||||
}).ToList(),
|
|
||||||
Total = total
|
Total = total
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SalesProductPublishRecordOutput MapPublishRecordOutput(SalesProductPublishRecord entity, bool includeContent)
|
||||||
|
{
|
||||||
|
var operatorType = entity.OperatorType;
|
||||||
|
return new SalesProductPublishRecordOutput
|
||||||
|
{
|
||||||
|
Id = entity.Id,
|
||||||
|
SalesProductId = entity.SalesProductId,
|
||||||
|
Version = entity.Version,
|
||||||
|
OperatorType = operatorType,
|
||||||
|
Status = EnumDisplayNames.Of(entity.Status),
|
||||||
|
PublishUser = entity.PublishUser,
|
||||||
|
PublishTime = entity.PublishTime,
|
||||||
|
Description = entity.Description,
|
||||||
|
AiAnalysisReport = includeContent ? entity.AiAnalysisReport : null,
|
||||||
|
Content = !includeContent
|
||||||
|
? null
|
||||||
|
: string.Equals(operatorType, PriceOperatorType, StringComparison.OrdinalIgnoreCase)
|
||||||
|
? OmsDocHelper.ParseSalesProductPricePublishContentForApi(entity.Content)
|
||||||
|
: OmsDocHelper.ToSnapshotApiContent(OmsDocHelper.DeserializeRulesSnapshot(entity.Content)),
|
||||||
|
CreateTime = entity.CreateTime
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单条发布记录(含快照正文),供版本详情按需加载。
|
||||||
|
/// </summary>
|
||||||
|
private async Task<SalesProductPublishRecordOutput> GetPublishRecordCoreAsync(int id)
|
||||||
|
{
|
||||||
|
var entity = await SalesProductRepository.GetPublishRecordByIdAsync(id);
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
throw new Fake.Application.BusinessException("发布记录不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
return MapPublishRecordOutput(entity, includeContent: true);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 组装规则发布快照(不落库),含黑名单/偏远/计重/进位明细。
|
/// 组装规则发布快照(不落库),含黑名单/偏远/计重/进位明细。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -386,6 +386,15 @@ public partial class SalesProductService : ApplicationService
|
|||||||
return GetPublishListAsync(input, RulesOperatorType);
|
return GetPublishListAsync(input, RulesOperatorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询单条发布记录,含快照正文。
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("/channel/sales-product/publish/get")]
|
||||||
|
public Task<SalesProductPublishRecordOutput> GetPublishRecordAsync([FromQuery] int id)
|
||||||
|
{
|
||||||
|
return GetPublishRecordCoreAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 预览即将发布的快照 JSON(不落库),用于核对黑名单/计重等是否已固化进 Content。
|
/// 预览即将发布的快照 JSON(不落库),用于核对黑名单/计重等是否已固化进 Content。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -25,6 +25,22 @@ public partial class ServiceChannelService : ApplicationService
|
|||||||
private OmsRbacUserDisplayNameResolver UserDisplayNameResolver =>
|
private OmsRbacUserDisplayNameResolver UserDisplayNameResolver =>
|
||||||
LazyServiceProvider.GetRequiredService<OmsRbacUserDisplayNameResolver>();
|
LazyServiceProvider.GetRequiredService<OmsRbacUserDisplayNameResolver>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务渠道下拉。返回全部渠道的名称,不分页。
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("/channel/service-channel/options")]
|
||||||
|
public async Task<List<ServiceChannelOptionOutput>> GetOptionsAsync()
|
||||||
|
{
|
||||||
|
var channels = await ServiceChannelRepository.GetOptionRowsAsync();
|
||||||
|
var groupMap = await GetGroupMapAsync();
|
||||||
|
return channels.Select(channel => new ServiceChannelOptionOutput
|
||||||
|
{
|
||||||
|
Id = channel.Id,
|
||||||
|
ChannelName = channel.ChannelName,
|
||||||
|
GroupName = channel.GroupId.HasValue && groupMap.TryGetValue(channel.GroupId.Value, out var name) ? name : null
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询服务渠道列表。
|
/// 查询服务渠道列表。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -50,6 +50,16 @@ public interface ISalesProductRepository : IRepository<SalesProduct>
|
|||||||
|
|
||||||
Task<List<SalesProductPublishRecord>> GetPublishRecordsAsync(int salesProductId, string operatorType, int pageIndex, int pageSize, CancellationToken cancellationToken = default);
|
Task<List<SalesProductPublishRecord>> GetPublishRecordsAsync(int salesProductId, string operatorType, int pageIndex, int pageSize, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发布记录头(不含 Content / AI 报告),供版本号展示。
|
||||||
|
/// </summary>
|
||||||
|
Task<List<SalesProductPublishRecord>> GetPublishRecordHeadersAsync(int salesProductId, string operatorType, int pageIndex, int pageSize, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 某产品某类发布记录的全部版本头,不含快照正文。
|
||||||
|
/// </summary>
|
||||||
|
Task<List<SalesProductPublishRecord>> GetAllPublishRecordHeadersAsync(int salesProductId, string operatorType, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
Task<int> CountPublishRecordsAsync(int salesProductId, string operatorType, CancellationToken cancellationToken = default);
|
Task<int> CountPublishRecordsAsync(int salesProductId, string operatorType, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
Task<SalesProductPublishRecord> InsertPublishRecordAsync(SalesProductPublishRecord record, CancellationToken cancellationToken = default);
|
Task<SalesProductPublishRecord> InsertPublishRecordAsync(SalesProductPublishRecord record, CancellationToken cancellationToken = default);
|
||||||
|
|||||||
@ -15,6 +15,11 @@ public interface IServiceChannelRepository : IRepository<ServiceChannel>
|
|||||||
|
|
||||||
Task<List<ServiceChannelGroup>> GetGroupsAsync(CancellationToken cancellationToken = default);
|
Task<List<ServiceChannelGroup>> GetGroupsAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下拉选项:仅主键、分组、渠道名,不分页。
|
||||||
|
/// </summary>
|
||||||
|
Task<List<ServiceChannel>> GetOptionRowsAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
Task<List<ServiceChannelPrice>> GetPricesAsync(int serviceChannelId, CancellationToken cancellationToken = default);
|
Task<List<ServiceChannelPrice>> GetPricesAsync(int serviceChannelId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
Task<ServiceChannelPrice?> GetPriceByIdAsync(int id, CancellationToken cancellationToken = default);
|
Task<ServiceChannelPrice?> GetPriceByIdAsync(int id, CancellationToken cancellationToken = default);
|
||||||
|
|||||||
@ -186,6 +186,48 @@ public class SalesProductRepository : OmsSqlSugarRepository<SalesProduct>, ISale
|
|||||||
.ToPageListAsync(pageIndex, pageSize, cancellationToken);
|
.ToPageListAsync(pageIndex, pageSize, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<SalesProductPublishRecord>> GetPublishRecordHeadersAsync(int salesProductId, string operatorType, int pageIndex, int pageSize, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var db = await GetDbContextAsync(cancellationToken);
|
||||||
|
return await db.Queryable<SalesProductPublishRecord>()
|
||||||
|
.Where(x => x.SalesProductId == salesProductId && x.OperatorType == operatorType)
|
||||||
|
.OrderBy(x => x.PublishTime, SqlSugar.OrderByType.Desc)
|
||||||
|
.Select(x => new SalesProductPublishRecord
|
||||||
|
{
|
||||||
|
Id = x.Id,
|
||||||
|
SalesProductId = x.SalesProductId,
|
||||||
|
Version = x.Version,
|
||||||
|
OperatorType = x.OperatorType,
|
||||||
|
Status = x.Status,
|
||||||
|
PublishUser = x.PublishUser,
|
||||||
|
PublishTime = x.PublishTime,
|
||||||
|
Description = x.Description,
|
||||||
|
CreateTime = x.CreateTime
|
||||||
|
})
|
||||||
|
.ToPageListAsync(pageIndex, pageSize, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<SalesProductPublishRecord>> GetAllPublishRecordHeadersAsync(int salesProductId, string operatorType, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var db = await GetDbContextAsync(cancellationToken);
|
||||||
|
return await db.Queryable<SalesProductPublishRecord>()
|
||||||
|
.Where(x => x.SalesProductId == salesProductId && x.OperatorType == operatorType)
|
||||||
|
.OrderBy(x => x.PublishTime, SqlSugar.OrderByType.Desc)
|
||||||
|
.Select(x => new SalesProductPublishRecord
|
||||||
|
{
|
||||||
|
Id = x.Id,
|
||||||
|
SalesProductId = x.SalesProductId,
|
||||||
|
Version = x.Version,
|
||||||
|
OperatorType = x.OperatorType,
|
||||||
|
Status = x.Status,
|
||||||
|
PublishUser = x.PublishUser,
|
||||||
|
PublishTime = x.PublishTime,
|
||||||
|
Description = x.Description,
|
||||||
|
CreateTime = x.CreateTime
|
||||||
|
})
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<int> CountPublishRecordsAsync(int salesProductId, string operatorType, CancellationToken cancellationToken = default)
|
public async Task<int> CountPublishRecordsAsync(int salesProductId, string operatorType, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var db = await GetDbContextAsync(cancellationToken);
|
var db = await GetDbContextAsync(cancellationToken);
|
||||||
|
|||||||
@ -35,6 +35,20 @@ public class ServiceChannelRepository : OmsSqlSugarRepository<ServiceChannel>, I
|
|||||||
return await db.Queryable<ServiceChannelGroup>().ToListAsync(cancellationToken);
|
return await db.Queryable<ServiceChannelGroup>().ToListAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<ServiceChannel>> GetOptionRowsAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var db = await GetDbContextAsync(cancellationToken);
|
||||||
|
return await db.Queryable<ServiceChannel>()
|
||||||
|
.OrderBy(x => x.Id)
|
||||||
|
.Select(x => new ServiceChannel
|
||||||
|
{
|
||||||
|
Id = x.Id,
|
||||||
|
GroupId = x.GroupId,
|
||||||
|
ChannelName = x.ChannelName
|
||||||
|
})
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<List<ServiceChannelPrice>> GetPricesAsync(int serviceChannelId, CancellationToken cancellationToken = default)
|
public async Task<List<ServiceChannelPrice>> GetPricesAsync(int serviceChannelId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var db = await GetDbContextAsync(cancellationToken);
|
var db = await GetDbContextAsync(cancellationToken);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user