diff --git a/src/Oms.Application/Dtos/Channels/SalesProductPublishListInput.cs b/src/Oms.Application/Dtos/Channels/SalesProductPublishListInput.cs
index a13648b..f50dc74 100644
--- a/src/Oms.Application/Dtos/Channels/SalesProductPublishListInput.cs
+++ b/src/Oms.Application/Dtos/Channels/SalesProductPublishListInput.cs
@@ -19,4 +19,9 @@ public class SalesProductPublishListInput
/// 每页条数。
///
public int PageSize { get; set; }
+
+ ///
+ /// 是否返回发布快照正文。版本头只展示版本号和时间时传 false,避免传输并反序列化整份价格矩阵。
+ ///
+ public bool IncludeContent { get; set; } = true;
}
diff --git a/src/Oms.Application/Dtos/Channels/ServiceChannelOptionOutput.cs b/src/Oms.Application/Dtos/Channels/ServiceChannelOptionOutput.cs
new file mode 100644
index 0000000..1bb6205
--- /dev/null
+++ b/src/Oms.Application/Dtos/Channels/ServiceChannelOptionOutput.cs
@@ -0,0 +1,22 @@
+namespace Oms.Application.Dtos.Channels;
+
+///
+/// 服务渠道下拉项。只含展示所需字段,不分页。
+///
+public class ServiceChannelOptionOutput
+{
+ ///
+ /// 主键。
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// 分组名称。
+ ///
+ public string? GroupName { get; set; }
+
+ ///
+ /// 渠道名称。
+ ///
+ public string ChannelName { get; set; } = string.Empty;
+}
diff --git a/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs b/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs
index 7e2de52..ff29681 100644
--- a/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs
+++ b/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs
@@ -213,32 +213,65 @@ public partial class SalesProductService
private async Task> GetPublishListAsync(SalesProductPublishListInput input, string operatorType)
{
await GetProductOrThrowAsync(input.SalesProductId);
+ // 版本列表不传正文时一次返回全部版本头,页面没有分页。
+ if (!input.IncludeContent)
+ {
+ var headers = await SalesProductRepository.GetAllPublishRecordHeadersAsync(input.SalesProductId, operatorType);
+ return new OmsPageResult
+ {
+ Items = headers.Select(entity => MapPublishRecordOutput(entity, includeContent: false)).ToList(),
+ Total = headers.Count
+ };
+ }
+
var pageIndex = OmsDocHelper.NormalizePage(input.Page);
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
var entities = await SalesProductRepository.GetPublishRecordsAsync(input.SalesProductId, operatorType, pageIndex, pageSize);
var total = await SalesProductRepository.CountPublishRecordsAsync(input.SalesProductId, operatorType);
return new OmsPageResult
{
- Items = entities.Select(entity => new SalesProductPublishRecordOutput
- {
- 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(),
+ Items = entities.Select(entity => MapPublishRecordOutput(entity, includeContent: true)).ToList(),
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
+ };
+ }
+
+ ///
+ /// 单条发布记录(含快照正文),供版本详情按需加载。
+ ///
+ private async Task GetPublishRecordCoreAsync(int id)
+ {
+ var entity = await SalesProductRepository.GetPublishRecordByIdAsync(id);
+ if (entity == null)
+ {
+ throw new Fake.Application.BusinessException("发布记录不存在");
+ }
+
+ return MapPublishRecordOutput(entity, includeContent: true);
+ }
+
///
/// 组装规则发布快照(不落库),含黑名单/偏远/计重/进位明细。
///
diff --git a/src/Oms.Application/Services/Channels/SalesProductService.cs b/src/Oms.Application/Services/Channels/SalesProductService.cs
index 5647829..e8e7fd1 100644
--- a/src/Oms.Application/Services/Channels/SalesProductService.cs
+++ b/src/Oms.Application/Services/Channels/SalesProductService.cs
@@ -386,6 +386,15 @@ public partial class SalesProductService : ApplicationService
return GetPublishListAsync(input, RulesOperatorType);
}
+ ///
+ /// 查询单条发布记录,含快照正文。
+ ///
+ [HttpGet("/channel/sales-product/publish/get")]
+ public Task GetPublishRecordAsync([FromQuery] int id)
+ {
+ return GetPublishRecordCoreAsync(id);
+ }
+
///
/// 预览即将发布的快照 JSON(不落库),用于核对黑名单/计重等是否已固化进 Content。
///
diff --git a/src/Oms.Application/Services/Channels/ServiceChannelService.cs b/src/Oms.Application/Services/Channels/ServiceChannelService.cs
index fdad653..a3b535d 100644
--- a/src/Oms.Application/Services/Channels/ServiceChannelService.cs
+++ b/src/Oms.Application/Services/Channels/ServiceChannelService.cs
@@ -25,6 +25,22 @@ public partial class ServiceChannelService : ApplicationService
private OmsRbacUserDisplayNameResolver UserDisplayNameResolver =>
LazyServiceProvider.GetRequiredService();
+ ///
+ /// 服务渠道下拉。返回全部渠道的名称,不分页。
+ ///
+ [HttpGet("/channel/service-channel/options")]
+ public async Task> 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();
+ }
+
///
/// 查询服务渠道列表。
///
diff --git a/src/Oms.Domain/ChannelsAggregate/Repositories/ISalesProductRepository.cs b/src/Oms.Domain/ChannelsAggregate/Repositories/ISalesProductRepository.cs
index 5ba942a..e72dc7f 100644
--- a/src/Oms.Domain/ChannelsAggregate/Repositories/ISalesProductRepository.cs
+++ b/src/Oms.Domain/ChannelsAggregate/Repositories/ISalesProductRepository.cs
@@ -50,6 +50,16 @@ public interface ISalesProductRepository : IRepository
Task> GetPublishRecordsAsync(int salesProductId, string operatorType, int pageIndex, int pageSize, CancellationToken cancellationToken = default);
+ ///
+ /// 发布记录头(不含 Content / AI 报告),供版本号展示。
+ ///
+ Task> GetPublishRecordHeadersAsync(int salesProductId, string operatorType, int pageIndex, int pageSize, CancellationToken cancellationToken = default);
+
+ ///
+ /// 某产品某类发布记录的全部版本头,不含快照正文。
+ ///
+ Task> GetAllPublishRecordHeadersAsync(int salesProductId, string operatorType, CancellationToken cancellationToken = default);
+
Task CountPublishRecordsAsync(int salesProductId, string operatorType, CancellationToken cancellationToken = default);
Task InsertPublishRecordAsync(SalesProductPublishRecord record, CancellationToken cancellationToken = default);
diff --git a/src/Oms.Domain/ChannelsAggregate/Repositories/IServiceChannelRepository.cs b/src/Oms.Domain/ChannelsAggregate/Repositories/IServiceChannelRepository.cs
index bb090e5..15fb005 100644
--- a/src/Oms.Domain/ChannelsAggregate/Repositories/IServiceChannelRepository.cs
+++ b/src/Oms.Domain/ChannelsAggregate/Repositories/IServiceChannelRepository.cs
@@ -15,6 +15,11 @@ public interface IServiceChannelRepository : IRepository
Task> GetGroupsAsync(CancellationToken cancellationToken = default);
+ ///
+ /// 下拉选项:仅主键、分组、渠道名,不分页。
+ ///
+ Task> GetOptionRowsAsync(CancellationToken cancellationToken = default);
+
Task> GetPricesAsync(int serviceChannelId, CancellationToken cancellationToken = default);
Task GetPriceByIdAsync(int id, CancellationToken cancellationToken = default);
diff --git a/src/Oms.SqlSugarCore/Channels/SalesProductRepository.cs b/src/Oms.SqlSugarCore/Channels/SalesProductRepository.cs
index fdc3af9..6fcf92a 100644
--- a/src/Oms.SqlSugarCore/Channels/SalesProductRepository.cs
+++ b/src/Oms.SqlSugarCore/Channels/SalesProductRepository.cs
@@ -186,6 +186,48 @@ public class SalesProductRepository : OmsSqlSugarRepository, ISale
.ToPageListAsync(pageIndex, pageSize, cancellationToken);
}
+ public async Task> GetPublishRecordHeadersAsync(int salesProductId, string operatorType, int pageIndex, int pageSize, CancellationToken cancellationToken = default)
+ {
+ var db = await GetDbContextAsync(cancellationToken);
+ return await db.Queryable()
+ .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> GetAllPublishRecordHeadersAsync(int salesProductId, string operatorType, CancellationToken cancellationToken = default)
+ {
+ var db = await GetDbContextAsync(cancellationToken);
+ return await db.Queryable()
+ .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 CountPublishRecordsAsync(int salesProductId, string operatorType, CancellationToken cancellationToken = default)
{
var db = await GetDbContextAsync(cancellationToken);
diff --git a/src/Oms.SqlSugarCore/Channels/ServiceChannelRepository.cs b/src/Oms.SqlSugarCore/Channels/ServiceChannelRepository.cs
index c0c6e49..f7f9c4a 100644
--- a/src/Oms.SqlSugarCore/Channels/ServiceChannelRepository.cs
+++ b/src/Oms.SqlSugarCore/Channels/ServiceChannelRepository.cs
@@ -35,6 +35,20 @@ public class ServiceChannelRepository : OmsSqlSugarRepository, I
return await db.Queryable().ToListAsync(cancellationToken);
}
+ public async Task> GetOptionRowsAsync(CancellationToken cancellationToken = default)
+ {
+ var db = await GetDbContextAsync(cancellationToken);
+ return await db.Queryable()
+ .OrderBy(x => x.Id)
+ .Select(x => new ServiceChannel
+ {
+ Id = x.Id,
+ GroupId = x.GroupId,
+ ChannelName = x.ChannelName
+ })
+ .ToListAsync(cancellationToken);
+ }
+
public async Task> GetPricesAsync(int serviceChannelId, CancellationToken cancellationToken = default)
{
var db = await GetDbContextAsync(cancellationToken);