弹窗添加

This commit is contained in:
2026-08-27 14:26:22 +08:00
parent 6a59552bc7
commit 47b4d3837b
3 changed files with 139 additions and 0 deletions
+54
View File
@@ -1,4 +1,5 @@
using Common; using Common;
using Command;
using ADP.ViewModels; using ADP.ViewModels;
using ADP.ViewModels.Dialogs; using ADP.ViewModels.Dialogs;
using ADP.Views; using ADP.Views;
@@ -12,6 +13,8 @@ using Service.Interface;
using System.Configuration; using System.Configuration;
using System.Data; using System.Data;
using System.Reflection; using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using UIShare.PubEvent; using UIShare.PubEvent;
using static System.Runtime.InteropServices.JavaScript.JSType; using static System.Runtime.InteropServices.JavaScript.JSType;
@@ -23,6 +26,7 @@ using DeviceCommand.Base;
using AutoMapper; using AutoMapper;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using ADP.Profiles; using ADP.Profiles;
using Prism.Dialogs;
using ; using ;
namespace ADP namespace ADP
@@ -60,6 +64,56 @@ namespace ADP
} }
protected override void OnInitialized() protected override void OnInitialized()
{ {
// 向命令库 CommandDialog 注入弹窗能力(命令库是纯 .NET 类库,不引用 WPF,这里通过委托实现依赖倒置)
var dialogService = Container.Resolve<IDialogService>();
CommandDialog. = (, , , , ct) =>
{
var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
CancellationTokenRegistration registration = default;
if ()
{
registration = ct.Register(() => tcs.TrySetCanceled(ct));
}
// 命令可能在后台线程执行,统一切回 UI 线程弹窗
Application.Current.Dispatcher.Invoke(() =>
{
var param = new DialogParameters
{
{ "Title", switch
{
CommandDialog.DialogType.Warning => "警告",
CommandDialog.DialogType.Error => "错误",
_ => "信息提示"
} },
{ "Message", ?? string.Empty },
{ "Icon", switch
{
CommandDialog.DialogType.Warning => "warn",
CommandDialog.DialogType.Error => "error",
_ => "info"
} },
{ "ShowOk", true },
{ "AutoCloseSeconds", (double) }
};
if ()
{
// 阻塞:用户手动关闭或自动关闭后才继续执行步骤
dialogService.ShowDialog("MessageBox", param, _ =>
{
registration.Dispose();
tcs.TrySetResult(true);
});
}
else
{
// 非阻塞:弹出后步骤立即继续(不等关闭回调)
dialogService.Show("MessageBox", param, _ => { });
tcs.TrySetResult(true);
}
});
return tcs.Task;
};
// 配置全局日志分发器:按 CurrentScope 路由到对应 LogArea // 配置全局日志分发器:按 CurrentScope 路由到对应 LogArea
var globalInfo = Container.Resolve<GlobalInfo>(); var globalInfo = Container.Resolve<GlobalInfo>();
LoggerHelper.Progress = new ScopeLogDispatcher(globalInfo); LoggerHelper.Progress = new ScopeLogDispatcher(globalInfo);
@@ -1,7 +1,9 @@
using UIShare.PubEvent; using UIShare.PubEvent;
using UIShare.ViewModelBase; using UIShare.ViewModelBase;
using System;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading;
namespace ADP.ViewModels.Dialogs namespace ADP.ViewModels.Dialogs
{ {
@@ -69,6 +71,11 @@ namespace ADP.ViewModels.Dialogs
public DialogCloseListener RequestClose { get; set; } public DialogCloseListener RequestClose { get; set; }
/// <summary>
/// 自动关闭定时器:自动关闭秒数大于 0 时启动,到时自动关闭弹窗(同时解除阻塞等待)
/// </summary>
private DispatcherTimer _autoCloseTimer;
public MessageBoxViewModel(IContainerProvider containerProvider):base(containerProvider) public MessageBoxViewModel(IContainerProvider containerProvider):base(containerProvider)
{ {
YesCommand = new DelegateCommand(OnYes); YesCommand = new DelegateCommand(OnYes);
@@ -93,6 +100,7 @@ namespace ADP.ViewModels.Dialogs
public override void OnDialogClosed() public override void OnDialogClosed()
{ {
_autoCloseTimer?.Stop();
_eventAggregator.GetEvent<OverlayEvent>().Publish(false); _eventAggregator.GetEvent<OverlayEvent>().Publish(false);
} }
@@ -117,6 +125,21 @@ namespace ADP.ViewModels.Dialogs
ShowNo = parameters.GetValue<bool>("ShowNo"); ShowNo = parameters.GetValue<bool>("ShowNo");
ShowOk = parameters.GetValue<bool>("ShowOk"); ShowOk = parameters.GetValue<bool>("ShowOk");
ShowCancel = parameters.GetValue<bool>("ShowCancel"); ShowCancel = parameters.GetValue<bool>("ShowCancel");
// 自动关闭:秒数大于 0 时启动定时器,到时自动关闭(供命令库 弹窗 命令的自动关闭参数使用)
if (parameters.TryGetValue("AutoCloseSeconds", out double autoCloseSeconds) && autoCloseSeconds > 0)
{
_autoCloseTimer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(autoCloseSeconds)
};
_autoCloseTimer.Tick += (s, e) =>
{
_autoCloseTimer.Stop();
RequestClose.Invoke(new DialogResult(ButtonResult.OK));
};
_autoCloseTimer.Start();
}
} }
#endregion #endregion
} }
+62
View File
@@ -0,0 +1,62 @@
using Common.Attributes;
using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
namespace Command
{
/// <summary>
/// 对话框命令:在测试流程中弹出提示窗口。
/// 命令库为纯 .NET 类库,不直接引用 WPF 程序集;
/// 实际的弹窗能力由宿主程序(ADP 外壳)在启动时注入到 <see cref="弹窗处理器"/> 委托中实现(依赖倒置)。
/// </summary>
[ADPCommand]
public static class CommandDialog
{
/// <summary>
/// 弹窗类型
/// </summary>
public enum DialogType
{
/// <summary>
/// 信息提示
/// </summary>
Info,
/// <summary>
/// 警告提示
/// </summary>
Warning,
/// <summary>
/// 错误提示
/// </summary>
Error
}
/// <summary>
/// 弹窗处理委托(参数依次为:弹窗类型、弹窗详细、是否阻塞、自动关闭秒数、取消令牌)。
/// 由宿主程序启动时注入实现;未注入时弹窗命令降级为仅输出日志,不会抛异常。
/// </summary>
[Browsable(false)]
public static Func<DialogType, string, bool, float, CancellationToken, Task> ;
/// <summary>
/// 弹窗:在界面上显示一个提示对话框。
/// </summary>
/// <param name="弹窗类型">弹窗样式:Info 信息 / Warning 警告 / Error 错误</param>
/// <param name="弹窗详细">弹窗中显示的详细内容</param>
/// <param name="是否阻塞">true = 步骤暂停,等待用户关闭(或自动关闭)后才继续;false = 弹出后步骤立即继续</param>
/// <param name="自动关闭秒数">大于 0 时,弹窗在指定秒数后自动关闭;小于等于 0 时不自动关闭,需用户手动关闭</param>
/// <param name="ct">异步取消令牌</param>
public static async Task (DialogType , string , bool , float , CancellationToken ct)
{
var handler = ;
if (handler == null)
{
Console.WriteLine($"[弹窗命令] 宿主未注入弹窗处理器,跳过弹窗:{弹窗详细}");
return;
}
await handler(, , , , ct);
}
}
}