Files

217 lines
5.7 KiB
C#

using _29WxOrderWpf.CefHelper;
using WxOrder.Framework.Commons;
using AllBase;
using CefSharp;
using CefSharp.Handler;
using CefSharp.Wpf;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Work._29Tools.CefTools;
using Work.BaseForms;
using WxOrder.Framework.Helpers;
namespace _29WxOrderWpf.Ctrls.PDDInvoice.ViewModels;
public partial class PDDInvoiceViewModel
{
/// <summary>
/// 订单列表浏览器
/// </summary>
public ChromiumWebBrowser Browser { get; private set; }
private IFrame frame;
partial void InitBrowser()
{
BrowserZIndex = -1;
Browser = WPFCEFBrowser.CreateChromiumWebBrowser("about:blank", false);
LocalResourceRequestHandler resourceRequestHandler = new LocalResourceRequestHandler();
//resourceRequestHandler.BeforeResourceLoadEvent += RequestHandler_BeforeResourceLoad;
resourceRequestHandler.ResourceLoadCompleteEvent += RequestHandler_ResourceLoadComplete;
Browser.RequestHandler = new LocalRequestHandler(resourceRequestHandler);
Browser.LifeSpanHandler = new LocalLifeSpanHandler(PopWindowType.SelfWindow);
Browser.KeyboardHandler = new KeyboardHandler();
Browser.LoadingStateChanged += Browser_LoadingStateChanged;
}
private void Browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e)
{
if (e.IsLoading == false)
{
var b = (ChromiumWebBrowser)sender;
b.Dispatcher.InvokeAsync(async () =>
{
if (b.Address != null && b.Address.StartsWith("https://mobile.yangkeduo.com/orders.html"))//加载完成 加载 js
{
frame = b.GetMainFrame();
string content = ResourceHelper.GetResourceText("/Ctrls/PDDInvoice/Resources/order.js", "29WxFindOrder");
if (string.IsNullOrEmpty(content)) return;
Install(frame, content);
if (await IsInstalledAsync(frame))
{
StartAutoScroll();
//await b.EvaluateScriptAsync(frame, content);
}
else
{
BaseMsgForm.ShowError("订单读取失败");
}
}
});
}
}
public ICommand CloseInvoiceDetailCommand => new DelegateCommand(HidenOrderBrowserDetail);
public int BrowserZIndex
{
get => GetValue<int>();
set => SetValue(value);
}
/// <summary>
/// 显示主浏览器
/// </summary>
public void ShowOrderBrowser()
{
BrowserZIndex = 10;
BrowserDetailZIndex = -1;
}
public void HidenOrderBrowser()
{
BrowserZIndex = -1;
}
public bool IsReadOrder
{
get => GetValue<bool>();
set => SetValue(value);
}
private int top = 0;
private DateTime lastGetOrderDataTime = DateTime.Now;
private string lastOrderSN = "0";
private void RequestHandler_ResourceLoadComplete(object sender, string url, string postData, string responseData, IRequest request)
{
if (url.StartsWith("https://mobile.yangkeduo.com/proxy/api/api/aristotle/order_list_v"))
{
lastGetOrderDataTime = DateTime.Now;
parserData(responseData, out lastOrderSN);
Debug.WriteLine($"LastOrder:{lastOrderSN}");
//File.WriteAllText(@$"E:\{Guid.NewGuid().ToString()}.txt", responseData);
}
}
public void StartAutoScroll()
{
if (frame == null)
{
StopAutoScroll(); return;
}
if (IsReadOrder) return;
IsReadOrder = true;
//_ = autoScroll(_cancellationTokenSource.Token);
_ = autoLoadOrderData(_cancellationTokenSource.Token);
}
// 停止滚动
public void StopAutoScroll()
{
IsReadOrder = false;
_cancellationTokenSource?.Cancel();
Application.Current?.Dispatcher.BeginInvoke(new Action(() =>
{
BottomMsg = $"订单读取结束";
}));
CompleteProgress();
}
private async Task autoLoadOrderData(CancellationToken token)
{
string templastOrderSN = "";
while (IsReadOrder && !token.IsCancellationRequested)
{
if (lastOrderSN == templastOrderSN)
{
await Task.Delay(500);
continue;
}
string jsStr = $"PDDOrders.trigger({{offset:'MO-01-{lastOrderSN}',type:0,size:10,mode:'store'}})";
templastOrderSN = lastOrderSN;
await frame.EvaluateScriptAsync(jsStr);
await Task.Delay(Randomx.GetId(1000, 3000));
//Thread.Sleep();
}
}
/// <summary>文档创建时注入(每个 document 注入一次即可,脚本本身幂等)</summary>
public void Install(IFrame frame, string hookJs)
{
if (frame == null || string.IsNullOrEmpty(hookJs)) return;
frame.ExecuteJavaScriptAsync(hookJs);
}
/// <summary>脚本是否已就绪(注入后自检用;异步,不会卡 UI 线程)</summary>
public async Task<bool> IsInstalledAsync(IFrame frame, int timeoutMs = 3000)
{
var deadline = DateTime.Now.AddMilliseconds(timeoutMs);
while (DateTime.Now < deadline)
{
var r = await frame.EvaluateScriptAsync("!!(window.PDDOrders && window.PDDOrders.__installed)")
.ConfigureAwait(false);
if (r != null && r.Success && r.Result is bool && (bool)r.Result) return true;
await Task.Delay(100).ConfigureAwait(false);
}
return false;
}
//private async Task autoScroll(CancellationToken token)
//{
// while (IsReadOrder && !token.IsCancellationRequested)
// {
// if ((DateTime.Now - lastGetOrderDataTime).Seconds > 30) StopAutoScroll();
// top += Randomx.GetId(450, 600);
// var jsStr = @"window.scroll({
// top: " + top + @",
// left: 0,
// behavior: 'smooth' // 可选,使滚动平滑
// });";
// var client = Browser.GetDevToolsClient();
// if (client != null)
// {
// var result = client.Runtime.EvaluateAsync(jsStr, null, true, null, null, true, null, true);
// result.Wait(5000);
// }
// await Task.Delay(Randomx.GetId(100, 300));
// //Thread.Sleep();
// }
//}
}