新增打印模板绑定功能,支持业务与打印模板的映射配置。实现打印模板的增删改查操作,优化打印数据的生成逻辑,提升打印模板的灵活性和用户体验。同时,新增打印机查询接口,增强打印服务的可用性和实时性。

This commit is contained in:
geht
2026-05-13 15:49:51 +08:00
parent 210f3614ea
commit c3f8190537
32 changed files with 2323 additions and 229 deletions

View File

@@ -23,4 +23,10 @@ public interface IRawMaterialCardService
/// <param name="dryRun">为 true 时仅返回匹配数量、不真正删除(用于「重新拆码」弹窗预提示)</param>
/// <returns>匹配/删除的卡片数量;失败返回 -1</returns>
Task<int> DeleteBySplitDetailIdsAsync(IEnumerable<string> splitDetailIds, bool dryRun = false, CancellationToken ct = default);
/// <summary>
/// 按业务打印绑定生成模板 JSON + 映射后 printData供桌面端打印预览使用。
/// </summary>
/// <returns>(templateJson, printDataJson, errorMessage) 元组errorMessage 非 null 时表示失败</returns>
Task<(string templateJson, string printDataJson, string? errorMessage)> PrepareNativePrintAsync(string id, CancellationToken ct = default);
}

View File

@@ -317,6 +317,39 @@ public class RawMaterialCardService : IRawMaterialCardService, ISingletonDepende
}
}
public async Task<(string templateJson, string printDataJson, string? errorMessage)> PrepareNativePrintAsync(string id, CancellationToken ct = default)
{
if (!_networkMonitor.IsOnline)
return (string.Empty, "{}", "当前离线,无法获取打印数据");
try
{
var url = $"{BaseUrl}/xslmes/mesXslRawMaterialCard/anon/prepareNativePrint?id={Uri.EscapeDataString(id)}&tenantId={DefaultTenantId}";
using var client = CreateClient();
var resp = await client.GetAsync(url, ct).ConfigureAwait(false);
var json = await resp.Content.ReadAsStringAsync(ct).ConfigureAwait(false);
using var doc = JsonDocument.Parse(json);
var root = doc.RootElement;
if (!root.TryGetProperty("code", out var codeEl) || codeEl.GetInt32() != 200)
{
var msg = root.TryGetProperty("message", out var msgEl) ? msgEl.GetString() : "未知错误";
return (string.Empty, "{}", msg ?? "服务端返回错误");
}
var result = root.GetProperty("result");
var templateJson = result.TryGetProperty("templateJson", out var tjEl) ? tjEl.GetString() : null;
var printDataJson = result.TryGetProperty("printData", out var pdEl)
? pdEl.GetRawText()
: "{}";
if (string.IsNullOrWhiteSpace(templateJson))
return (string.Empty, "{}", "服务端未返回模板 JSON请先在「业务打印绑定」中配置原材料卡片");
return (templateJson!, printDataJson, null);
}
catch (Exception ex)
{
_logger.Warning($"[原材料卡片] 准备打印数据失败 id={id}: {ex.Message}");
return (string.Empty, "{}", $"获取打印数据失败:{ex.Message}");
}
}
public async Task<bool> UpdatePriorityAsync(string id, string priorityPickup, CancellationToken ct = default)
{
if (_networkMonitor.IsOnline)

View File

@@ -5,11 +5,12 @@ using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows;
using YY.Admin.Core;
using YY.Admin.Core.Entity;
using YY.Admin.Core.Events;
using YY.Admin.Core.Helper;
using YY.Admin.Core.Entity;
using YY.Admin.Core.Services;
using YY.Admin.Services.Service;
using YY.Admin.Views.Print;
using YY.Admin.Views.RawMaterialCard;
namespace YY.Admin.ViewModels.RawMaterialCard;
@@ -18,6 +19,7 @@ public class RawMaterialCardListViewModel : BaseViewModel
{
private readonly IRawMaterialCardService _cardService;
private readonly IJeecgDictSyncService _dictSyncService;
private readonly IPrintDotService _printDotService;
private SubscriptionToken? _changedToken;
private SubscriptionToken? _syncConflictToken;
@@ -60,6 +62,7 @@ public class RawMaterialCardListViewModel : BaseViewModel
public DelegateCommand AddCommand { get; }
public DelegateCommand<MesXslRawMaterialCard> EditCommand { get; }
public DelegateCommand<MesXslRawMaterialCard> DeleteCommand { get; }
public DelegateCommand<MesXslRawMaterialCard> PrintCommand { get; }
public DelegateCommand<MesXslRawMaterialCard> TogglePriorityCommand { get; }
public DelegateCommand PrevPageCommand { get; }
public DelegateCommand NextPageCommand { get; }
@@ -67,11 +70,13 @@ public class RawMaterialCardListViewModel : BaseViewModel
public RawMaterialCardListViewModel(
IRawMaterialCardService cardService,
IJeecgDictSyncService dictSyncService,
IPrintDotService printDotService,
IContainerExtension container,
IRegionManager regionManager) : base(container, regionManager)
{
_cardService = cardService;
_dictSyncService = dictSyncService;
_printDotService = printDotService;
SearchCommand = new DelegateCommand(async () => { PageNo = 1; await LoadAsync(); });
ResetCommand = new DelegateCommand(async () =>
@@ -83,6 +88,7 @@ public class RawMaterialCardListViewModel : BaseViewModel
AddCommand = new DelegateCommand(async () => await ShowAddDialogAsync());
EditCommand = new DelegateCommand<MesXslRawMaterialCard>(async c => await ShowEditDialogAsync(c));
DeleteCommand = new DelegateCommand<MesXslRawMaterialCard>(async c => await DeleteAsync(c));
PrintCommand = new DelegateCommand<MesXslRawMaterialCard>(async c => await ShowPrintPreviewAsync(c));
TogglePriorityCommand = new DelegateCommand<MesXslRawMaterialCard>(async c => await TogglePriorityAsync(c));
PrevPageCommand = new DelegateCommand(async () => { if (PageNo > 1) { PageNo--; await LoadAsync(); } });
NextPageCommand = new DelegateCommand(async () => { if ((long)PageNo * PageSize < Total) { PageNo++; await LoadAsync(); } });
@@ -255,6 +261,65 @@ public class RawMaterialCardListViewModel : BaseViewModel
}
}
private async Task ShowPrintPreviewAsync(MesXslRawMaterialCard card)
{
if (card?.Id == null) return;
try
{
IsLoading = true;
var (templateJson, printDataJson, errorMessage) = await _cardService.PrepareNativePrintAsync(card.Id);
if (errorMessage != null)
{
Growl.Error(errorMessage);
return;
}
// 构造一个最简的 PrintTemplate 对象用于传入 PrintPreviewWindow供显示标题 / 纸张信息)
var tpl = BuildPrintTemplateFromJson(templateJson);
var win = new PrintPreviewWindow(tpl, templateJson, _printDotService, null, printDataJson)
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
};
win.Show();
}
catch (Exception ex)
{
Growl.Error($"打开打印预览失败:{ex.Message}");
}
finally
{
IsLoading = false;
}
}
private static PrintTemplate BuildPrintTemplateFromJson(string templateJson)
{
try
{
var root = System.Text.Json.JsonDocument.Parse(templateJson).RootElement;
double w = 210, h = 297;
if (root.TryGetProperty("page", out var page))
{
if (page.TryGetProperty("width", out var wEl)) w = wEl.GetDouble();
if (page.TryGetProperty("height", out var hEl)) h = hEl.GetDouble();
}
return new PrintTemplate
{
TemplateName = "原材料卡片",
TemplateCode = "MES_RAW_MATERIAL_CARD",
PaperWidthMm = w,
PaperHeightMm = h,
PaperOrientation = w > h ? "横向" : "纵向",
};
}
catch
{
return new PrintTemplate { TemplateName = "原材料卡片", TemplateCode = "MES_RAW_MATERIAL_CARD" };
}
}
protected override void CleanUp()
{
base.CleanUp();

View File

@@ -23,7 +23,8 @@ public partial class PrintPreviewWindow : HandyControl.Controls.Window
}
public PrintPreviewWindow(PrintTemplate template, string? templateJson,
IPrintDotService? printDotService, string? selectedPrinterName)
IPrintDotService? printDotService, string? selectedPrinterName,
string? initialParamJson = null)
{
InitializeComponent();
_template = template;
@@ -36,7 +37,9 @@ public partial class PrintPreviewWindow : HandyControl.Controls.Window
$"尺寸:{template.PaperWidthMm ?? 210}×{template.PaperHeightMm ?? 297} mm " +
$"方向:{template.PaperOrientation ?? ""}";
TbParamJson.Text = BuildMockParamJson(_templateJson);
TbParamJson.Text = !string.IsNullOrWhiteSpace(initialParamJson)
? initialParamJson!
: BuildMockParamJson(_templateJson);
// 没有 PrintDot 服务时禁用打印相关按钮
if (_printDotService == null)

View File

@@ -143,7 +143,7 @@
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="操作" Width="160">
<DataGridTemplateColumn Header="操作" Width="230">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<hc:UniformSpacingPanel Spacing="6" HorizontalAlignment="Center">
@@ -152,6 +152,11 @@
FontSize="12" Height="26" Padding="8,0"
Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
CommandParameter="{Binding}"/>
<Button Content="打印"
Style="{StaticResource ButtonInfo}"
FontSize="12" Height="26" Padding="8,0"
Command="{Binding DataContext.PrintCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
CommandParameter="{Binding}"/>
<Button Content="删除"
Style="{StaticResource ButtonDanger}"
FontSize="12" Height="26" Padding="8,0"