修改工单流程页面,订单列表增加工单按钮
This commit is contained in:
1 parent
f9dcae4610
commit
10bb0803d9
44 files changed
+5920
-1291
No files matched your search
@@ -12,7 +12,41 @@ namespace WxOrder.Framework.Commons.Dialogs
|
||||
public static class DialogService
|
||||
{
|
||||
// ========== 对外接口 ==========
|
||||
public static bool ExistsWindow(FrameworkElement view)
|
||||
{
|
||||
var window = Application.Current.Windows.OfType<Window>().FirstOrDefault(w => w.Content != null && w.Content.GetType() == view.GetType());
|
||||
return window != null;
|
||||
}
|
||||
public static void ActivateWindow(FrameworkElement view)
|
||||
{
|
||||
var window = Application.Current.Windows.OfType<Window>().FirstOrDefault(w => w.Content != null && w.Content.GetType() == view.GetType());
|
||||
if (window == null)
|
||||
return;
|
||||
|
||||
if (!window.IsVisible)
|
||||
window.Show();
|
||||
if (window.WindowState == WindowState.Minimized)
|
||||
window.WindowState = WindowState.Normal;
|
||||
|
||||
if (!window.Activate())
|
||||
{
|
||||
// 窗口被其他进程遮挡时,短暂置顶以切换到用户面前。
|
||||
window.Topmost = true;
|
||||
window.Topmost = false;
|
||||
window.Activate();
|
||||
}
|
||||
}
|
||||
public static void ShowOrActivateWindow(FrameworkElement view, IDialogParameters parameters = null, Action<IDialogResult> callback = null)
|
||||
{
|
||||
if (ExistsWindow(view))
|
||||
{
|
||||
ActivateWindow(view);
|
||||
}
|
||||
else
|
||||
{
|
||||
Show(view, parameters, callback);
|
||||
}
|
||||
}
|
||||
/// <summary>非模态弹出</summary>
|
||||
public static void Show(FrameworkElement view,
|
||||
IDialogParameters parameters = null,
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media.Effects;
|
||||
|
||||
namespace _29WxOrderWpf.ToolCtrls;
|
||||
|
||||
public enum ToastType { Info, Success, Warning, Error }
|
||||
|
||||
/// <summary>
|
||||
/// 在指定 Window 内显示自动消失的提示框(Toast)
|
||||
/// 用法:ToastHelper.Show(window, "保存成功", ToastType.Success);
|
||||
/// </summary>
|
||||
public static class ToastHelper
|
||||
{
|
||||
// 每个 Window 对应一个提示容器,用于多个提示堆叠
|
||||
private static readonly ConditionalWeakTable<Window, ToastAdorner> Hosts = new();
|
||||
private static SolidColorBrush msgBrush;
|
||||
static ToastHelper()
|
||||
{
|
||||
msgBrush = Application.Current.Resources["pageColorBrush"] as SolidColorBrush;
|
||||
msgBrush = Application.Current.Resources["pageColorBrush"] as SolidColorBrush;
|
||||
}
|
||||
/// <param name="owner">要展示提示的窗口</param>
|
||||
/// <param name="message">提示内容</param>
|
||||
/// <param name="type">类型(决定背景色)</param>
|
||||
/// <param name="durationMs">停留时长(毫秒,不含淡入淡出)</param>
|
||||
public static void Show(Window owner, string message,
|
||||
ToastType type = ToastType.Info, int durationMs = 2000)
|
||||
{
|
||||
if (owner == null || string.IsNullOrEmpty(message)) return;
|
||||
|
||||
// 允许在非 UI 线程调用
|
||||
if (!owner.Dispatcher.CheckAccess())
|
||||
{
|
||||
owner.Dispatcher.BeginInvoke(new Action(() => Show(owner, message, type, durationMs)));
|
||||
return;
|
||||
}
|
||||
|
||||
// 窗口还没加载完,等加载后再显示
|
||||
if (!owner.IsLoaded)
|
||||
{
|
||||
RoutedEventHandler handler = null;
|
||||
handler = (s, e) =>
|
||||
{
|
||||
owner.Loaded -= handler;
|
||||
Show(owner, message, type, durationMs);
|
||||
};
|
||||
owner.Loaded += handler;
|
||||
return;
|
||||
}
|
||||
|
||||
if (owner.Content is not UIElement content) return;
|
||||
var layer = AdornerLayer.GetAdornerLayer(content);
|
||||
if (layer == null) return;
|
||||
|
||||
if (!Hosts.TryGetValue(owner, out var host))
|
||||
{
|
||||
host = new ToastAdorner(content);
|
||||
layer.Add(host);
|
||||
Hosts.Add(owner, host);
|
||||
}
|
||||
|
||||
var toast = CreateToast(message, type);
|
||||
host.Panel.Children.Add(toast);
|
||||
|
||||
// 淡入 -> 停留 -> 淡出
|
||||
var fadeIn = TimeSpan.FromMilliseconds(250);
|
||||
var fadeOut = TimeSpan.FromMilliseconds(400);
|
||||
var hold = TimeSpan.FromMilliseconds(Math.Max(durationMs, 0));
|
||||
|
||||
var anim = new DoubleAnimationUsingKeyFrames();
|
||||
anim.KeyFrames.Add(new LinearDoubleKeyFrame(0, TimeSpan.Zero));
|
||||
anim.KeyFrames.Add(new LinearDoubleKeyFrame(1, fadeIn));
|
||||
anim.KeyFrames.Add(new LinearDoubleKeyFrame(1, fadeIn + hold));
|
||||
anim.KeyFrames.Add(new LinearDoubleKeyFrame(0, fadeIn + hold + fadeOut));
|
||||
anim.Completed += (s, e) =>
|
||||
{
|
||||
host.Panel.Children.Remove(toast);
|
||||
if (host.Panel.Children.Count == 0)
|
||||
{
|
||||
layer.Remove(host);
|
||||
Hosts.Remove(owner);
|
||||
}
|
||||
};
|
||||
toast.BeginAnimation(UIElement.OpacityProperty, anim);
|
||||
}
|
||||
public static void Show(string message,
|
||||
ToastType type = ToastType.Info, int durationMs = 2000)
|
||||
{
|
||||
Window window = Application.Current.Windows
|
||||
.OfType<Window>()
|
||||
.FirstOrDefault(w => w.IsActive) ?? Application.Current.MainWindow;
|
||||
Show(window, message, type, durationMs);
|
||||
}
|
||||
private static Border CreateToast(string message, ToastType type)
|
||||
{
|
||||
var color = type switch
|
||||
{
|
||||
ToastType.Success => Color.FromRgb(0x2E, 0x9E, 0x5B),
|
||||
ToastType.Warning => Color.FromRgb(0xE6, 0x9A, 0x1A),
|
||||
ToastType.Error => Color.FromRgb(0xD9, 0x4A, 0x4A),
|
||||
_ => msgBrush.Color,//Color.FromRgb(0x40, 0x40, 0x40),
|
||||
};
|
||||
|
||||
return new Border
|
||||
{
|
||||
Background = new SolidColorBrush(color),
|
||||
CornerRadius = new CornerRadius(6),
|
||||
Padding = new Thickness(18, 10, 18, 10),
|
||||
Margin = new Thickness(0, 0, 0, 8),
|
||||
Opacity = 0,
|
||||
MaxWidth = 480,
|
||||
Effect = new DropShadowEffect
|
||||
{
|
||||
BlurRadius = 12,
|
||||
ShadowDepth = 2,
|
||||
Opacity = 0.3,
|
||||
Color = Colors.Black
|
||||
},
|
||||
Child = new TextBlock
|
||||
{
|
||||
Text = message,
|
||||
Foreground = Brushes.White,
|
||||
FontSize = 14,
|
||||
TextWrapping = TextWrapping.Wrap
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>覆盖在窗口内容上方的提示容器,顶部居中</summary>
|
||||
private sealed class ToastAdorner : Adorner
|
||||
{
|
||||
public StackPanel Panel { get; }
|
||||
|
||||
public ToastAdorner(UIElement adornedElement) : base(adornedElement)
|
||||
{
|
||||
IsHitTestVisible = false; // 不拦截鼠标事件
|
||||
Panel = new StackPanel { Orientation = Orientation.Vertical };
|
||||
AddVisualChild(Panel);
|
||||
}
|
||||
|
||||
protected override int VisualChildrenCount => 1;
|
||||
protected override Visual GetVisualChild(int index) => Panel;
|
||||
|
||||
protected override Size MeasureOverride(Size constraint)
|
||||
{
|
||||
Panel.Measure(constraint);
|
||||
return AdornedElement.RenderSize;
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
var size = Panel.DesiredSize;
|
||||
double x = (finalSize.Width - size.Width) / 2;
|
||||
Panel.Arrange(new Rect(new Point(Math.Max(x, 0), 30), size)); // 距顶部 30
|
||||
return finalSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user