782 lines
22 KiB
C#
782 lines
22 KiB
C#
using _29WxOrderWpf.BaseWindows;
|
|
using _29WxOrderWpf.Ctrls.BuyerCtrls;
|
|
using _29WxOrderWpf.Ctrls.OrderCtrls;
|
|
using _29WxOrderWpf.Ctrls.Settings;
|
|
using _29WxOrderWpf.Windows.LoginWindows;
|
|
using AllBase;
|
|
using AllBase.DouYinModel.Result;
|
|
using AllBase.Extension;
|
|
using AllBase.Helper;
|
|
using AllBase.Model;
|
|
using AllBase.Model.DBModel;
|
|
using AllBase.Model.Result;
|
|
using CefSharp;
|
|
using NaiBa.Util;
|
|
using NaiBa.Util.Extension;
|
|
using Newtonsoft.Json.Linq;
|
|
using OrderSupportTicket.Models;
|
|
using OrderSupportTicket.Services;
|
|
using OrderSupportTicket.Views;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Data;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Animation;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Navigation;
|
|
using System.Windows.Shapes;
|
|
using System.Xml.Linq;
|
|
using Work;
|
|
using Work._29Tools.BLL;
|
|
using Work._29Tools.Forms.UserForms;
|
|
using WxOrder.Framework.Commons;
|
|
using WxOrder.Framework.Commons.Dialogs;
|
|
using WxOrder.Framework.Helpers;
|
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
|
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
|
|
|
|
namespace _29WxOrderWpf
|
|
{
|
|
/// <summary>
|
|
/// MainWindow.xaml 的交互逻辑
|
|
/// </summary>
|
|
public partial class MainWindow : BaseWindow, INotifyPropertyChanged
|
|
{
|
|
public static MainWindow Instance { get; private set; }
|
|
public static readonly object _orderLock = new object();
|
|
|
|
private readonly TicketRealtimeMonitor _ticketMonitor = TicketRealtimeMonitor.Current;
|
|
private readonly WorkOrderUnreadService _workOrderUnreadService = new WorkOrderUnreadService();
|
|
private TicketClientOptions _ticketOptions;
|
|
private OrderSupportTicketView _orderSupportView;
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
public string Balance { get { return "快递余额:" + BaseClass.Balance.ToString("0.00"); } set { OnPropertyChanged("Balance"); } }
|
|
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
this.DataContext = this;
|
|
Instance = this;
|
|
|
|
gridUser.Visibility = Visibility.Collapsed;
|
|
|
|
_ticketMonitor.NewMessageReceived += OnTicketNewMessageReceived;
|
|
_ticketMonitor.UnreadCountChanged += OnTicketUnreadCountChanged;
|
|
Closed += MainWindow_Closed;
|
|
}
|
|
|
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
GlobalConfig.Dispatcher = this.Dispatcher;
|
|
lblDebug.Visibility = Visibility.Collapsed;
|
|
|
|
ucWindowBox.SetWindowMax();
|
|
this.Title = BaseClass.ToolName;
|
|
|
|
new Thread(AutoAntiGrabbingMechanism).Start(); // 反抓包
|
|
|
|
#region 弹出登录窗口
|
|
LoginWindow loginWindow = new LoginWindow(App.args);
|
|
loginWindow.Owner = this;
|
|
loginWindow.ShowDialog();
|
|
#endregion
|
|
|
|
if (loginWindow.IsLogin)
|
|
{
|
|
lblVersion.Content = BaseClass.ToolName + " V" + BaseClass.Varsion + " - " + BaseClass.NickName;
|
|
|
|
//shopListCtrl.Visibility = Visibility.Visible;
|
|
orderListCtrl.Visibility = Visibility.Visible;
|
|
pddBuyerOrderReadCtrl.Visibility = Visibility.Visible;
|
|
tbBuyerOrderReadCtrl.Visibility = Visibility.Visible;
|
|
pddBuyerSelectCtrl.Visibility = Visibility.Visible;
|
|
Task.Run(() =>
|
|
{
|
|
GetServerShop();
|
|
StartTicketRealtimeMonitor();//启动工单监控
|
|
GetShopSupplier(GlobalConfig.ShopLoginList.ToList());
|
|
});
|
|
Task.Run(() =>
|
|
{
|
|
GetPddBuyer();
|
|
GetTaobaoBuyer();
|
|
});
|
|
}
|
|
}
|
|
protected virtual void OnPropertyChanged(string propertyName)
|
|
{
|
|
if (this.PropertyChanged != null)//有改变
|
|
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
|
|
}
|
|
|
|
#region 反抓包功能
|
|
private void AutoAntiGrabbingMechanism()
|
|
{
|
|
while (true)
|
|
{
|
|
#if DEBUG
|
|
#else
|
|
AntiGrabbingMechanism();
|
|
#endif
|
|
try { Thread.Sleep(3000); } catch { }
|
|
}
|
|
}
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static extern bool IsWow64Process([In] IntPtr process, [Out] out bool wow64Process);
|
|
private List<string> _AntiProcesses = "WINRAR,WIRESHARK,FIDDLER,HTTPDEBUGGERPRO,IEHTTPANALYZER,CHARLES,HTTPWATCH,SMARTSNIFF,MINISNIFFER,PROXIFIER,HTTP ANALYZER,SNIFFER,WSOCKEXPERT,IPANALYSE,ANALYZER,HTTP ANALYZER STAND-ALONE EDITION".Split(',').ToList();
|
|
private void AntiGrabbingMechanism()
|
|
{
|
|
//Gate 1 - Anti Proxy
|
|
if (IsUseSystemProxy())
|
|
{
|
|
LockUserAndKillProcess();
|
|
}
|
|
|
|
//Gate 2 - Anti Special Processes
|
|
System.Diagnostics.Process[] processList = System.Diagnostics.Process.GetProcesses();
|
|
foreach (System.Diagnostics.Process process in processList)
|
|
{
|
|
try
|
|
{
|
|
if (_AntiProcesses.Contains(process.ProcessName.ToUpper()))
|
|
{
|
|
process.Kill();
|
|
LockUserAndKillProcess();
|
|
}
|
|
|
|
if (process.MainWindowTitle.Contains("正在捕获"))
|
|
{
|
|
process.Kill();
|
|
LockUserAndKillProcess();
|
|
}
|
|
|
|
if (!IsWin23App(process))
|
|
{
|
|
continue;
|
|
}
|
|
if (process.MainModule?.FileVersionInfo.FileDescription != null)
|
|
{
|
|
foreach (string antiProcess in _AntiProcesses)
|
|
{
|
|
if (process.MainModule.FileVersionInfo.FileDescription.ToUpper().Contains(antiProcess))
|
|
{
|
|
process.Kill();
|
|
LockUserAndKillProcess();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LockUserAndKillProcess()
|
|
{
|
|
string url = BaseClass.BuildObjString("user&act=add_user_lock");
|
|
string data = UserLogin.GetSignaturex("", "");
|
|
string html = GetHtml.PostUtf8(url, data);
|
|
Process.GetCurrentProcess().Kill();
|
|
}
|
|
public static bool IsUseSystemProxy()
|
|
{
|
|
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
|
|
IWebProxy systemWebProxy = WebRequest.GetSystemWebProxy();
|
|
FieldInfo field1 = systemWebProxy.GetType().GetField("webProxy", bindingAttr);
|
|
if (field1 != (FieldInfo)null)
|
|
{
|
|
WebProxy webProxy = field1.GetValue((object)systemWebProxy) as WebProxy;
|
|
FieldInfo field2 = webProxy.GetType().GetField("_ProxyHostAddresses", bindingAttr);
|
|
if (field2 != (FieldInfo)null)
|
|
{
|
|
Hashtable hashtable = field2.GetValue((object)webProxy) as Hashtable;
|
|
if (hashtable != null && hashtable.Count > 0)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool IsWin23App(Process process)
|
|
{
|
|
if (Environment.Is64BitOperatingSystem)
|
|
{
|
|
IntPtr processHandle;
|
|
bool retVal;
|
|
|
|
try
|
|
{
|
|
processHandle = Process.GetProcessById(process.Id).Handle;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
return IsWow64Process(processHandle, out retVal) && retVal;
|
|
}
|
|
return true;
|
|
}
|
|
#endregion
|
|
|
|
private void BaseWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
|
{
|
|
if (BaseMsgWindow.ShowConfirm("是否关闭软件?", "退出微信小店订单管理").DialogResult == true)
|
|
Process.GetCurrentProcess().Kill();
|
|
else
|
|
e.Cancel = true;
|
|
}
|
|
|
|
#region 读取微信店铺
|
|
public bool isReadShop { get; set; } = false;
|
|
public bool hasReadShop { get; set; } = false;
|
|
public void GetServerShop()
|
|
{
|
|
if (isReadShop)
|
|
return;
|
|
|
|
var tList = new ConcurrentList<Task>();
|
|
List<ShopLoginInfo> list = new List<ShopLoginInfo>();
|
|
List<ShopLoginInfo> listTmp = new List<ShopLoginInfo>();
|
|
//Dispatcher.Invoke(new Action(() =>
|
|
//{
|
|
//}));
|
|
isReadShop = true;
|
|
int page = 0;
|
|
while (true)
|
|
{
|
|
Thread.Sleep(1);
|
|
|
|
page++;
|
|
var url = BaseClass.Build29WxObjString("shop/get_shop_list");
|
|
var data = UserLogin.GetSignaturex() + "&page=" + page + "&page_size=100";
|
|
data += "&is_get_erp_shop_id=true";
|
|
var html = GetHtml.PostUtf8(url, data);
|
|
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
|
|
html = GetHtml.PostUtf8(url, data);
|
|
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
|
|
html = GetHtml.PostUtf8(url, data);
|
|
if (string.IsNullOrEmpty(html)
|
|
|| !html.Contains("shop_id") || !html.Contains("shop_account") || !html.Contains("login_pass"))
|
|
{
|
|
break;
|
|
}
|
|
|
|
var jArr = JObject.Parse(html)["data"];
|
|
if (jArr.Count() == 0)
|
|
break;
|
|
|
|
foreach (JObject jObj in jArr)
|
|
{
|
|
var shop = ShopBLL.DeserializationShop(jObj);
|
|
|
|
var shopExist = list.LastOrDefault(l => l.ShopId == shop.ShopId);
|
|
while (shopExist != null)
|
|
{
|
|
shop.Is29Supplier = shopExist.Is29Supplier;
|
|
shop.IsSelect = shopExist.IsSelect;
|
|
shop.IsFilter = shopExist.IsFilter;
|
|
list.Remove(shopExist);
|
|
shopExist = list.LastOrDefault(l => l.ShopId == shop.ShopId);
|
|
}
|
|
list.Add(shop);
|
|
|
|
if (!listTmp.Any(s => s.ShopId == shop.ShopId && !shop.is_point_shop_expire))
|
|
{
|
|
listTmp.Add(shop);
|
|
|
|
Task.Run(() =>
|
|
{
|
|
while (tList.Count > 20)
|
|
{
|
|
tList.RemoveAll(ta => ta.IsFaulted || ta.IsCompleted || ta.IsCanceled);
|
|
Thread.Sleep(100);
|
|
}
|
|
tList.Add(Task.Run(() =>
|
|
{
|
|
try
|
|
{
|
|
if (shop.LoginStatus == "登录成功")
|
|
{
|
|
shop.Is29Supplier = false;
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
var is29SupplierRst = WxSimOrderSupplierBLL.GetWxSupplierListV2(shop);
|
|
if (!is29SupplierRst.Contains("\"code\":0"))
|
|
is29SupplierRst = WxSimOrderSupplierBLL.GetWxSupplierListV2(shop);
|
|
if (is29SupplierRst.Contains("\"code\":0") && is29SupplierRst.Contains("\"name\":\"29供货商\""))
|
|
{
|
|
shop.Is29Supplier = true;
|
|
break;
|
|
}
|
|
else if (!is29SupplierRst.Contains("\"code\":0"))
|
|
{
|
|
ShopBLL.CheckShopLogin(shop);
|
|
}
|
|
int totalCount = BaseRegex.GetIntJson(ref is29SupplierRst, "totalCount");
|
|
if (i * 20 >= totalCount)
|
|
break;
|
|
}
|
|
|
|
List<oms_wei_order_info> orders;
|
|
lock (_orderLock)
|
|
{
|
|
orders = GlobalConfig.lstFilterOrder.Where(o => o.shop_id.ParseToString() == shop.ErpShopId).ToList();
|
|
}
|
|
foreach (var order in orders)
|
|
{
|
|
// 更新代发管理情况
|
|
foreach (var orderItem in order.orderItems)
|
|
orderItem.UpdateOrderItemBuyButton();
|
|
//Dispatcher.Invoke(new Action(() => { orderItem.UpdateOrderItemBuyButton(); }));
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}));
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
Dispatcher.Invoke(new Action(() =>
|
|
{
|
|
GlobalConfig.ShopLoginList = new AllBase.Util.ObservableCollectionThreadSafe<ShopLoginInfo>(list);
|
|
shopListCtrl.lbxShop.ItemsSource = GlobalConfig.ShopLoginList;
|
|
|
|
foreach (var shop in GlobalConfig.ShopLoginList.Where(s => !list.Any(ss => ss.ShopId == s.ShopId)).ToList())
|
|
{
|
|
GlobalConfig.ShopLoginList.Remove(shop);
|
|
}
|
|
foreach (var shop in GlobalConfig.ShopLoginList.Where(s => s.is_point_shop_expire).ToList())
|
|
{
|
|
GlobalConfig.ShopLoginList.Remove(shop);
|
|
}
|
|
}));
|
|
isReadShop = false;
|
|
hasReadShop = true;
|
|
|
|
Task.Run(() =>
|
|
{
|
|
while (tList.Where(ta => !ta.IsFaulted && !ta.IsCompleted).Count() >= 1)
|
|
{
|
|
tList.RemoveAll(ta => ta.IsFaulted || ta.IsCompleted || ta.IsCanceled); Thread.Sleep(100);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void GetShopSupplier(List<ShopLoginInfo> shops)
|
|
{
|
|
// 同步单代发申请,放在拍单时候做
|
|
while (GlobalConfig.BuyConfig.IsSyncDirectBuyOrderWaybill == false)
|
|
{
|
|
Thread.Sleep(500);
|
|
}
|
|
foreach (var shop in shops)
|
|
{
|
|
var rst = new WxApiBLL().GetShopSupplier(shop);
|
|
try
|
|
{
|
|
var jArr = JsonHelper.JObjectParse(rst)["list"] as JArray;
|
|
// appid "wx7809625286c28f2f" name "百川日用";
|
|
if (jArr.Any(aa => aa["appid"].ParseToString() == "wx7809625286c28f2f" && aa["status"].ParseToInt() == 1))
|
|
//if (rst.Contains("wx7809625286c28f2f") || rst.Contains("百川日用"))
|
|
continue;
|
|
|
|
rst = new WxApiBLL().SetShopSupplier(shop, "wx7809625286c28f2f", "4431685489938137094");
|
|
if (!rst.Contains("\"errcode\":0"))
|
|
{
|
|
//return;
|
|
}
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region 读取拼多多买手号
|
|
public bool isGetPddBuyer = false;
|
|
public bool hasGetPddBuyer = false;
|
|
|
|
/// <summary>
|
|
/// 读取拼多多买手
|
|
/// </summary>
|
|
public void GetPddBuyer()
|
|
{
|
|
if (isGetPddBuyer)
|
|
return;
|
|
|
|
isGetPddBuyer = true;
|
|
//var ids = dgvBuyer.Rows.Cast<DataGridViewRow>().Where(r => r.Cells["colSelect"].Value.ParseToBool() == true).Select(s => s.Cells["colBuyerId"].Value.ParseToString()).ToList();
|
|
//Invoke(new Action(() => { pbLoading.Visible = true; }));
|
|
|
|
try
|
|
{
|
|
var url = BaseClass.Build29PDDObjString("user/get_buyer");
|
|
var data = UserLogin.GetSignaturex();
|
|
data += "&page_size=200";
|
|
|
|
var result = GetHtml.PostUtf8(url, data);
|
|
if (string.IsNullOrEmpty(result) || !result.Contains("\"code\":200"))
|
|
result = GetHtml.PostUtf8(url, data);
|
|
|
|
if (result.Contains("\"code\":200"))
|
|
{
|
|
List<BuyerLoginInfo> loginInfoLst = JsonHelper.DeserializeJsonToList<BuyerLoginInfo>(JsonHelper.JObjectParse(result)["data"].ParseToString());
|
|
|
|
foreach (var buyer in GlobalConfig.PDDBuyerLoginList.Where(bu => !loginInfoLst.Any(b => b.buyer_id == bu.buyer_id)).ToList())
|
|
{
|
|
Dispatcher.Invoke(new Action(() => { GlobalConfig.PDDBuyerLoginList.Remove(buyer); }));
|
|
}
|
|
|
|
foreach (var b in loginInfoLst)
|
|
{
|
|
Dispatcher.Invoke(new Action(() =>
|
|
{
|
|
var buyer = GlobalConfig.PDDBuyerLoginList.FirstOrDefault(bu => bu.buyer_id == b.buyer_id);
|
|
if (buyer == null)
|
|
GlobalConfig.PDDBuyerLoginList.Add(b);
|
|
else
|
|
{
|
|
buyer.add_time = b.add_time;
|
|
buyer.buyer_id = b.buyer_id;
|
|
buyer.buyer_name = b.buyer_name;
|
|
buyer.buyer_nick = b.buyer_nick;
|
|
buyer.cookie = b.cookie;
|
|
buyer.mdy_time = b.mdy_time;
|
|
buyer.notes = b.notes;
|
|
buyer.status = b.status;
|
|
buyer.user_name = b.user_name;
|
|
}
|
|
}));
|
|
}
|
|
|
|
//Invoke(new Action(() =>
|
|
//{
|
|
//dgvBuyer.Rows.Clear();
|
|
//cmbBuyer.Items.Clear();
|
|
//}));
|
|
|
|
foreach (var buyer in GlobalConfig.PDDBuyerLoginList)
|
|
{
|
|
//Invoke(new Action(() =>
|
|
//{
|
|
//BindBuyer(buyer, "", ids);
|
|
//cmbBuyer.Items.Add(buyer.buyer_nick);
|
|
//}));
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
//Invoke(new Action(() =>
|
|
//{
|
|
// pbLoading.Visible = false;
|
|
//}));
|
|
|
|
isGetPddBuyer = false;
|
|
hasGetPddBuyer = true;
|
|
}
|
|
#endregion
|
|
|
|
#region 读取拼多多买手号
|
|
public bool isGetTaobaoBuyer = false;
|
|
public bool hasGetTaobaoBuyer = false;
|
|
|
|
/// <summary>
|
|
/// 读取拼多多买手
|
|
/// </summary>
|
|
public void GetTaobaoBuyer()
|
|
{
|
|
if (isGetTaobaoBuyer)
|
|
return;
|
|
|
|
isGetTaobaoBuyer = true;
|
|
|
|
try
|
|
{
|
|
var url = BaseClass.Build29WxObjString("user/get_taobao_buyer");
|
|
var data = UserLogin.GetSignaturex();
|
|
data += "&page_size=200";
|
|
|
|
var result = GetHtml.PostUtf8(url, data);
|
|
if (string.IsNullOrEmpty(result) || !result.Contains("\"code\":200"))
|
|
result = GetHtml.PostUtf8(url, data);
|
|
|
|
if (result.Contains("\"code\":200"))
|
|
{
|
|
List<BuyerLoginInfo> loginInfoLst = JsonHelper.DeserializeJsonToList<BuyerLoginInfo>(JsonHelper.JObjectParse(result)["data"].ParseToString());
|
|
|
|
foreach (var buyer in GlobalConfig.TaobaoBuyerLoginList.Where(bu => !loginInfoLst.Any(b => b.buyer_id == bu.buyer_id)).ToList())
|
|
{
|
|
Dispatcher.Invoke(new Action(() => { GlobalConfig.TaobaoBuyerLoginList.Remove(buyer); }));
|
|
}
|
|
|
|
foreach (var b in loginInfoLst)
|
|
{
|
|
Dispatcher.Invoke(new Action(() =>
|
|
{
|
|
var buyer = GlobalConfig.TaobaoBuyerLoginList.FirstOrDefault(bu => bu.buyer_id == b.buyer_id);
|
|
if (buyer == null)
|
|
GlobalConfig.TaobaoBuyerLoginList.Add(b);
|
|
else
|
|
{
|
|
buyer.add_time = b.add_time;
|
|
buyer.buyer_id = b.buyer_id;
|
|
buyer.buyer_name = b.buyer_name;
|
|
buyer.buyer_nick = b.buyer_nick;
|
|
buyer.cookie = b.cookie;
|
|
buyer.mdy_time = b.mdy_time;
|
|
buyer.notes = b.notes;
|
|
buyer.status = b.status;
|
|
buyer.user_name = b.user_name;
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
isGetTaobaoBuyer = false;
|
|
hasGetTaobaoBuyer = true;
|
|
}
|
|
#endregion
|
|
|
|
private void lblBalance_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
|
{
|
|
WXGetBalanceQrCodeForm balanceQrCodeForm = new WXGetBalanceQrCodeForm(StartUp.UpdateBalance);
|
|
balanceQrCodeForm.ShowDialog();
|
|
}
|
|
|
|
private void gridPddBuyerOrderReadCtrl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
|
{
|
|
//if (Panel.GetZIndex(MainWindow.Instance.gridPddBuyerOrderReadCtrl) < 1)
|
|
// Panel.SetZIndex(MainWindow.Instance.gridPddBuyerOrderReadCtrl, 1);
|
|
//else
|
|
// Panel.SetZIndex(MainWindow.Instance.gridPddBuyerOrderReadCtrl, -1);
|
|
}
|
|
|
|
private void gridTitle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
if (e.ClickCount == 2)
|
|
{
|
|
// 双击切换窗口状态
|
|
this.WindowState = this.WindowState == WindowState.Maximized
|
|
? WindowState.Normal
|
|
: WindowState.Maximized;
|
|
}
|
|
else if (e.LeftButton == MouseButtonState.Pressed)
|
|
{
|
|
this.DragMove();
|
|
}
|
|
}
|
|
|
|
private void bt_setting(object sender, RoutedEventArgs e)
|
|
{
|
|
SettingsView view = new SettingsView();
|
|
view.ShowDialog();
|
|
|
|
}
|
|
|
|
private void bt_showOrderSupport(object sender, RoutedEventArgs e)
|
|
{
|
|
OpenOrderSupportTicket(_ticketMonitor.LatestNotification);
|
|
_ticketMonitor.MarkAllRead();
|
|
}
|
|
|
|
private void StartTicketRealtimeMonitor()
|
|
{
|
|
try
|
|
{
|
|
var options = GetTicketOptions().Clone();
|
|
_ticketMonitor.Start(options);
|
|
UpdateOrderSupportBadge();
|
|
_ = LoadHistoricalTicketUnreadAsync(options);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
NLogger.Instance.Error("TicketRealtimeStartError:" + ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 启动后根据服务端工单列表和历史缓存补齐未读角标。
|
|
/// </summary>
|
|
private async Task LoadHistoricalTicketUnreadAsync(TicketClientOptions options)
|
|
{
|
|
try
|
|
{
|
|
var unreadByTicket = await _workOrderUnreadService
|
|
.GetUnreadByTicketAsync(options);
|
|
_ticketMonitor.MergeUnread(unreadByTicket);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogSave.Add("TicketUnreadLoadError:" + ex);
|
|
}
|
|
}
|
|
|
|
private TicketClientOptions GetTicketOptions()
|
|
{
|
|
if (_ticketOptions != null)
|
|
return _ticketOptions;
|
|
|
|
_ticketOptions = new TicketClientOptions
|
|
{
|
|
UserName = BaseClass.UserName,
|
|
AppIds = GlobalConfig.ShopLoginList.Select(a => a.ShopId).ToList(),
|
|
Orders = []
|
|
};
|
|
|
|
|
|
|
|
//OrderSupportTicketView
|
|
// .CreateDefaultOptions(BaseClass.UserName)
|
|
// .Clone();
|
|
return _ticketOptions;
|
|
}
|
|
|
|
private void OpenOrderSupportTicket(TicketRealtimeNotification notification)
|
|
{
|
|
var view = EnsureOrderSupportView();
|
|
view.ViewModel.ShowHistory();
|
|
|
|
if (notification != null)
|
|
{
|
|
view.OpenTicket(
|
|
notification.AppId,
|
|
notification.WechatOrderId);
|
|
}
|
|
|
|
// DialogService 会复用同类型的已打开窗口,避免重复创建。
|
|
DialogService.ShowOrActivateWindow(view);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从订单行打开工单页面。若左侧列表已有相同订单号的工单,直接定位到该工单;
|
|
/// 否则在同一个工单页面中进入新建工单状态。
|
|
/// </summary>
|
|
public async Task CreateOrderSupportTicketAsync(TicketOrderOption order)
|
|
{
|
|
if (order == null)
|
|
return;
|
|
|
|
var view = EnsureOrderSupportView();
|
|
await view.ViewModel.InitializeAsync();
|
|
|
|
var existing = view.ViewModel.FindTicketByOrderId(order.OrderId);
|
|
if (existing != null)
|
|
{
|
|
view.ViewModel.ApplyOrderInfo(order);
|
|
view.OpenTicket(existing.AppId, existing.WechatOrderId);
|
|
}
|
|
else
|
|
{
|
|
view.OpenNewTicket(order);
|
|
}
|
|
|
|
DialogService.ShowOrActivateWindow(view);
|
|
}
|
|
|
|
private OrderSupportTicketView EnsureOrderSupportView()
|
|
{
|
|
if (_orderSupportView == null)
|
|
{
|
|
_orderSupportView = new OrderSupportTicketView(
|
|
new TicketService(
|
|
new TicketApiService(),
|
|
_ticketMonitor.RealtimeService,
|
|
ownsRealtime: false),
|
|
GetTicketOptions().Clone());
|
|
}
|
|
|
|
return _orderSupportView;
|
|
}
|
|
|
|
private void OnTicketNewMessageReceived(
|
|
object sender,
|
|
TicketInboxMessageEventArgs e)
|
|
{
|
|
if (!Dispatcher.CheckAccess())
|
|
{
|
|
Dispatcher.BeginInvoke(new Action(
|
|
() => OnTicketNewMessageReceived(sender, e)));
|
|
return;
|
|
}
|
|
|
|
var notification = e?.Notification;
|
|
if (notification == null)
|
|
return;
|
|
|
|
UpdateOrderSupportBadge();
|
|
}
|
|
|
|
private void OnTicketUnreadCountChanged(
|
|
object sender,
|
|
TicketUnreadCountChangedEventArgs e)
|
|
{
|
|
if (!Dispatcher.CheckAccess())
|
|
{
|
|
Dispatcher.BeginInvoke(new Action(
|
|
() => OnTicketUnreadCountChanged(sender, e)));
|
|
return;
|
|
}
|
|
UpdateOrderSupportBadge(e?.UnreadCount ?? 0);
|
|
}
|
|
|
|
private void UpdateOrderSupportBadge()
|
|
{
|
|
UpdateOrderSupportBadge(_ticketMonitor.UnreadCount);
|
|
}
|
|
|
|
private void UpdateOrderSupportBadge(int unreadCount)
|
|
{
|
|
if (borderOrderSupportUnread == null)
|
|
return;
|
|
this.Dispatcher.Invoke(() =>
|
|
{
|
|
borderOrderSupportUnread.Visibility = unreadCount > 0
|
|
? Visibility.Visible
|
|
: Visibility.Collapsed;
|
|
tbOrderSupportUnread.Text = unreadCount > 99
|
|
? "99+"
|
|
: unreadCount.ToString();
|
|
btOrderSupport.ToolTip = unreadCount > 0
|
|
? $"客户工单({unreadCount} 条未读消息)"
|
|
: "客户工单";
|
|
});
|
|
}
|
|
|
|
private void MainWindow_Closed(object sender, EventArgs e)
|
|
{
|
|
_ticketMonitor.NewMessageReceived -= OnTicketNewMessageReceived;
|
|
_ticketMonitor.UnreadCountChanged -= OnTicketUnreadCountChanged;
|
|
}
|
|
}
|
|
}
|