using Fake.Application;
using Microsoft.AspNetCore.Mvc;
using Oms.Application.Dtos.Channels;
using Oms.Application.Dtos.Shared;
using Oms.Application.Labeling;
using Oms.Application.Shared;
using Oms.Domain.ChannelsAggregate.Consts;
using Oms.Domain.ChannelsAggregate.Entities;
using Oms.Domain.ChannelsAggregate.Repositories;
namespace Oms.Application.Services.Channels;
///
/// 面单模板 API 服务。
///
[ApiExplorerSettings(GroupName = "OMS-Channel")]
public class LabelTemplateService : ApplicationService
{
private ILabelTemplateRepository LabelTemplateRepository => LazyServiceProvider.GetRequiredService();
private LabelPdfGenerationService LabelPdfGenerationService =>
LazyServiceProvider.GetRequiredService();
///
/// 标签模板列表(不含 JSON,供浏览/下拉)。
///
[HttpGet("/channel/label-template/list")]
public async Task> GetListAsync(
[FromQuery] string? keyword = null,
[FromQuery] string? templateType = null)
{
var keywordValue = keyword?.Trim();
var typeValue = templateType?.Trim();
var hasKeyword = !string.IsNullOrEmpty(keywordValue);
var hasType = !string.IsNullOrEmpty(typeValue);
var entities = await LabelTemplateRepository.GetListAsync(x =>
(!hasKeyword || x.Name.Contains(keywordValue!)) &&
(!hasType || x.TemplateType == typeValue));
var items = entities
.OrderByDescending(x => x.UpdateTime)
.ThenByDescending(x => x.Id)
.Select(x => new LabelTemplateListItemOutput
{
Id = x.Id,
Name = x.Name,
TemplateType = x.TemplateType,
CreateTime = x.CreateTime,
UpdateTime = OmsDocHelper.NullIfDefault(x.UpdateTime)
})
.ToList();
return new OmsItemsResult { Items = items };
}
///
/// 标签模板详情(含 TemplateJson,编辑用)。
///
[HttpGet("/channel/label-template/{id:int}")]
public async Task GetAsync(int id)
{
var entity = await GetEntityOrThrowAsync(id);
return MapOutput(entity);
}
///
/// 设计器字段字典(可拖字段分组)。
///
[HttpGet("/channel/label-template/field-dictionary")]
public Task> GetFieldDictionaryAsync()
{
return Task.FromResult(new OmsItemsResult
{
Items = LabelFieldDictionary.GetGroups().ToList()
});
}
///
/// 预览 PDF(同一套 ILabelPdfRenderer)。
///
[HttpPost("/channel/label-template/preview-pdf")]
public async Task PreviewPdfAsync([FromBody] LabelTemplatePreviewInput input)
{
string? templateJson = null;
string? templateType = null;
if (input.TemplateId is > 0)
{
var entity = await GetEntityOrThrowAsync(input.TemplateId.Value);
templateJson = entity.TemplateJson;
templateType = entity.TemplateType;
}
else
{
templateJson = OmsDocHelper.SerializeJson(input.TemplateJson);
}
if (string.IsNullOrWhiteSpace(templateJson))
{
throw new BusinessException("模板 JSON 为空");
}
IReadOnlyDictionary? printData = null;
if (input.PrintData is { Count: > 0 })
{
printData = input.PrintData.ToDictionary(
x => x.Key,
x => x.Value,
StringComparer.OrdinalIgnoreCase);
}
else if (string.Equals(templateType, LabelTemplateTypeCodes.Box, StringComparison.OrdinalIgnoreCase))
{
printData = InboundBoxLabelPrintDataBuilder.BuildMock();
}
else if (string.Equals(templateType, LabelTemplateTypeCodes.Sku, StringComparison.OrdinalIgnoreCase))
{
printData = SkuLabelPrintDataBuilder.BuildMock();
}
var bytes = await LabelPdfGenerationService.PreviewAsync(templateJson, printData);
return new FileContentResult(bytes, "application/pdf")
{
FileDownloadName = $"label-preview-{DateTime.Now:yyyyMMddHHmmss}.pdf"
};
}
///
/// 保存标签模板。
///
[HttpPost("/channel/label-template/save")]
public async Task SaveAsync(LabelTemplateSaveInput input)
{
LabelTemplate entity;
if (input.Id > 0)
{
entity = await GetEntityOrThrowAsync(input.Id);
await ValidateUniqueNameAsync(input.Name, input.TemplateType, entity.Id);
entity.Name = input.Name;
entity.TemplateType = input.TemplateType;
entity.TemplateJson = OmsDocHelper.SerializeJson(input.TemplateJson);
await LabelTemplateRepository.UpdateAsync(entity);
}
else
{
await ValidateUniqueNameAsync(input.Name, input.TemplateType, null);
entity = new LabelTemplate
{
Name = input.Name,
TemplateType = input.TemplateType,
TemplateJson = OmsDocHelper.SerializeJson(input.TemplateJson)
};
entity = await LabelTemplateRepository.InsertAsync(entity);
}
return MapOutput(entity);
}
///
/// 删除标签模板。
///
[HttpPost("/channel/label-template/delete")]
public async Task DeleteAsync(IdInput input)
{
var entity = await GetEntityOrThrowAsync(input.Id);
await LabelTemplateRepository.DeleteAsync(entity);
}
private async Task ValidateUniqueNameAsync(string name, string? templateType, int? id)
{
var existed = await LabelTemplateRepository.GetByNameAndTypeAsync(name, templateType);
if (existed != null && existed.Id != id)
{
throw new BusinessException("标签模板名称已存在");
}
}
private async Task GetEntityOrThrowAsync(int id)
{
var entity = await LabelTemplateRepository.FirstOrDefaultAsync(x => x.Id == id);
if (entity == null)
{
throw new BusinessException("标签模板不存在");
}
return entity;
}
private static LabelTemplateSaveOutput MapOutput(LabelTemplate entity)
{
return new LabelTemplateSaveOutput
{
Id = entity.Id,
Name = entity.Name,
TemplateType = entity.TemplateType,
TemplateJson = OmsDocHelper.DeserializeJsonObject(entity.TemplateJson),
CreateTime = entity.CreateTime,
UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime)
};
}
}