using _29WxOrderWpf.ToolCtrls;
using OrderSupportTicket.Models;
using OrderSupportTicket.Services;
using OrderSupportTicket.ViewModels;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace OrderSupportTicket.Views;
///
/// 工单对话页面。页面生命周期只负责激活/停用 ViewModel,业务交互均在 ViewModel 中。
///
public partial class OrderSupportTicketView : UserControl
{
private bool _active;
private Window _hostWindow;
public OrderSupportTicketView()
: this(
new TicketApiService(),
new EventSourceTicketRealtimeService(),
CreateDefaultOptions(),
ownsRealtime: true)
{
}
public OrderSupportTicketView(
ITicketApiService api,
ITicketRealtimeService realtime,
TicketClientOptions options = null)
: this(api, realtime, options, ownsRealtime: true)
{
}
///
/// 创建工单页。ownsRealtime 为 false 时复用宿主提供的共享 SSE 连接,
/// 页面关闭不会停止该连接。
///
public OrderSupportTicketView(
ITicketApiService api,
ITicketRealtimeService realtime,
TicketClientOptions options,
bool ownsRealtime)
{
InitializeComponent();
ViewModel = new OrderSupportTicketViewModel(
api,
realtime,
options ?? CreateDefaultOptions(),
ownsRealtime);
DataContext = ViewModel;
Loaded += OnLoaded;
Unloaded += OnUnloaded;
}
///
/// 当前联调使用的默认参数。正式接入时可由宿主替换为登录账号和店铺 APPID。
///
public static TicketClientOptions CreateDefaultOptions(string fallbackUserName = null)
{
var configured = TicketClientOptions.FromApplicationSettings();
var userName = !string.IsNullOrWhiteSpace(configured.UserName)
? configured.UserName
: (!string.IsNullOrWhiteSpace(fallbackUserName)
? fallbackUserName.Trim()
: "18990991234");
var appIds = configured.AppIds != null && configured.AppIds.Count > 0
? configured.AppIds
: new List
{
"wx316b1291351558aa",
"wx7999743c3d64c05c"
};
return new TicketClientOptions
{
UserName = userName,
AppIds = appIds,
Orders =
[
new TicketOrderOption
{
Amount = 109m,
AppId = "wx316b1291351558aa",
GoodsName = "梵客隆收腹内裤女新款高腰无痕磨毛暖融收小肚子提臀塑身平角裤",
OrderId = "9000000000000000001",
OrderedAt = new DateTime(2020, 1, 1),
},
new TicketOrderOption
{
Amount = 109m,
AppId = "wx7999743c3d64c05c",
GoodsName = "洁柔抽纸粉Face家用实惠装批发纸巾大包面纸餐巾纸抽整箱可湿水纸",
OrderId = "9000000000000000002",
OrderedAt = new DateTime(2020, 1, 1),
}
]
};
}
///
/// 当前页面对应的工单 ViewModel。
///
public OrderSupportTicketViewModel ViewModel { get; }
///
/// 宿主可在页面加载前注入账号、APPID 与本地订单数据。
///
public void Configure(TicketClientOptions options)
{
ViewModel.Configure(options);
}
///
/// 从订单页直接打开新工单草稿。
///
public void OpenNewTicket(TicketOrderOption order)
{
ViewModel.OpenNewTicket(order);
}
///
/// 打开并定位到指定工单。
///
public void OpenTicket(string appId, string wechatOrderId)
{
ViewModel.OpenTicket(appId, wechatOrderId);
}
private void TicketSearchBox_GotFocus(object sender, RoutedEventArgs e)
{
ViewModel.CancelNewTicketDraft();
}
///
/// 点击订单号复制到剪贴板,并使用宿主窗口的 Toast 提示结果。
///
private void CopyOrderId_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (sender is not FrameworkElement element)
return;
var orderId = element.Tag as string;
if (string.IsNullOrWhiteSpace(orderId)
&& element.DataContext is WorkOrderSummaryViewModel ticket)
{
orderId = ticket.WechatOrderId;
}
if (string.IsNullOrWhiteSpace(orderId))
return;
var window = Window.GetWindow(this) ?? _hostWindow;
if (window == null)
return;
if (ClipboardHelper.TrySetText(orderId))
{
ToastHelper.Show(window, "订单号已复制");
}
else
{
ToastHelper.Show(window, "复制失败");
}
}
private async void OnLoaded(object sender, System.Windows.RoutedEventArgs e)
{
if (_active)
return;
_active = true;
AttachHostWindow(Window.GetWindow(this));
UpdateWindowActiveState();
await ViewModel.InitializeAsync();
}
private async void OnUnloaded(object sender, System.Windows.RoutedEventArgs e)
{
if (!_active)
return;
_active = false;
ViewModel.IsWindowActive = false;
DetachHostWindow();
await ViewModel.DeactivateAsync();
}
private void AttachHostWindow(Window window)
{
DetachHostWindow();
_hostWindow = window;
if (_hostWindow == null)
return;
_hostWindow.Activated += OnHostWindowActivated;
_hostWindow.Deactivated += OnHostWindowDeactivated;
_hostWindow.IsVisibleChanged += OnHostWindowIsVisibleChanged;
_hostWindow.StateChanged += OnHostWindowStateChanged;
_hostWindow.Closed += OnHostWindowClosed;
}
private void DetachHostWindow()
{
if (_hostWindow == null)
return;
_hostWindow.Activated -= OnHostWindowActivated;
_hostWindow.Deactivated -= OnHostWindowDeactivated;
_hostWindow.IsVisibleChanged -= OnHostWindowIsVisibleChanged;
_hostWindow.StateChanged -= OnHostWindowStateChanged;
_hostWindow.Closed -= OnHostWindowClosed;
_hostWindow = null;
}
private void UpdateWindowActiveState()
{
var window = _hostWindow;
ViewModel.IsWindowActive = window != null
&& window.IsVisible
&& window.IsActive
&& window.WindowState != WindowState.Minimized;
}
private void OnHostWindowActivated(object sender, EventArgs e)
{
UpdateWindowActiveState();
}
private void OnHostWindowDeactivated(object sender, EventArgs e)
{
UpdateWindowActiveState();
}
private void OnHostWindowIsVisibleChanged(
object sender,
DependencyPropertyChangedEventArgs e)
{
UpdateWindowActiveState();
}
private void OnHostWindowStateChanged(object sender, EventArgs e)
{
UpdateWindowActiveState();
}
private void OnHostWindowClosed(object sender, EventArgs e)
{
ViewModel.IsWindowActive = false;
DetachHostWindow();
}
}