From 9201c7ca158eea4d74016111800d845ef4e38445 Mon Sep 17 00:00:00 2001 From: geht <2947093423@qq.com> Date: Fri, 15 May 2026 15:46:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E5=8E=9F=E6=9D=90=E6=96=99?= =?UTF-8?q?=E5=85=A5=E5=9C=BA=E8=AE=B0=E5=BD=95=E8=A7=86=E5=9B=BE=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=EF=BC=8C=E6=96=B0=E5=A2=9E=20SuspendEmbeddedPrintPrev?= =?UTF-8?q?iewAirspace=20=E5=B1=9E=E6=80=A7=E4=BB=A5=E5=A4=84=E7=90=86=20W?= =?UTF-8?q?ebView2=20=E7=9A=84=E5=B5=8C=E5=85=A5=E5=BC=8F=E6=89=93?= =?UTF-8?q?=E5=8D=B0=E9=A2=84=E8=A7=88=E9=81=AE=E6=8C=A1=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E3=80=82=E9=87=8D=E6=9E=84=E7=9B=B8=E5=85=B3=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E6=A1=86=E8=B0=83=E7=94=A8=E9=80=BB=E8=BE=91=EF=BC=8C=E7=A1=AE?= =?UTF-8?q?=E4=BF=9D=E5=9C=A8=E5=BC=B9=E7=AA=97=E6=9C=9F=E9=97=B4=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E7=AE=A1=E7=90=86=E9=A2=84=E8=A7=88=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E3=80=82=E5=90=8C=E6=97=B6=EF=BC=8C=E4=BC=98=E5=8C=96=E5=8E=9F?= =?UTF-8?q?=E6=9D=90=E6=96=99=E5=8D=A1=E7=89=87=E7=94=9F=E6=88=90=E7=A1=AE?= =?UTF-8?q?=E8=AE=A4=E7=AA=97=E5=8F=A3=E7=9A=84=E9=A2=84=E8=A7=88=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E6=8F=90=E5=8D=87=E7=94=A8=E6=88=B7=E4=BD=93?= =?UTF-8?q?=E9=AA=8C=E5=92=8C=E7=95=8C=E9=9D=A2=E5=93=8D=E5=BA=94=E6=80=A7?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RawMaterialEntryEditDialogViewModel.cs | 92 ++++++++++++++----- .../RawMaterialEntryOperationViewModel.cs | 13 ++- .../RawMaterialCardGenerateConfirmWindow.xaml | 28 +++++- ...wMaterialCardGenerateConfirmWindow.xaml.cs | 83 ++++++++++++++--- .../RawMaterialEntryOperationView.xaml | 2 +- 5 files changed, 172 insertions(+), 46 deletions(-) diff --git a/yy-admin-master/YY.Admin/ViewModels/RawMaterialEntry/RawMaterialEntryEditDialogViewModel.cs b/yy-admin-master/YY.Admin/ViewModels/RawMaterialEntry/RawMaterialEntryEditDialogViewModel.cs index 7198f54..cb52ef2 100644 --- a/yy-admin-master/YY.Admin/ViewModels/RawMaterialEntry/RawMaterialEntryEditDialogViewModel.cs +++ b/yy-admin-master/YY.Admin/ViewModels/RawMaterialEntry/RawMaterialEntryEditDialogViewModel.cs @@ -114,6 +114,46 @@ public class RawMaterialEntryEditDialogViewModel : BaseViewModel, IDialogResulta public ObservableCollection> IsSpecialAdoptionOptions { get; } = new(); public ObservableCollection> StatusOptions { get; } = new(); public ObservableCollection SplitCodeDetails { get; } = new(); + + private bool _suspendEmbeddedPrintPreviewAirspace; + + /// + /// WebView2 使用独立 HWND(Airspace),会同窗体内浮在 WPF 元素之上,遮挡 HandyControl 内嵌 Dialog。 + /// 原料入场独立页在弹窗期间通过绑定收起预览宿主;其它页面无 WebView2 时可忽略该属性。 + /// + public bool SuspendEmbeddedPrintPreviewAirspace + { + get => _suspendEmbeddedPrintPreviewAirspace; + private set + { + if (!SetProperty(ref _suspendEmbeddedPrintPreviewAirspace, value)) + { + return; + } + + OnSuspendEmbeddedPrintPreviewAirspaceChanged(); + } + } + + /// 子类在预览区可见性依赖此标志时,覆写以联动通知。 + protected virtual void OnSuspendEmbeddedPrintPreviewAirspaceChanged() + { + } + + /// 在异步弹窗期间挂起右侧嵌入 WebView2,避免遮挡模态内容。 + protected async Task SuspendEmbeddedPrintPreviewAirspaceWhileAsync(Func> action) + { + SuspendEmbeddedPrintPreviewAirspace = true; + try + { + return await action(); + } + finally + { + SuspendEmbeddedPrintPreviewAirspace = false; + } + } + public double SplitCodeTableHeight => CalculateSplitCodeTableHeight(); public string SplitTotalPortionsDisplay => JoinSplitValue(item => item.Portions?.ToString(CultureInfo.InvariantCulture), true); public string SplitPortionWeightDisplay => JoinSplitValue(item => FormatNullableDecimal(item.PortionWeight), true); @@ -439,13 +479,14 @@ public class RawMaterialEntryEditDialogViewModel : BaseViewModel, IDialogResulta bool confirmed; try { - confirmed = await HandyControl.Controls.Dialog.Show() - .Initialize(vm => - { - pickerVm = vm; - vm.Initialize(Entry?.BillNo); - }) - .GetResultAsync(); + confirmed = await SuspendEmbeddedPrintPreviewAirspaceWhileAsync(() => + HandyControl.Controls.Dialog.Show() + .Initialize(vm => + { + pickerVm = vm; + vm.Initialize(Entry?.BillNo); + }) + .GetResultAsync()); } catch { @@ -490,13 +531,14 @@ public class RawMaterialEntryEditDialogViewModel : BaseViewModel, IDialogResulta bool confirmed; try { - confirmed = await HandyControl.Controls.Dialog.Show() - .Initialize(vm => - { - pickerVm = vm; - vm.Initialize(row.WarehouseLocation); - }) - .GetResultAsync(); + confirmed = await SuspendEmbeddedPrintPreviewAirspaceWhileAsync(() => + HandyControl.Controls.Dialog.Show() + .Initialize(vm => + { + pickerVm = vm; + vm.Initialize(row.WarehouseLocation); + }) + .GetResultAsync()); } catch (Exception ex) { @@ -521,13 +563,14 @@ public class RawMaterialEntryEditDialogViewModel : BaseViewModel, IDialogResulta bool confirmed; try { - confirmed = await HandyControl.Controls.Dialog.Show() - .Initialize(vm => - { - pickerVm = vm; - vm.Initialize(Entry?.MaterialCode, Entry?.MaterialName); - }) - .GetResultAsync(); + confirmed = await SuspendEmbeddedPrintPreviewAirspaceWhileAsync(() => + HandyControl.Controls.Dialog.Show() + .Initialize(vm => + { + pickerVm = vm; + vm.Initialize(Entry?.MaterialCode, Entry?.MaterialName); + }) + .GetResultAsync()); } catch { @@ -582,9 +625,10 @@ public class RawMaterialEntryEditDialogViewModel : BaseViewModel, IDialogResulta bool confirmed; try { - confirmed = await HandyControl.Controls.Dialog.Show() - .Initialize(vm => pickerVm = vm) - .GetResultAsync(); + confirmed = await SuspendEmbeddedPrintPreviewAirspaceWhileAsync(() => + HandyControl.Controls.Dialog.Show() + .Initialize(vm => pickerVm = vm) + .GetResultAsync()); } catch { return; } diff --git a/yy-admin-master/YY.Admin/ViewModels/RawMaterialEntry/RawMaterialEntryOperationViewModel.cs b/yy-admin-master/YY.Admin/ViewModels/RawMaterialEntry/RawMaterialEntryOperationViewModel.cs index 2a79f40..ae9a88d 100644 --- a/yy-admin-master/YY.Admin/ViewModels/RawMaterialEntry/RawMaterialEntryOperationViewModel.cs +++ b/yy-admin-master/YY.Admin/ViewModels/RawMaterialEntry/RawMaterialEntryOperationViewModel.cs @@ -170,9 +170,18 @@ public class RawMaterialEntryOperationViewModel : RawMaterialEntryEditDialogView { if (!SetProperty(ref _isPrintPreviewExpanded, value)) return; if (value) _lastPreviewSnapshot = string.Empty; + RaisePropertyChanged(nameof(IsPrintPreviewWebAreaVisible)); } } + /// 右侧下方预览区是否显示 WebView2 宿主(HandyControl 内嵌弹窗期间因 Airspace 临时隐藏)。 + public bool IsPrintPreviewWebAreaVisible => !SuspendEmbeddedPrintPreviewAirspace && IsPrintPreviewExpanded; + + protected override void OnSuspendEmbeddedPrintPreviewAirspaceChanged() + { + RaisePropertyChanged(nameof(IsPrintPreviewWebAreaVisible)); + } + private string _printPreviewStatus = string.Empty; /// 预览区状态提示(如离线、加载中、错误摘要)。 public string PrintPreviewStatus @@ -744,7 +753,9 @@ public class RawMaterialEntryOperationViewModel : RawMaterialEntryEditDialogView Owner = Application.Current.MainWindow, WindowStartupLocation = WindowStartupLocation.CenterOwner }; - var confirmed = confirmWindow.ShowDialog() == true; + // WebView2 Airspace:模态子窗体仍可能与本窗体内 HWND 叠层异常,弹窗期间收起嵌入预览 + var confirmed = await SuspendEmbeddedPrintPreviewAirspaceWhileAsync(() => + Task.FromResult(confirmWindow.ShowDialog() == true)); if (!confirmed) return; var selectedPrinterName = confirmWindow.SelectedPrinterName; if (string.IsNullOrWhiteSpace(selectedPrinterName)) diff --git a/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialCardGenerateConfirmWindow.xaml b/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialCardGenerateConfirmWindow.xaml index ef6abc6..639fd23 100644 --- a/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialCardGenerateConfirmWindow.xaml +++ b/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialCardGenerateConfirmWindow.xaml @@ -70,6 +70,8 @@ ItemsSource="{Binding PlanItems}" SelectedItem="{Binding SelectedPlanItem, Mode=TwoWay}" AutoGenerateColumns="False" + EnableRowVirtualization="False" + EnableColumnVirtualization="False" HeadersVisibility="Column" CanUserResizeColumns="True" CanUserReorderColumns="False" @@ -85,10 +87,10 @@ SelectionMode="Single" SelectionUnit="FullRow" ScrollViewer.HorizontalScrollBarVisibility="Auto" - ScrollViewer.VerticalScrollBarVisibility="Auto" - SelectionChanged="PlanGrid_OnSelectionChanged"> + ScrollViewer.VerticalScrollBarVisibility="Auto"> + @@ -119,10 +129,17 @@ + + + + + + + @@ -159,7 +176,8 @@ - + + diff --git a/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialCardGenerateConfirmWindow.xaml.cs b/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialCardGenerateConfirmWindow.xaml.cs index 21f01d0..5c02d67 100644 --- a/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialCardGenerateConfirmWindow.xaml.cs +++ b/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialCardGenerateConfirmWindow.xaml.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Text.Json; using System.Threading; +using System.Threading.Tasks; using System.Windows; using System.Windows.Controls.Primitives; using YY.Admin.Core.Services; @@ -37,8 +38,12 @@ public partial class RawMaterialCardGenerateConfirmWindow : HandyControl.Control private readonly Func _previewHtmlBuilder; private readonly IPrintDotService _printDotService; private bool _webViewReady; + /// 增大表示又有新的预览请求,旧的后台渲染结果应丢弃。 + private int _previewVersion; private bool _isRefreshingPrinters; private bool _suppressPrinterSave; + /// Loaded 中批量赋值选中行时跳过 Setter 内的去抖预览,再由 Loaded 单次立即刷新。 + private bool _suppressPreviewSchedule; private string? _preferredPrinterNameOnLoad; private string _printerStatus = "加载打印机中..."; @@ -78,6 +83,11 @@ public partial class RawMaterialCardGenerateConfirmWindow : HandyControl.Control if (ReferenceEquals(_selectedPlanItem, value)) return; _selectedPlanItem = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedPlanItem))); + // 仅用属性变更触发预览刷新,避免 SelectionChanged + 绑定 双重 Navigate 造成卡顿 + if (!_suppressPreviewSchedule) + { + SchedulePreviewNavigate(skipDebounce: false); + } } } @@ -124,15 +134,24 @@ public partial class RawMaterialCardGenerateConfirmWindow : HandyControl.Control { await PreviewWebView.EnsureCoreWebView2Async(); _webViewReady = true; - if (SelectedPlanItem == null && PlanItems.Count > 0) + try { - SelectedPlanItem = PlanItems[0]; + _suppressPreviewSchedule = true; + if (SelectedPlanItem == null && PlanItems.Count > 0) + { + SelectedPlanItem = PlanItems[0]; + } } - RenderSelectedPreview(); + finally + { + _suppressPreviewSchedule = false; + } + + SchedulePreviewNavigate(skipDebounce: true); } catch { - PreviewWebView.NavigateToString("模板预览加载失败"); + PreviewWebView.NavigateToString("模板预览加载失败"); } } @@ -247,6 +266,7 @@ public partial class RawMaterialCardGenerateConfirmWindow : HandyControl.Control private void OnClosing(object? sender, CancelEventArgs e) { + Interlocked.Increment(ref _previewVersion); SavePaneRatio(GetCurrentLeftRatio()); SaveCurrentColumnWidths(); } @@ -330,28 +350,61 @@ public partial class RawMaterialCardGenerateConfirmWindow : HandyControl.Control } } - private void PlanGrid_OnSelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) + /// + /// RenderToHtml 在 UI 线程会阻塞鼠标/选中反馈;移至后台线程并做短去抖合并连点。 + /// + private async void SchedulePreviewNavigate(bool skipDebounce) { - RenderSelectedPreview(); - } - - private void RenderSelectedPreview() - { - if (!_webViewReady) return; - if (SelectedPlanItem == null) + if (!_webViewReady) { - PreviewWebView.NavigateToString("请先选择左侧卡片记录"); return; } + var token = Interlocked.Increment(ref _previewVersion); + try { - var html = _previewHtmlBuilder.Invoke(SelectedPlanItem); + if (!skipDebounce) + { + await Task.Delay(45).ConfigureAwait(true); + if (token != _previewVersion) + { + return; + } + } + + var row = SelectedPlanItem; + if (row == null) + { + PreviewWebView.NavigateToString( + "请先选择左侧卡片记录"); + return; + } + + string html; + try + { + var capturedRow = row; + html = await Task.Run(() => _previewHtmlBuilder(capturedRow)).ConfigureAwait(true); + } + catch (Exception ex) + { + html = + "模板预览失败:" + + System.Net.WebUtility.HtmlEncode(ex.Message) + + ""; + } + + if (token != _previewVersion || !ReferenceEquals(SelectedPlanItem, row)) + { + return; + } + PreviewWebView.NavigateToString(html); } catch { - PreviewWebView.NavigateToString("模板预览加载失败"); + /* 窗口关闭或调度异常时忽略 */ } } diff --git a/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialEntryOperationView.xaml b/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialEntryOperationView.xaml index e68cc95..a7ef3d1 100644 --- a/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialEntryOperationView.xaml +++ b/yy-admin-master/YY.Admin/Views/RawMaterialEntry/RawMaterialEntryOperationView.xaml @@ -1136,7 +1136,7 @@ MinHeight="200" MaxHeight="420" Background="#525659" - Visibility="{Binding IsPrintPreviewExpanded, Converter={StaticResource Boolean2VisibilityConverter}}"> + Visibility="{Binding IsPrintPreviewWebAreaVisible, Converter={StaticResource Boolean2VisibilityConverter}}">