主页增加发票助手
This commit is contained in:
1 parent
5456e6611d
commit
a15f97ac2e
22 files changed
+3825
-309
No files matched your search
@@ -0,0 +1,250 @@
|
||||
using _29WxOrderWpf.CefHelper;
|
||||
using _29WxOrderWpf.Commands;
|
||||
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 WxOrder.Framework.Helpers;
|
||||
|
||||
namespace _29WxOrderWpf.Ctrls.PDDInvoice.ViewModels;
|
||||
|
||||
public partial class PDDInvoiceViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单列表浏览器
|
||||
/// </summary>
|
||||
public ChromiumWebBrowser Browser { get; private set; }
|
||||
/// <summary>
|
||||
/// 内容浏览器
|
||||
/// 订单详情
|
||||
/// 发票详情
|
||||
/// 申请发票
|
||||
/// </summary>
|
||||
public ChromiumWebBrowser BrowserDetail { get; private set; }
|
||||
|
||||
partial void InitBrowser()
|
||||
{
|
||||
BrowserZIndex = -1;
|
||||
BrowserDetailZIndex = -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;
|
||||
|
||||
BrowserDetail = WPFCEFBrowser.CreateChromiumWebBrowser("about:blank", false);
|
||||
LocalResourceRequestHandler detailResourceRequestHandler = new LocalResourceRequestHandler();
|
||||
detailResourceRequestHandler.ResourceLoadCompleteEvent += DetailRequestHandler_ResourceLoadComplete;
|
||||
BrowserDetail.RequestHandler = new LocalRequestHandler(resourceRequestHandler);
|
||||
BrowserDetail.LifeSpanHandler = new LocalLifeSpanHandler(PopWindowType.SelfWindow);
|
||||
BrowserDetail.KeyboardHandler = new KeyboardHandler();
|
||||
BrowserDetail.LoadingStateChanged += BrowserDetail_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"))
|
||||
{
|
||||
StartAutoScroll();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void BrowserDetail_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/transac_return_compensation.html"))
|
||||
{
|
||||
string html = await b.GetBrowser().GetSourceAsync();
|
||||
if (html.Contains("window.rawData"))
|
||||
{
|
||||
await ExecuteInvoiceApplyScriptAsync(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 页面异常(未渲染出发票表单)时直接判定失败,避免批量开票长时间等待
|
||||
_currentInvoiceTcs?.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注入发票填写脚本并执行。
|
||||
/// 单张申请模式保持原有行为;批量开票模式下轮询脚本写入的
|
||||
/// <c>window.__invoiceApplyResult</c>,完成后通过 <see cref="_currentInvoiceTcs"/> 回传结果。
|
||||
/// </summary>
|
||||
private async Task ExecuteInvoiceApplyScriptAsync(ChromiumWebBrowser b)
|
||||
{
|
||||
string content = ResourceHelper.GetResourceText("/Ctrls/PDDInvoice/Resources/invoice.js", "29WxFindOrder");
|
||||
content = content.Replace("{公司}", InvoiceTitle);
|
||||
content = content.Replace("{税号}", TaxNo);
|
||||
if (string.IsNullOrEmpty(content)) return;
|
||||
|
||||
await b.EvaluateScriptAsync(content);
|
||||
|
||||
if (_currentInvoiceTcs == null) return; // 单张申请模式:保持原有行为
|
||||
|
||||
// 批量模式:等待异步脚本执行完成
|
||||
// 捕获当前 TCS,避免批量循环超时进入下一个订单后,迟到的轮询误触发新订单的结果
|
||||
var tcs = _currentInvoiceTcs;
|
||||
for (int i = 0; i < 120; i++)
|
||||
{
|
||||
await Task.Delay(500);
|
||||
try
|
||||
{
|
||||
var res = await b.EvaluateScriptAsync("window.__invoiceApplyResult");
|
||||
if (res.Success && res.Result != null)
|
||||
{
|
||||
tcs.TrySetResult(Convert.ToBoolean(res.Result));
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
tcs.TrySetResult(false);
|
||||
}
|
||||
|
||||
public ICommand CloseInvoiceDetailCommand => new DelegateCommand(HidenOrderBrowserDetail);
|
||||
|
||||
public int BrowserZIndex
|
||||
{
|
||||
get => GetValue<int>();
|
||||
set => SetValue(value);
|
||||
}
|
||||
public int BrowserDetailZIndex
|
||||
{
|
||||
get => GetValue<int>();
|
||||
set => SetValue(value);
|
||||
}
|
||||
/// <summary>
|
||||
/// 显示主浏览器
|
||||
/// </summary>
|
||||
public void ShowOrderBrowser()
|
||||
{
|
||||
BrowserZIndex = 10;
|
||||
BrowserDetailZIndex = -1;
|
||||
}
|
||||
/// <summary>
|
||||
/// 显示子浏览器
|
||||
/// </summary>
|
||||
public void ShowOrderBrowserDetail()
|
||||
{
|
||||
BrowserZIndex = -1;
|
||||
BrowserDetailZIndex = 10;
|
||||
}
|
||||
public void HidenOrderBrowser()
|
||||
{
|
||||
BrowserZIndex = -1;
|
||||
}
|
||||
public void HidenOrderBrowserDetail()
|
||||
{
|
||||
BrowserDetailZIndex = -1;
|
||||
}
|
||||
public bool IsReadOrder
|
||||
{
|
||||
get => GetValue<bool>();
|
||||
set => SetValue(value);
|
||||
}
|
||||
private int top = 0;
|
||||
private DateTime lastGetOrderDataTime = DateTime.Now;
|
||||
private void RequestHandler_ResourceLoadComplete(object sender, string url, string postData, string responseData, IRequest request)
|
||||
{
|
||||
if (url.StartsWith("https://mobile.yangkeduo.com/orders.html"))
|
||||
{
|
||||
//if (isAutoScroll == false)
|
||||
//{
|
||||
// StartAutoScroll();
|
||||
//}
|
||||
|
||||
StartAutoScroll();
|
||||
}
|
||||
if (url.StartsWith("https://mobile.yangkeduo.com/proxy/api/api/aristotle/order_list_v"))
|
||||
{
|
||||
lastGetOrderDataTime = DateTime.Now;
|
||||
parserData(responseData);
|
||||
|
||||
//File.WriteAllText(@$"E:\{Guid.NewGuid().ToString()}.txt", responseData);
|
||||
}
|
||||
}
|
||||
public void StartAutoScroll()
|
||||
{
|
||||
if (IsReadOrder) return;
|
||||
|
||||
IsReadOrder = true;
|
||||
_ = autoScroll(_cancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
// 停止滚动
|
||||
public void StopAutoScroll()
|
||||
{
|
||||
IsReadOrder = false;
|
||||
_cancellationTokenSource?.Cancel();
|
||||
_cancellationTokenSource?.Dispose();
|
||||
_cancellationTokenSource = null;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void DetailRequestHandler_ResourceLoadComplete(object sender, string url, string postData, string responseData, IRequest request)
|
||||
{
|
||||
if (url.StartsWith("https://mobile.yangkeduo.com/transac_return_compensation.html"))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user