新增打印模板管理功能,包含免密接口和实时通知机制,支持桌面端打印模板的查询和列表展示。更新相关控制器、服务和视图,优化用户体验并增强系统的实时数据同步能力。
This commit is contained in:
@@ -140,7 +140,18 @@ namespace YY.Admin.ViewModels.Control
|
||||
// 已实现页面:库区管理
|
||||
["WarehouseAreaListView"] = "WarehouseAreaListView",
|
||||
["/xslmes/mesXslWarehouseArea"] = "WarehouseAreaListView",
|
||||
["mesXslWarehouseArea"] = "WarehouseAreaListView"
|
||||
["mesXslWarehouseArea"] = "WarehouseAreaListView",
|
||||
|
||||
// 已实现页面:打印设置
|
||||
["PrintSettingsView"] = "PrintSettingsView",
|
||||
["/system/printSettings"] = "PrintSettingsView",
|
||||
["printSettings"] = "PrintSettingsView",
|
||||
|
||||
// 已实现页面:打印模板
|
||||
["PrintTemplateListView"] = "PrintTemplateListView",
|
||||
["/platform/print"] = "PrintTemplateListView",
|
||||
["print"] = "PrintTemplateListView",
|
||||
["printTemplate"] = "PrintTemplateListView"
|
||||
};
|
||||
|
||||
private MenuItem? _selectedMenuItem;
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows;
|
||||
using Prism.Commands;
|
||||
using YY.Admin.Core.Entity;
|
||||
using YY.Admin.Core.Services;
|
||||
using YY.Admin.Services.Service.Print;
|
||||
using YY.Admin.Core;
|
||||
|
||||
namespace YY.Admin.ViewModels.Print;
|
||||
|
||||
public class PrintSettingsViewModel : BaseViewModel
|
||||
{
|
||||
private readonly IPrintDotService _printDotService;
|
||||
private readonly IPrintTemplateService _printTemplateService;
|
||||
|
||||
// ── 连接设置 ──────────────────────────────────────────────────────────
|
||||
|
||||
private string _wsUrl = "ws://127.0.0.1:1122/ws";
|
||||
public string WsUrl
|
||||
{
|
||||
get => _wsUrl;
|
||||
set => SetProperty(ref _wsUrl, value);
|
||||
}
|
||||
|
||||
// ── 打印机列表 ──────────────────────────────────────────────────────────
|
||||
|
||||
public ObservableCollection<PrintDotPrinter> Printers { get; } = new();
|
||||
|
||||
private PrintDotPrinter? _selectedPrinter;
|
||||
public PrintDotPrinter? SelectedPrinter
|
||||
{
|
||||
get => _selectedPrinter;
|
||||
set => SetProperty(ref _selectedPrinter, value);
|
||||
}
|
||||
|
||||
// ── 模板列表 ────────────────────────────────────────────────────────────
|
||||
|
||||
public ObservableCollection<PrintTemplate> Templates { get; } = new();
|
||||
|
||||
// ── 状态 ────────────────────────────────────────────────────────────────
|
||||
|
||||
private bool _isBusy;
|
||||
public bool IsBusy
|
||||
{
|
||||
get => _isBusy;
|
||||
set => SetProperty(ref _isBusy, value);
|
||||
}
|
||||
|
||||
private string _statusMessage = string.Empty;
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => SetProperty(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
// ── 命令 ────────────────────────────────────────────────────────────────
|
||||
|
||||
public DelegateCommand TestConnectionCommand { get; }
|
||||
public DelegateCommand SaveCommand { get; }
|
||||
public DelegateCommand RefreshTemplatesCommand { get; }
|
||||
|
||||
public PrintSettingsViewModel(
|
||||
IPrintDotService printDotService,
|
||||
IPrintTemplateService printTemplateService,
|
||||
IContainerExtension container,
|
||||
IRegionManager regionManager) : base(container, regionManager)
|
||||
{
|
||||
_printDotService = printDotService;
|
||||
_printTemplateService = printTemplateService;
|
||||
|
||||
TestConnectionCommand = new DelegateCommand(async () => await TestConnectionAsync());
|
||||
SaveCommand = new DelegateCommand(SaveSettings);
|
||||
RefreshTemplatesCommand = new DelegateCommand(async () => await RefreshTemplatesAsync());
|
||||
|
||||
// 加载已保存的设置
|
||||
var saved = PrintDotSettings.Load();
|
||||
WsUrl = saved.WsUrl;
|
||||
if (!string.IsNullOrWhiteSpace(saved.SelectedPrinter))
|
||||
_selectedPrinter = new PrintDotPrinter(saved.SelectedPrinter, false);
|
||||
}
|
||||
|
||||
private async Task TestConnectionAsync()
|
||||
{
|
||||
IsBusy = true;
|
||||
StatusMessage = "正在连接...";
|
||||
Printers.Clear();
|
||||
try
|
||||
{
|
||||
// 临时用当前输入的 URL 测试
|
||||
PrintDotSettings.Current!.WsUrl = WsUrl;
|
||||
var list = await _printDotService.GetPrintersAsync();
|
||||
foreach (var p in list) Printers.Add(p);
|
||||
|
||||
// 还原保存的已选打印机
|
||||
var saved = PrintDotSettings.Load();
|
||||
var match = list.FirstOrDefault(p => p.Name == saved.SelectedPrinter);
|
||||
SelectedPrinter = match ?? (list.Count > 0 ? list[0] : null);
|
||||
|
||||
StatusMessage = $"连接成功,共 {list.Count} 台打印机";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusMessage = $"连接失败:{ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveSettings()
|
||||
{
|
||||
var settings = new PrintDotSettings
|
||||
{
|
||||
WsUrl = WsUrl.Trim(),
|
||||
SelectedPrinter = SelectedPrinter?.Name ?? string.Empty
|
||||
};
|
||||
settings.Save();
|
||||
StatusMessage = "设置已保存";
|
||||
MessageBox.Show("PrintDot 设置已保存", "保存成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
private async Task RefreshTemplatesAsync()
|
||||
{
|
||||
IsBusy = true;
|
||||
Templates.Clear();
|
||||
try
|
||||
{
|
||||
var list = await _printTemplateService.ListAsync();
|
||||
foreach (var t in list) Templates.Add(t);
|
||||
StatusMessage = $"已加载 {list.Count} 个打印模板";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusMessage = $"加载模板失败:{ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsBusy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using YY.Admin.Core;
|
||||
using YY.Admin.Core.Entity;
|
||||
using YY.Admin.Core.Events;
|
||||
using YY.Admin.Core.Services;
|
||||
using YY.Admin.Services.Service.Print;
|
||||
using YY.Admin.Views.Print;
|
||||
|
||||
namespace YY.Admin.ViewModels.Print;
|
||||
|
||||
public class PrintTemplateListViewModel : BaseViewModel
|
||||
{
|
||||
private readonly IPrintTemplateService _printTemplateService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private SubscriptionToken? _changeToken;
|
||||
|
||||
private List<PrintTemplate> _allTemplates = new();
|
||||
|
||||
public ObservableCollection<PrintTemplate> Templates { get; } = new();
|
||||
|
||||
private string _statusMessage = string.Empty;
|
||||
public string StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => SetProperty(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
private string? _filterCode;
|
||||
public string? FilterCode
|
||||
{
|
||||
get => _filterCode;
|
||||
set => SetProperty(ref _filterCode, value);
|
||||
}
|
||||
|
||||
private string? _filterName;
|
||||
public string? FilterName
|
||||
{
|
||||
get => _filterName;
|
||||
set => SetProperty(ref _filterName, value);
|
||||
}
|
||||
|
||||
private string? _filterCategory;
|
||||
public string? FilterCategory
|
||||
{
|
||||
get => _filterCategory;
|
||||
set => SetProperty(ref _filterCategory, value);
|
||||
}
|
||||
|
||||
public DelegateCommand SearchCommand { get; }
|
||||
public DelegateCommand ResetCommand { get; }
|
||||
public DelegateCommand<PrintTemplate> PreviewCommand { get; }
|
||||
|
||||
public PrintTemplateListViewModel(
|
||||
IPrintTemplateService printTemplateService,
|
||||
IEventAggregator eventAggregator,
|
||||
IContainerExtension container,
|
||||
IRegionManager regionManager) : base(container, regionManager)
|
||||
{
|
||||
_printTemplateService = printTemplateService;
|
||||
_eventAggregator = eventAggregator;
|
||||
|
||||
SearchCommand = new DelegateCommand(ApplyFilter);
|
||||
PreviewCommand = new DelegateCommand<PrintTemplate>(ShowPreview);
|
||||
ResetCommand = new DelegateCommand(() =>
|
||||
{
|
||||
FilterCode = null;
|
||||
FilterName = null;
|
||||
FilterCategory = null;
|
||||
ApplyFilter();
|
||||
});
|
||||
|
||||
_changeToken = _eventAggregator
|
||||
.GetEvent<PrintTemplateChangedEvent>()
|
||||
.Subscribe(_ => { RefreshSilentlyAsync().ConfigureAwait(false); }, ThreadOption.UIThread);
|
||||
|
||||
// 先用缓存立即填充,再后台静默刷新
|
||||
ShowCached();
|
||||
_ = RefreshSilentlyAsync();
|
||||
}
|
||||
|
||||
private void ShowCached()
|
||||
{
|
||||
var cached = _printTemplateService.GetCached();
|
||||
if (cached.Count == 0) return;
|
||||
_allTemplates = cached.ToList();
|
||||
ApplyFilter();
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
private async Task RefreshSilentlyAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var list = await _printTemplateService.RefreshCacheAsync().ConfigureAwait(false);
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
_allTemplates = list.ToList();
|
||||
ApplyFilter();
|
||||
UpdateStatus();
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 静默失败:保留当前缓存内容不动,不显示错误
|
||||
var cached = _printTemplateService.GetCached();
|
||||
if (cached.Count > 0 && _allTemplates.Count == 0)
|
||||
{
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
_allTemplates = cached.ToList();
|
||||
ApplyFilter();
|
||||
UpdateStatus();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyFilter()
|
||||
{
|
||||
IEnumerable<PrintTemplate> result = _allTemplates;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FilterCode))
|
||||
result = result.Where(t => (t.TemplateCode ?? string.Empty)
|
||||
.Contains(FilterCode, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FilterName))
|
||||
result = result.Where(t => (t.TemplateName ?? string.Empty)
|
||||
.Contains(FilterName, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FilterCategory))
|
||||
result = result.Where(t => (t.Category ?? string.Empty)
|
||||
.Contains(FilterCategory, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
var filtered = result.ToList();
|
||||
|
||||
// 原地差量更新,避免滚动位置重置和闪烁
|
||||
for (int i = Templates.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (!filtered.Any(t => t.Id == Templates[i].Id))
|
||||
Templates.RemoveAt(i);
|
||||
}
|
||||
for (int i = 0; i < filtered.Count; i++)
|
||||
{
|
||||
var item = filtered[i];
|
||||
var existingIdx = -1;
|
||||
for (int j = 0; j < Templates.Count; j++)
|
||||
{
|
||||
if (Templates[j].Id == item.Id) { existingIdx = j; break; }
|
||||
}
|
||||
if (existingIdx < 0)
|
||||
Templates.Insert(i, item);
|
||||
else
|
||||
{
|
||||
if (existingIdx != i) Templates.Move(existingIdx, i);
|
||||
Templates[i] = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateStatus()
|
||||
{
|
||||
var hasFilter = !string.IsNullOrWhiteSpace(FilterCode)
|
||||
|| !string.IsNullOrWhiteSpace(FilterName)
|
||||
|| !string.IsNullOrWhiteSpace(FilterCategory);
|
||||
StatusMessage = hasFilter
|
||||
? $"筛选结果 {Templates.Count} / {_allTemplates.Count} 个"
|
||||
: _allTemplates.Count > 0
|
||||
? $"共 {_allTemplates.Count} 个模板"
|
||||
: "暂无模板";
|
||||
}
|
||||
|
||||
private void ShowPreview(PrintTemplate template)
|
||||
{
|
||||
if (template == null) return;
|
||||
ShowPreviewAsync(template);
|
||||
}
|
||||
|
||||
private async Task ShowPreviewAsync(PrintTemplate template)
|
||||
{
|
||||
// 列表缓存可能不含 templateJson(大字段),按需通过 queryByCode 单独拉取
|
||||
var json = template.TemplateJson;
|
||||
if (string.IsNullOrWhiteSpace(json) || json == "{}")
|
||||
{
|
||||
try
|
||||
{
|
||||
var full = await _printTemplateService.GetByCodeAsync(template.TemplateCode ?? "");
|
||||
json = full?.TemplateJson;
|
||||
}
|
||||
catch { /* 保持 json 为 null,预览窗口显示"尚未设计" */ }
|
||||
}
|
||||
|
||||
var win = new PrintPreviewWindow(template, json)
|
||||
{
|
||||
Owner = Application.Current.MainWindow
|
||||
};
|
||||
win.Show();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user