diff --git a/29WxOrder.sln b/29WxOrder.sln
index d2c7bd8..cbb0fa1 100644
--- a/29WxOrder.sln
+++ b/29WxOrder.sln
@@ -21,6 +21,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_SolutionItems", "_Solution
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WxOrder.Framework", "WxOrder.Framework\WxOrder.Framework.csproj", "{3123963C-A0EC-4AD5-9916-DC063F73490B}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".test", ".test", "{14261B9B-E3EA-4BC0-B08D-4B3591AC13E5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WXOrder.Test", "test\WXOrder.Test\WXOrder.Test.csproj", "{3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -97,6 +101,22 @@ Global
{3123963C-A0EC-4AD5-9916-DC063F73490B}.Release|x64.Build.0 = Release|Any CPU
{3123963C-A0EC-4AD5-9916-DC063F73490B}.Release|x86.ActiveCfg = Release|Any CPU
{3123963C-A0EC-4AD5-9916-DC063F73490B}.Release|x86.Build.0 = Release|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Debug|x64.Build.0 = Debug|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Debug|x86.Build.0 = Debug|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Release|x64.ActiveCfg = Release|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Release|x64.Build.0 = Release|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Release|x86.ActiveCfg = Release|Any CPU
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -105,6 +125,7 @@ Global
{6461D807-B1C8-45F0-B388-E0CA1A418DE0} = {4A54DC2A-B47C-4ED1-A482-EE60161DB2C3}
{1AD45D66-6872-4522-ACF0-04E2C0514048} = {4A54DC2A-B47C-4ED1-A482-EE60161DB2C3}
{5A410EB5-06AD-97BB-2314-9D7A808E12F7} = {1A7830FA-AC8F-40FB-A232-F0626812B8BE}
+ {3790EC79-EA1D-4660-AB0D-EA0DE4FF77B7} = {14261B9B-E3EA-4BC0-B08D-4B3591AC13E5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {38687A61-0347-49AC-98C7-E7F7148C0234}
diff --git a/29WxOrderWpf/Converters/OrderTaskStatusConverter.cs b/29WxOrderWpf/Converters/OrderTaskStatusConverter.cs
new file mode 100644
index 0000000..d852de0
--- /dev/null
+++ b/29WxOrderWpf/Converters/OrderTaskStatusConverter.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+using Work.ERP.API;
+
+namespace _29WxOrderWpf.Converters
+{
+ ///
+ /// 订单任务状态转换: (int) → 中文描述。
+ /// 1=执行中,2=已完成,3=已人为中断。
+ ///
+ public class OrderTaskStatusConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is int status)
+ {
+ switch ((TaskStatus)status)
+ {
+ case TaskStatus.Executing:
+ return "执行中";
+ case TaskStatus.Completed:
+ return "已完成";
+ case TaskStatus.ManuallyInterrupted:
+ return "已中断";
+ }
+ }
+ return value?.ToString() ?? string.Empty;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml b/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml
index f6c080a..381a983 100644
--- a/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml
+++ b/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml
@@ -1,1191 +1,1209 @@
+ x:Class="_29WxOrderWpf.Ctrls.OrderCtrls.OrderListCtrl"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:c="clr-namespace:_29WxOrderWpf.Common"
+ xmlns:converters="clr-namespace:_29WxOrderWpf.Converters"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:local="clr-namespace:_29WxOrderWpf.Ctrls.OrderCtrls"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:usercontrols="clr-namespace:_29WxOrderWpf.UserControls"
+ xmlns:utils="clr-namespace:_29WxOrderWpf.Utils"
+ xmlns:wpf="WPFCommon"
+ d:DesignHeight="450"
+ d:DesignWidth="1560"
+ Loaded="Window_Loaded"
+ mc:Ignorable="d">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
- 标题包含
-
-
- 标题不含
-
-
-
-
+
+
+
+
+ 标题包含
+
+
+ 标题不含
+
+
+
+
-
-
+
+
-
-
-
-
- 更新时间
-
-
- 成交时间
-
-
+
+
+
+
+ 更新时间
+
+
+ 成交时间
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 店铺备注包含
-
-
- 软件备注包含
-
-
- 店铺备注不含
-
-
- 软件备注不含
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 店铺备注包含
+
+
+ 软件备注包含
+
+
+ 店铺备注不含
+
+
+ 软件备注不含
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml.cs b/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml.cs
index 70b13f0..5ff9fed 100644
--- a/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml.cs
+++ b/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml.cs
@@ -1,4 +1,5 @@
using _29WxOrderWpf.BaseWindows;
+using _29WxOrderWpf.Commands;
using _29WxOrderWpf.Common;
using _29WxOrderWpf.Ctrls.BuyerCtrls;
using _29WxOrderWpf.Ctrls.Statistics;
@@ -1936,25 +1937,36 @@ namespace _29WxOrderWpf.Ctrls.OrderCtrls
int errorCount = 0;
foreach (oms_wei_order_info item in list)
{
- var rst = await WxApiBLL.WxSearchAndDropshipCancelAsync(item.Shop, item);
- if (rst == "success")
+ try
{
- var ret = await _shipGiftService.Send(item.order_id, giftType);
- if (ret)
+ var rst = await WxApiBLL.WxSearchAndDropshipCancelAsync(item.Shop, item);
+ if (rst == "success")
{
- sucessCount++;
- item.gift_order_status = 1;
- this.FilterOneOrder(item, true);
+ var ret = await _shipGiftService.Send(item.order_id, giftType);
+ if (ret)
+ {
+ sucessCount++;
+ item.gift_order_status = 1;
+ this.FilterOneOrder(item, true);
+ }
+ else
+ {
+ errorCount++;
+ }
}
else
{
errorCount++;
}
}
- else
+ catch (Exception ex)
{
errorCount++;
}
+ finally
+ {
+ item.IsSelect = false;
+ }
SetProgress(index, count);
BottomMsg = $"礼品单发送进度:{index}/{count}\t\t{item.orderItems.FirstOrDefault()?.title ?? ""}";
@@ -1972,6 +1984,181 @@ namespace _29WxOrderWpf.Ctrls.OrderCtrls
}
}
+
+ ///
+ /// 拉取微信订单到任务列表
+ ///
+ public ICommand PullWXOrderCommand => new AsyncDelegateCommand(PullWXOrder);
+
+ private async Task PullWXOrder()
+ {
+ try
+ {
+ var isAfterSales = GlobalConfig.OrderTabHeaderStr.StartsWith("需处理售后单");//是否售后
+
+ var selectedShops = GlobalConfig.ShopLoginList.Where(a => a.IsSelect).ToList();
+ if (selectedShops.Count == 0)
+ {
+ selectedShops = GlobalConfig.ShopLoginList.ToList();
+ }
+
+ var selectedOrders = GlobalConfig.lstFilterOrder.Where(a => a.IsSelect).ToList();
+ int count = selectedOrders.Count;
+ if (count > 0 && isAfterSales == false)//非售后订单
+ {
+ if (BaseMsgWindow.ShowConfirm($"已选取:{count}个订单", "同步订单", MainWindow.Instance, MsgWindowLevel.MEDIUM).DialogResult == false) return;
+ BottomMsg = $"订单同步进度....";
+ int index = 1;
+ int sucessCount = 0;
+ int errorCount = 0;
+ foreach (var item in selectedOrders)
+ {
+ var ret = await PullWXOrderService.Instance.PullOrderDetailAsync(item.shop_id, item.order_id); ;
+ if (ret)
+ {
+ sucessCount++;
+ this.GetOrder(item.order_id);
+ SetProgress(index, count);
+ item.IsSelect = false;
+ }
+ else
+ {
+ errorCount++;
+ }
+ BottomMsg = $"订单同步进度:{index}/{count}\t\t{item.orderItems.FirstOrDefault()?.title ?? ""}";
+ index++;
+ }
+ BottomMsg = $"订单同步进度完成 成功:{sucessCount} 失败:{errorCount} 总数:{count}";
+ }
+ else if (count > 0 && isAfterSales == true)//售后订单
+ {
+ if (BaseMsgWindow.ShowConfirm($"已选取:{count}个售后订单", "同步订单", MainWindow.Instance, MsgWindowLevel.MEDIUM).DialogResult == false) return;
+ //var dictionaryResult = selectedOrders
+ // .Where(o => o?.refundItems != null)
+ // .SelectMany(o => o.refundItems
+ // .Where(item => item != null)
+ // .Select(item => new { o.shop_id, item.after_sale_order_id }))
+ // .GroupBy(x => x.shop_id)
+ // .ToDictionary(
+ // g => g.Key,
+ // g => g.Select(x => x.after_sale_order_id).ToArray()
+ // );
+
+
+ //BottomMsg = $"售后订单同步进度....";
+ //foreach (var item in dictionaryResult)
+ //{
+ // var ret = await PullWXOrderService.Instance.PullAfterSaleOrdersAsync(item.Key, item.Value);
+ //}
+ //BottomMsg = $"售后同步任务已发送,等待同步完成";
+
+
+
+ int index = 1;
+ int sucessCount = 0;
+ int errorCount = 0;
+ BottomMsg = $"售后订单同步进度....";
+ foreach (KeyValuePair> item in selectedOrders.GroupBy(a => a.shop_id).ToDictionary(a => a.Key, a => a.ToList()))
+ {
+ long shopid = item.Key;
+ string shopName = item.Value.FirstOrDefault()?.shop_name ?? "";
+ string[] afterSaleOrderIds = item.Value.SelectMany(a => a.refundItems).Where(a => a != null).Select(a => a.after_sale_order_id).ToArray();
+ var ret = await PullWXOrderService.Instance.PullAfterSaleOrdersAsync(shopid, afterSaleOrderIds);
+ if (ret)
+ {
+ sucessCount++;
+ SetProgress(index, count);
+ item.Value.ForEach(a => a.IsSelect = false);
+ }
+ else
+ {
+ errorCount++;
+ }
+ BottomMsg = $"售后订单同步进度:{index}/{count}\t\t{shopName}";
+ index++;
+
+ }
+ BottomMsg = $"售后同步任务已发送,等待同步完成";
+ }
+ else
+ {
+ count = selectedShops.Count;
+ string prefix = $"已选取:{count}个商铺";
+ if (count == GlobalConfig.ShopLoginList.Count)
+ {
+ prefix = "已选取全部商铺";
+ }
+
+
+ var startTime = dateStart.SelectedDate.Value;
+ var endTime = dateEnd.SelectedDate.Value;
+
+ string msg = "";
+ if (isAfterSales)
+ {
+ msg = $"{prefix}";
+ }
+ else
+ {
+ msg = $"{prefix}\n\n时间范围:{startTime.ToString("yyyy-MM-dd")}-{endTime.ToString("yyyy-MM-dd")}";
+ }
+
+ if (BaseMsgWindow.ShowConfirm(msg, $"{(isAfterSales ? "售后" : "")}同步订单", MainWindow.Instance, MsgWindowLevel.MEDIUM).DialogResult == false) return;
+
+ if ((endTime - startTime).Days > 7)
+ {
+ throw new Exception("时间范围最大7天");
+ }
+
+ var ret = false;
+ if (isAfterSales)
+ {
+ ret = await PullWXOrderService.Instance.PullRefundOrderByShopsAsync(selectedShops.Select(a => a.ErpShopId.ParseToLong()).ToArray(), startTime, endTime);
+ }
+ else
+ {
+ ret = await PullWXOrderService.Instance.PullOrderByShopIdsAndTimeRangeAsync(selectedShops.Select(a => a.ErpShopId.ParseToLong()).ToArray(), startTime, endTime);
+ }
+ if (ret)
+ {
+ BaseMsgWindow.ShowInfo("同步任务已发送,等待同步完成\n任务详情查看任务列表");
+ }
+ else
+ {
+ BaseMsgWindow.ShowError("同步任务失败");
+ }
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ BaseMsgWindow.ShowError("同步订单失败\n" + ex.Message, "Error");
+ }
+ //var service = PullWXOrderService.Instance;
+ //foreach (var item in list)
+ //{
+ // await service.PullOrderDetailAsync(item.shop_id, item.order_id);
+ //}
+ }
+
+ private DialogWindow _taskDialog;
+ public ICommand ShowTaskDialogViewCommand => new DelegateCommand(ShowTaskDialogView);
+
+ private void ShowTaskDialogView()
+ {
+ if (_taskDialog == null)
+ {
+ _taskDialog = new DialogWindow()
+ {
+ Title = "任务列表",
+ Content = new OrderTaskDialogView(),
+
+ };
+ _taskDialog.Closed += (s, e) => _taskDialog = null;
+ }
+ _taskDialog.Show();
+ }
}
public class OrderFilterConfig
diff --git a/29WxOrderWpf/Ctrls/OrderCtrls/OrderTaskDialogView.xaml b/29WxOrderWpf/Ctrls/OrderCtrls/OrderTaskDialogView.xaml
new file mode 100644
index 0000000..309113b
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/OrderCtrls/OrderTaskDialogView.xaml
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/29WxOrderWpf/Ctrls/OrderCtrls/OrderTaskDialogView.xaml.cs b/29WxOrderWpf/Ctrls/OrderCtrls/OrderTaskDialogView.xaml.cs
new file mode 100644
index 0000000..d211e2a
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/OrderCtrls/OrderTaskDialogView.xaml.cs
@@ -0,0 +1,185 @@
+using _29WxOrderWpf.Commands;
+using _29WxOrderWpf.Services;
+using AllBase.Model.MvvmBaseClasses;
+using AllBase.Util;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Timers;
+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.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using System.Windows.Threading;
+using Work.KJDServer.API.Models;
+using WPFCommon.Models;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;
+
+namespace _29WxOrderWpf.Ctrls.OrderCtrls;
+
+///
+/// OrderTaskDialogView.xaml 的交互逻辑
+///
+public partial class OrderTaskDialogView : UserControl
+{
+ private readonly OrderTaskDialogViewModel _viewModel;
+
+ public OrderTaskDialogView()
+ {
+ InitializeComponent();
+ this.Loaded += OrderTaskDialogView_Loaded;
+ _viewModel = new OrderTaskDialogViewModel();
+ DataContext = _viewModel;
+ }
+
+ private async void OrderTaskDialogView_Loaded(object sender, RoutedEventArgs e)
+ {
+ await _viewModel.LoadTasks();
+ }
+}
+
+///
+/// 任务列表 - ViewModel
+///
+public class OrderTaskDialogViewModel : BindableBaseEx, IDisposable
+{
+ private DispatcherTimer _timer;
+ private const int RefreshIntervals = 10;
+ private int _timeCount = 0;
+ private readonly PullWXOrderService _service;
+ private readonly NotifyCollectionChangedEventHandler _collectionChangedHandler;
+
+
+ public OrderTaskDialogViewModel()
+ : this(PullWXOrderService.Instance)
+ {
+ _timer = new DispatcherTimer();
+ _timer.Interval = TimeSpan.FromSeconds(1);
+ _timer.Tick += _timer_Tick;
+ _timer.Start();
+ }
+
+ private async void _timer_Tick(object sender, EventArgs e)
+ {
+ _timeCount++;
+ if (_timeCount % RefreshIntervals == 0)
+ {
+ await LoadTasks();
+ _timeCount = 0;
+ }
+ RefreshTime = RefreshIntervals - _timeCount;
+ }
+
+ public OrderTaskDialogViewModel(PullWXOrderService service)
+ {
+ _service = service ?? PullWXOrderService.Instance;
+ Tasks = _service.Tasks;
+ _collectionChangedHandler = OnTasksCollectionChanged;
+ Tasks.CollectionChanged += _collectionChangedHandler;
+
+
+ ClearFinishedCommand = new DelegateCommand(ClearFinished);
+ ClearAllCommand = new DelegateCommand(ClearAll);
+
+ UpdateSummary();
+
+ TasksView = CollectionViewSource.GetDefaultView(Tasks);
+ TasksView.Filter = FilterTaskStatus;
+ }
+
+ public async Task LoadTasks()
+ {
+ await _service.GetTaskStatus();
+ }
+ private bool FilterTaskStatus(object obj)
+ {
+ if (obj is not OrderTask task)
+ return false;
+
+ if (IsShowAll == true)
+ return true;
+
+ return task.Status == 1 || task.Status == 3;
+ }
+
+ /// 任务列表
+ public ObservableCollection Tasks { get; }
+
+ public ICollectionView TasksView { get; }
+
+ /// 清空已完成/失败任务
+ public ICommand ClearFinishedCommand { get; }
+
+ /// 清空全部任务
+ public ICommand ClearAllCommand { get; }
+
+ /// 汇总文字(总数/执行中/成功/失败)
+ public string SummaryText
+ {
+ get => GetValue();
+ set => SetValue(value);
+ }
+ public int RefreshTime
+ {
+ get => GetValue();
+ set => SetValue(value);
+ }
+ public bool IsShowAll
+ {
+ get => GetValue();
+ set
+ {
+ SetValue(value);
+ TasksView.Refresh();
+ }
+ }
+
+ private void ClearFinished()
+ {
+ _service.ClearFinished();
+ }
+
+ private void ClearAll()
+ {
+ if (System.Windows.MessageBox.Show("确定清空全部任务吗?", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Question) != MessageBoxResult.OK)
+ return;
+ _service.ClearAll();
+ }
+
+ private void OnTasksCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ UpdateSummary();
+ }
+
+ private void OnTaskPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(OrderTask.Status))
+ UpdateSummary();
+ }
+
+ private void UpdateSummary()
+ {
+ var items = Tasks;
+ //int running = items.Count(t => t.Status == OrderTask.Running);
+ //int success = items.Count(t => t.Status == OrderTask.Success);
+ //int failed = items.Count(t => t.Status == OrderTask.Failed);
+ //string.Format("任务总数:{0} 执行中:{1} 成功:{2} 失败:{3}",
+ //items.Length, running, success, failed);
+ }
+
+ public void Dispose()
+ {
+ _timer.Stop();
+ _timer = null;
+ }
+}
diff --git a/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs b/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs
index c9da6a5..7941294 100644
--- a/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs
+++ b/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs
@@ -1,5 +1,4 @@
-using _29WxOrderWpf.Common;
-using _29WxOrderWpf.Ctrls.Statistics.Models;
+using _29WxOrderWpf.Ctrls.Statistics.Models;
using AllBase;
using AllBase.Helper;
using Newtonsoft.Json;
@@ -7,10 +6,12 @@ using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Work;
+using WxOrder.Framework.Commons;
namespace _29WxOrderWpf.Ctrls.Statistics.Services
{
@@ -131,7 +132,9 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services
// 总订单数(退款率分母)= 已付款订单 + 已退款订单,不含未付款的 10/250
int totalOrderCount = list.Count();
int refundOrderCount = refunded.Select(r => r.OrderId).Distinct().Count();
-
+ Debug.WriteLine($"计算利润:{(salesAmount - buyerPaymentAmount - platformFeeTotal)}");
+ Debug.WriteLine($"正常订单利润:{valid.Sum(r => (decimal)(r.Profit))/100}");
+ Debug.WriteLine($"售后订单利润:{refunded.Sum(r => (decimal)(r.Profit))/100}");
return new ShopRevenueSummary
{
SalesAmount = salesAmount,
diff --git a/29WxOrderWpf/Services/PullWXOrderService.cs b/29WxOrderWpf/Services/PullWXOrderService.cs
new file mode 100644
index 0000000..a69bae0
--- /dev/null
+++ b/29WxOrderWpf/Services/PullWXOrderService.cs
@@ -0,0 +1,184 @@
+using AllBase;
+using AllBase.Util;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Work.ERP.API;
+using Work.ERP.API.Orders;
+using Work.KJDServer.API.Models;
+using Work.KJDServer.API.WXOrder;
+using ServerTaskStatus = Work.ERP.API.TaskStatus;
+
+namespace _29WxOrderWpf.Services
+{
+ ///
+ /// 拉取微信订单 - 任务数据服务。
+ /// 维护一个任务列表,每次拉取操作都会记录为一条任务,供"任务列表"界面展示;
+ /// 拉取请求通过 提交,提交后返回服务器任务ID;
+ /// 随后循环查询任务状态,直到完成/中断/超时。任务状态查询是另一个独立API
+ /// (查询 task 表),见 (占位,需自行实现)。
+ ///
+ public class PullWXOrderService
+ {
+ /// 循环查询服务器任务状态的间隔(秒)
+ private const int TaskStatusPollIntervalSeconds = 30;
+
+ /// 循环查询服务器任务状态的最大等待时间
+ private static readonly TimeSpan TaskStatusMaxWait = TimeSpan.FromMinutes(10);
+ private static readonly Lazy _lazy = new Lazy(() => new PullWXOrderService());
+
+ /// 单例(全局共享同一份任务列表)
+ public static PullWXOrderService Instance => _lazy.Value;
+
+ private readonly PullWXOrderServiceApi _erpApi = new PullWXOrderServiceApi();
+ private readonly WxOrderServiceApi _kjdApi = new WxOrderServiceApi();
+ private long _seq;
+
+ public PullWXOrderService()
+ {
+ Tasks = new ObservableCollection();
+ }
+
+ /// 任务列表(线程安全,界面可直接绑定)
+ public ObservableCollection Tasks { get; }
+
+ ///
+ /// 拉取指定店铺的指定订单
+ ///
+ public async Task PullOrderDetailAsync(long shopId, string orderId)
+ {
+ return await _erpApi.PullOrderDetail(shopId, orderId);
+ }
+
+ /////
+ ///// 拉取指定店铺的多个订单
+ /////
+ //public Task PullOrdersDetailAsync(long shopId, string[] orderIds)
+ //{
+ // return RunTaskAsync("批量拉取订单", shopId.ToString(), string.Join(",", orderIds ?? new string[0]),
+ // () => _erpApi.PullOrdersDetail(shopId, orderIds));
+ //}
+
+ ///
+ /// 按店铺与时间范围拉取订单
+ ///
+ public Task PullOrderByShopIdsAndTimeRangeAsync(long[] shopIds, DateTime startTime, DateTime endTime)
+ {
+ return _erpApi.PullOrderByShopIdsAndTimeRange(shopIds, startTime, endTime);
+ }
+
+ ///
+ /// 拉取指定店铺的售后订单
+ ///
+ public Task PullRefundOrderByShopsAsync(long[] shopIds, DateTime startTime, DateTime endTime)
+ {
+ return _erpApi.PullRefundOrder(shopIds, startTime, endTime);
+ }
+
+ ///
+ /// 拉取指定店铺的多个售后订单
+ ///
+ public Task PullAfterSaleOrdersAsync(long shopId, string[] afterSaleOrderIds)
+ {
+ return _erpApi.PullAfterSaleOrders(shopId, afterSaleOrderIds);
+ }
+
+
+ public async Task GetTaskStatus()
+ {
+ var tasks = await _kjdApi.GetWxTaskStatus();
+ if (tasks != null)
+ {
+ Tasks.Clear();
+ tasks.ForEach(a => Tasks.Add(a));
+ }
+ }
+
+ ///
+ /// 清空已完成/失败的任务(保留执行中的任务)
+ ///
+ public void ClearFinished()
+ {
+
+ }
+
+ ///
+ /// 清空所有任务
+ ///
+ public void ClearAll()
+ {
+ Tasks.Clear();
+ }
+
+ /////
+ ///// 创建一个任务并执行:提交拉取请求获取服务器任务ID,再循环查询任务状态直至完成。
+ /////
+ //private async Task RunTaskAsync(string taskName, string shopIds, string orderIds, Func> action)
+ //{
+ // var task = new PullWXOrderTaskItem
+ // {
+ // Id = Interlocked.Increment(ref _seq),
+ // TaskName = taskName,
+ // ShopIds = shopIds,
+ // OrderIds = orderIds,
+ // StartTime = DateTime.Now,
+ // Status = PullWXOrderTaskStatus.Running
+ // };
+ // Tasks.Add(task);
+ // try
+ // {
+ // long serverTaskId = await action();
+ // task.ServerTaskId = serverTaskId;
+ // if (serverTaskId > 0)
+ // {
+ // await PollTaskStatusAsync(task, serverTaskId);
+ // }
+ // else
+ // {
+ // // 服务器直接完成,无需轮询
+ // task.EndTime = DateTime.Now;
+ // task.Message = "成功";
+ // task.Status = PullWXOrderTaskStatus.Success;
+ // }
+ // }
+ // catch (Exception ex)
+ // {
+ // task.EndTime = DateTime.Now;
+ // task.Message = ex.Message;
+ // task.Status = PullWXOrderTaskStatus.Failed;
+ // }
+ // return task;
+ //}
+
+ ///
+ /// 循环查询服务器任务状态,直到完成/中断/超时。
+ /// 每次查询都会用 task 表的可用字段刷新任务列表展示内容(任务描述/进度/失败原因等)。
+ ///
+ private async Task PollTaskStatusAsync(OrderTask task, long serverTaskId)
+ {
+
+
+ }
+
+
+ ///
+ /// 查询服务器任务信息(对应 task 表,任务状态查询接口返回的数据)。
+ /// TODO:任务状态查询是另一个独立API,请在这里接入你自己的查询实现,
+ /// 返回 ;task 表 status 字段:1=执行中(Executing),2=已完成(Completed),3=已人为中断(ManuallyInterrupted)。
+ ///
+ //private async Task QueryTaskAsync()
+ //{
+ // await _kjdApi.GetWxTaskStatus();
+ // // ===================== 请在这里接入你自己的任务状态查询API =====================
+ // // 示例:
+ // // TaskInfo info = await 你的查询API.QueryTask(taskId);
+ // // return info;
+ // // ===============================================================================
+ // throw new NotImplementedException("任务状态查询API尚未实现,请在 PullWXOrderService.QueryTaskAsync 中接入");
+ //}
+ }
+}
diff --git a/29WxOrderWpf/Services/ShipGiftService.cs b/29WxOrderWpf/Services/ShipGiftService.cs
index 4652a09..6664594 100644
--- a/29WxOrderWpf/Services/ShipGiftService.cs
+++ b/29WxOrderWpf/Services/ShipGiftService.cs
@@ -11,6 +11,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Work._29Tools.BLL;
+using Work.ERP.API.Orders;
namespace _29WxOrderWpf.Services;
@@ -25,6 +26,11 @@ public class ShipGiftService
_155 = 2,
_160 = 5
}
+ private ShipGiftServiceApi _api;
+ public ShipGiftService()
+ {
+ _api = new ShipGiftServiceApi();
+ }
public async Task Send(string orderId, GiftType giftType)
{
var item = GlobalConfig.lstFilterOrder.FirstOrDefault(a => a.order_id == orderId);
@@ -58,30 +64,19 @@ public class ShipGiftService
amount += 12.15m;
}
- string data = JsonConvert.SerializeObject(new
- {
- platformCode = "WEISHOP",
- orderIds = new List { orderId },
- userId = BaseClass.UserId,
- userName = BaseClass.UserName,
- giftOrderType = (int)giftType,
- amount = (int)(amount * 100),
- oemAmount = (int)(BaseClass.OemGiftAmount * 100)
- });
- Debug.WriteLine($"礼品单:{data}");
- string ret = await HttpResponseWXBLL.e57PostResponseAsync("https://po.e57.cn//prod-api/api/oms-api/gift/order/deliveryFor29Erp", data, "");
- XmlDocument doc = new XmlDocument();
- doc.LoadXml(ret);
+ //string data = JsonConvert.SerializeObject(new
+ //{
+ // platformCode = "WEISHOP",
+ // orderIds = new List { orderId },
+ // userId = BaseClass.UserId,
+ // userName = BaseClass.UserName,
+ // giftOrderType = (int)giftType,
+ // amount = (int)(amount * 100),
+ // oemAmount = (int)(BaseClass.OemGiftAmount * 100)
+ //});
+ var ret = await _api.SendShipGift([orderId], (int)giftType, amount, BaseClass.OemGiftAmount);
+ return ret;
- //使用 Newtonsoft.Json 进行转换
- string jsonText = JsonConvert.SerializeXmlNode(doc);
- JObject jsonObject = JObject.Parse(jsonText);
- int code = jsonObject["AjaxResult"]?["code"]?.Value() ?? 0;
- string msg = jsonObject["AjaxResult"]?["msg"]?.Value() ?? "";
- if (code == 200 && msg.ToUpper() == "SUCCESS")
- {
- return true;
- }
- return false;
+
}
}
diff --git a/29WxOrderWpf/ViewModels/OrderTaskViewModel.cs b/29WxOrderWpf/ViewModels/OrderTaskViewModel.cs
new file mode 100644
index 0000000..42748d0
--- /dev/null
+++ b/29WxOrderWpf/ViewModels/OrderTaskViewModel.cs
@@ -0,0 +1,42 @@
+//using Newtonsoft.Json;
+//using System;
+//using System.Collections.Generic;
+//using System.Linq;
+//using System.Text;
+//using System.Threading.Tasks;
+//using WPFCommon.Models;
+
+//namespace _29WxOrderWpf.ViewModels;
+
+//public class OrderTaskViewModel : BindableBaseEx
+//{
+// public int Id { get; set; }
+
+// public int TaskType { get; set; }
+
+// public string TaskDescribe { get; set; }
+
+// public string TaskShopIds { get; set; }
+
+// public string TaskObjectIds { get; set; }
+
+// public int SubTaskNum { get; set; }
+
+// public int SuccessTaskNum { get; set; }
+
+// public int FailTaskNum { get; set; }
+
+// public int Status { get; set; }
+
+// public string CreateBy { get; set; }
+
+// public string UpdateBy { get; set; }
+
+// public string Remark { get; set; }
+
+// public string TaskFailReason { get; set; }
+
+// public DateTime CreateTime { get; set; }
+
+// public DateTime UpdateTime { get; set; }
+//}
\ No newline at end of file
diff --git a/Work/29WxOrderWork.csproj b/Work/29WxOrderWork.csproj
index 078c638..3699d32 100644
--- a/Work/29WxOrderWork.csproj
+++ b/Work/29WxOrderWork.csproj
@@ -227,6 +227,11 @@
+
+
+
+
+
@@ -234,6 +239,7 @@
+
@@ -263,6 +269,8 @@
TokenForm.cs
+
+
@@ -317,6 +325,10 @@
{6461d807-b1c8-45f0-b388-e0ca1a418de0}
29WxOrderAllBase
+
+ {3123963c-a0ec-4ad5-9916-dc063f73490b}
+ WxOrder.Framework
+
diff --git a/Work/ERP.API/ERPConfig.cs b/Work/ERP.API/ERPConfig.cs
new file mode 100644
index 0000000..0a2c198
--- /dev/null
+++ b/Work/ERP.API/ERPConfig.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Work.ERP.API
+{
+ public class ERPConfig
+ {
+ public const string Domain = "https://po.e57.cn";
+ }
+}
diff --git a/Work/ERP.API/ERPHttp.cs b/Work/ERP.API/ERPHttp.cs
new file mode 100644
index 0000000..239680b
--- /dev/null
+++ b/Work/ERP.API/ERPHttp.cs
@@ -0,0 +1,40 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Work._29Tools.BLL;
+using WxOrder.Framework.Commons;
+
+namespace Work.ERP.API
+{
+ public class ERPHttp
+ {
+ public static string e57PostResponse(string _url, string _data)
+ {
+ return HttpResponseWXBLL.e57PostResponse(ERPConfig.Domain + _url, _data, "");
+ }
+ public static Task e57PostResponseAsync(string _url, string _data)
+ {
+ return HttpResponseWXBLL.e57PostResponseAsync(ERPConfig.Domain + _url, _data);
+ }
+ public static async Task e57PostResponseAsync(string _url, string _data) where T : Result, new()
+ {
+ try
+ {
+ string content = await HttpResponseWXBLL.e57PostResponseAsync(ERPConfig.Domain + _url, _data);
+ return JsonConvert.DeserializeObject(content);
+ }
+ catch (JsonException)
+ {
+ return new T { Code = 0, Msg = "数据解析失败" };
+ }
+ catch (Exception ex)
+ {
+ return new T { Code = 0, Msg = ex.Message };
+ }
+
+ }
+ }
+}
diff --git a/Work/ERP.API/Orders/PullWXOrderServiceApi.cs b/Work/ERP.API/Orders/PullWXOrderServiceApi.cs
new file mode 100644
index 0000000..cae7049
--- /dev/null
+++ b/Work/ERP.API/Orders/PullWXOrderServiceApi.cs
@@ -0,0 +1,186 @@
+using AllBase;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using WxOrder.Framework.Commons;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+
+namespace Work.ERP.API.Orders
+{
+ class PullWXOrderResult : Result
+ {
+
+ public List Data { get; set; }
+ public class FailedItem
+ {
+ public long shopId { get; set; }
+ public string shopName { get; set; }
+ public string message { get; set; }
+ }
+ }
+ ///
+ /// 拉取微信订单
+ ///
+ public class PullWXOrderServiceApi
+ {
+ ///
+ /// 拉取指定店铺的指定订单
+ ///
+ /// 店铺ID
+ /// 订单号
+ /// 服务器异步任务ID;为 0 表示服务器已直接完成
+ ///
+ public async Task PullOrderDetail(long shopId, string orderId)
+ {
+ string data = JsonConvert.SerializeObject(new
+ {
+ platformCode = "WEISHOP",
+ shopId = shopId,
+ orderId = orderId,
+ clientUserName = BaseClass.UserName
+ });
+ var result = await PostAndGetTaskIdAsync("/prod-api/api/oms-api/client/sync/pull_order_detail", data);
+ return result.Code == 200;
+ }
+
+ ///
+ /// 拉取指定店铺的订单列表
+ ///
+ /// 店铺ID
+ /// 订单号列表
+ /// 服务器异步任务ID;为 0 表示服务器已直接完成
+ ///
+ public async Task PullOrdersDetail(long shopId, string[] orderIds)
+ {
+ string data = JsonConvert.SerializeObject(new
+ {
+ platformCode = "WEISHOP",
+ shopId = shopId,
+ orderId = string.Join(",", orderIds),
+ clientUserName = BaseClass.UserName,
+
+ });
+ var result = await PostAndGetTaskIdAsync("/prod-api/api/oms-api/client/sync/pull_order_detail/batch", data);
+ if (result.Code == 200)
+ {
+ return true;
+ }
+ else
+ {
+ string msg = string.Join("\n", result.Data.Select(a => $"{a.shopName},{a.message}"));
+ throw new Exception(msg);
+ }
+ }
+
+ ///
+ /// 拉取指定商铺列表时间范围内的数据
+ ///
+ /// 店铺ID列表
+ /// 开始时间
+ /// 结束时间
+ /// 服务器异步任务ID;为 0 表示服务器已直接完成
+ ///
+ public async Task PullOrderByShopIdsAndTimeRange(long[] shopIds, DateTime startTime, DateTime endTime)
+ {
+ TimeSpan time = endTime - startTime;
+ if (time.TotalDays > 7) throw new Exception("时间范围最大7天");
+ string data = JsonConvert.SerializeObject(new
+ {
+ platformCode = "WEISHOP",
+ shopIds = string.Join(",", shopIds),
+ startTime = startTime.ToString("yyyy-MM-dd HH:mm:ss"),
+ endTime = endTime.ToString("yyyy-MM-dd HH:mm:ss"),
+ clientUserName = BaseClass.UserName,
+ remark=$"同步 {startTime.ToString("yyyy-MM-dd")}/{endTime.ToString("dd")}"
+ });
+ var result = await PostAndGetTaskIdAsync("/prod-api/api/oms-api/client/sync/pull_order", data);
+
+ if (result.Code == 200)
+ {
+ return true;
+ }
+ else
+ {
+ string msg = string.Join("\n", result.Data.Select(a => $"{a.shopName},{a.message}"));
+ throw new Exception(msg);
+ }
+ }
+
+ ///
+ /// 拉取指定店铺的售后订单
+ ///
+ /// 店铺ID列表
+ /// 服务器异步任务ID;为 0 表示服务器已直接完成
+ ///
+ public async Task PullRefundOrder(long[] shopIds, DateTime startTime, DateTime endTime)
+ {
+ TimeSpan time = endTime - startTime;
+ if (time.TotalDays > 7) throw new Exception("时间范围最大7天");
+ string data = JsonConvert.SerializeObject(new
+ {
+ platformCode = "WEISHOP",
+ shopIdList = shopIds,
+ startTime = startTime.ToString("yyyy-MM-dd HH:mm:ss"),
+ endTime = endTime.ToString("yyyy-MM-dd HH:mm:ss"),
+ clientUserName = BaseClass.UserName,
+ remark = $"同步售后订单"
+ });
+ var result = await PostAndGetTaskIdAsync("/prod-api/api/oms-api/client/sync/oms/pull_refund_order", data);
+
+ if (result.Code == 200)
+ {
+ return true;
+ }
+ else
+ {
+ string msg = string.Join("\n", result.Data.Select(a => $"{a.shopName},{a.message}"));
+ throw new Exception(msg);
+ }
+ }
+
+ ///
+ /// 拉取指定商铺的售后订单
+ ///
+ /// 店铺ID
+ /// 售后订单号列表
+ /// 服务器异步任务ID;为 0 表示服务器已直接完成
+ ///
+ public async Task PullAfterSaleOrders(long shopId, string[] afterSaleOrderIds)
+ {
+ string data = JsonConvert.SerializeObject(new
+ {
+ platformCode = "WEISHOP",
+ shopId = shopId,
+ afterSaleOrderIds = afterSaleOrderIds,
+ clientUserName = BaseClass.UserName,
+ remark = $"同步售后订单"
+ });
+ var result = await PostAndGetTaskIdAsync("/prod-api/api/oms-api/client/sync/oms/pull_list/batch", data);
+
+ if (result.Code == 200)
+ {
+ return true;
+ }
+ else
+ {
+ string msg = string.Join("\n", result.Data.Select(a => $"{a.shopName},{a.message}"));
+ throw new Exception(msg);
+ }
+ }
+
+ ///
+ /// 提交拉取请求并从返回结果中解析服务器异步任务ID。
+ /// 兼容 data 为纯数字、数字字符串或对象(含 taskId/task_id/id 字段)等返回格式;
+ /// 无法解析时返回 0(视为服务器直接完成)。
+ ///
+ private async Task PostAndGetTaskIdAsync(string url, string data)
+ {
+ var result = await ERPHttp.e57PostResponseAsync(url, data);
+ if (result.Code != 200) throw new Exception(result.Msg);
+ return result;
+ }
+ }
+}
diff --git a/Work/ERP.API/Orders/ShipGiftServiceApi.cs b/Work/ERP.API/Orders/ShipGiftServiceApi.cs
new file mode 100644
index 0000000..c10579e
--- /dev/null
+++ b/Work/ERP.API/Orders/ShipGiftServiceApi.cs
@@ -0,0 +1,39 @@
+using AllBase;
+using CefSharp.DevTools.FedCm;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Policy;
+using System.Text;
+using System.Threading.Tasks;
+using Work.ERP.API.Orders;
+using WxOrder.Framework.Commons;
+
+namespace Work.ERP.API.Orders
+{
+ public class ShipGiftServiceApi
+ {
+ public async Task SendShipGift(string[] orderIds, int giftType, decimal amount, decimal oemGiftAmount)
+ {
+ string data = JsonConvert.SerializeObject(new
+ {
+ platformCode = "WEISHOP",
+ orderIds = orderIds,
+ userId = BaseClass.UserId,
+ userName = BaseClass.UserName,
+ giftOrderType = (int)giftType,
+ amount = (int)(amount * 100),
+ oemAmount = (int)(oemGiftAmount * 100)
+ });
+ Debug.WriteLine($"礼品单:{data}");
+ var result = await ERPHttp.e57PostResponseAsync("/prod-api/api/oms-api/gift/order/deliveryFor29Erp", data);
+ if (result.Code != 200)
+ {
+ throw new Exception(result.Msg);
+ }
+ return true;
+ }
+ }
+}
diff --git a/Work/ERP.API/TaskStatus.cs b/Work/ERP.API/TaskStatus.cs
new file mode 100644
index 0000000..73503ba
--- /dev/null
+++ b/Work/ERP.API/TaskStatus.cs
@@ -0,0 +1,26 @@
+using System.ComponentModel;
+
+namespace Work.ERP.API
+{
+ ///
+ /// 服务器异步任务状态(与任务状态表字段一致:1=执行中,2=已完成,3=已人为中断)
+ ///
+ public enum TaskStatus
+ {
+ ///
+ /// 执行中
+ ///
+ [Description("执行中")]
+ Executing = 1,
+ ///
+ /// 已完成
+ ///
+ [Description("已完成")]
+ Completed = 2,
+ ///
+ /// 已人为中断
+ ///
+ [Description("已人为中断")]
+ ManuallyInterrupted = 3
+ }
+}
diff --git a/Work/KJDServer.API/KJDServerHttp.cs b/Work/KJDServer.API/KJDServerHttp.cs
new file mode 100644
index 0000000..24080ce
--- /dev/null
+++ b/Work/KJDServer.API/KJDServerHttp.cs
@@ -0,0 +1,112 @@
+using AllBase;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using WxOrder.Framework.Commons;
+
+namespace Work.KJDServer.API
+{
+ public class KJDServerHttp
+ {
+ public static async Task PostAsync(string url, string data)
+ {
+ if (url.StartsWith("/"))
+ url = url.Substring(1);
+ url = BaseClass.LoginApiUrl + "/wxxd_" + url + "?obj=" + BaseClass.MainPath + "/wxxd_" + url;
+ string sign = UserLogin.GetSignaturex();
+ data = $"{sign}&{data}";
+ return await _postAsync(url, data);
+ }
+ public static async Task PostAsync(string url, string data) where T : Result, new()
+ {
+ try
+ {
+ string result = await PostAsync(url, data);
+ return JsonConvert.DeserializeObject(result);
+ }
+ catch (JsonException)
+ {
+ return new T { Code = 0, Msg = "数据解析失败" };
+ }
+ catch (Exception ex)
+ {
+ return new T { Code = 0, Msg = ex.Message };
+ }
+ }
+
+
+ private static async Task _postAsync(string url, string postData, int timeOut = -1)
+ {
+ HttpWebResponse response = null;
+ string result;
+ try
+ {
+ HttpWebRequest request;
+ request = (HttpWebRequest)WebRequest.Create(url);
+
+ request.KeepAlive = true;
+ request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
+ request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36";
+ request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
+ request.Headers.Set(HttpRequestHeader.AcceptLanguage, "zh-CN,zh;q=0.9");
+
+ request.Method = "POST";
+ request.ServicePoint.Expect100Continue = false;
+
+ string body = postData;
+ byte[] postBytes = System.Text.Encoding.UTF8.GetBytes(body);
+ request.ContentLength = postBytes.Length;
+ Stream stream = request.GetRequestStream();
+ stream.Write(postBytes, 0, postBytes.Length);
+ stream.Close();
+
+ response = (HttpWebResponse)await request.GetResponseAsync();
+ }
+ catch (WebException ex)
+ {
+ if (ex.Status == WebExceptionStatus.ProtocolError)
+ {
+ response = (HttpWebResponse)ex.Response;
+ result = ReadResponse(response);
+ return result;
+ }
+ else return ex.Message;
+ }
+ catch (Exception e)
+ {
+ if (response != null) response.Close();
+ return e.Message;
+ }
+ result = ReadResponse(response);
+ return result;
+
+ }
+
+ public static string ReadResponse(HttpWebResponse response, Encoding encoding = null)
+ {
+ using (Stream responseStream = response.GetResponseStream())
+ {
+ Stream streamToRead = responseStream;
+ if (response.ContentEncoding.ToLower().Contains("gzip"))
+ {
+ streamToRead = new GZipStream(streamToRead, CompressionMode.Decompress);
+ }
+ else if (response.ContentEncoding.ToLower().Contains("deflate"))
+ {
+ streamToRead = new DeflateStream(streamToRead, CompressionMode.Decompress);
+ }
+ if (encoding == null) encoding = Encoding.UTF8;
+ using (StreamReader streamReader = new StreamReader(streamToRead, encoding))
+ {
+ return streamReader.ReadToEnd();
+ }
+ }
+ }
+ }
+}
diff --git a/Work/KJDServer.API/Models/OrderTask.cs b/Work/KJDServer.API/Models/OrderTask.cs
new file mode 100644
index 0000000..3feda5f
--- /dev/null
+++ b/Work/KJDServer.API/Models/OrderTask.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Work.KJDServer.API.Models
+{
+ public class OrderTask
+ {
+ public int Id { get; set; }
+
+ public int TaskType { get; set; }
+
+ public string TaskDescribe { get; set; }
+
+ public string ShopId { get; set; }
+ public string ShopName { get; set; }
+
+ public string ObjectIds { get; set; }
+
+ public int SubTaskNum { get; set; }
+
+ public int SuccessTaskNum { get; set; }
+
+ public int FailTaskNum { get; set; }
+
+ public int Status { get; set; }
+
+ public string CreateBy { get; set; }
+
+ public string UpdateBy { get; set; }
+
+ public string Remark { get; set; }
+
+ public string TaskFailReason { get; set; }
+
+ public DateTime CreateTime { get; set; }
+
+ public DateTime UpdateTime { get; set; }
+ }
+
+}
\ No newline at end of file
diff --git a/Work/KJDServer.API/WXOrder/WxOrderServiceApi.cs b/Work/KJDServer.API/WXOrder/WxOrderServiceApi.cs
new file mode 100644
index 0000000..fb0689d
--- /dev/null
+++ b/Work/KJDServer.API/WXOrder/WxOrderServiceApi.cs
@@ -0,0 +1,30 @@
+using AllBase;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Work.KJDServer.API.Models;
+using WxOrder.Framework.Commons;
+
+namespace Work.KJDServer.API.WXOrder
+{
+ public class WxOrderServiceApi
+ {
+ public WxOrderServiceApi()
+ {
+
+ }
+
+ public async Task> GetWxTaskStatus()
+ {
+ var ret = await KJDServerHttp.PostAsync>>("order/wx_get_task_status_list", "");
+ if (ret.Code == 200)
+ {
+ return ret.Data;
+ }
+ return null;
+ }
+ }
+}
diff --git a/Work/_29Tools/BLL/HttpResponseWXBLL.cs b/Work/_29Tools/BLL/HttpResponseWXBLL.cs
index be8b77f..8b127a1 100644
--- a/Work/_29Tools/BLL/HttpResponseWXBLL.cs
+++ b/Work/_29Tools/BLL/HttpResponseWXBLL.cs
@@ -659,7 +659,7 @@ namespace Work._29Tools.BLL
return result;
}
- public static async Task e57PostResponseAsync(string _url, string _data, string referer)
+ public static async Task e57PostResponseAsync(string _url, string _data)
{
//await Task.Delay(2000);
//return await Task.FromResult("SUCCESS200");
@@ -694,26 +694,11 @@ namespace Work._29Tools.BLL
}
else
request = (HttpWebRequest)WebRequest.Create(url);
-
request.KeepAlive = true;
- //request.Headers.Set(HttpRequestHeader.CacheControl, "max-age=0");
- //request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36";
request.ContentType = "application/json";
- //request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"; //request.Accept = "*/*";
- //request.Referer = referer;
- //request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
- //request.Headers.Set(HttpRequestHeader.AcceptLanguage, "zh-CN,zh;q=0.9");
- request.Headers.Add("sec-ch-ua", @"""Not(A:Brand"";v=""8"", ""Chromium"";v=""144"", ""Google Chrome"";v=""144""");
- request.Headers.Add("sec-ch-ua-mobile", @"?0");
- request.Headers.Add("sec-ch-ua-platform", @"""Windows""");
- request.Headers.Add("Upgrade-Insecure-Requests", @"1");
+
request.Headers.Add("Authorization", "Bearer " + sAuthorization);
- request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36";
- request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7";
- request.Headers.Add("Sec-Fetch-Site", @"none");
- request.Headers.Add("Sec-Fetch-Mode", @"navigate");
- request.Headers.Add("Sec-Fetch-User", @"?1");
- request.Headers.Add("Sec-Fetch-Dest", @"document");
+ request.Accept = "application/json";
request.Headers.Set(HttpRequestHeader.Cookie, "Admin-Token=" + sAuthorization);
request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
request.Headers.Set(HttpRequestHeader.AcceptLanguage, "zh-CN,zh;q=0.9");
diff --git a/29WxOrderWpf/Common/Result.cs b/WxOrder.Framework/Commons/Result.cs
similarity index 91%
rename from 29WxOrderWpf/Common/Result.cs
rename to WxOrder.Framework/Commons/Result.cs
index 43f7e9e..6608d8a 100644
--- a/29WxOrderWpf/Common/Result.cs
+++ b/WxOrder.Framework/Commons/Result.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace _29WxOrderWpf.Common
+namespace WxOrder.Framework.Commons
{
public class Result
{
diff --git a/WxOrder.Framework/WxOrder.Framework.csproj b/WxOrder.Framework/WxOrder.Framework.csproj
index 8dbcc0e..078c8ae 100644
--- a/WxOrder.Framework/WxOrder.Framework.csproj
+++ b/WxOrder.Framework/WxOrder.Framework.csproj
@@ -7,6 +7,14 @@
true
+
+
+
+
+
+
+
+
diff --git a/test/WXOrder.Test/PullWXOrder.Test.cs b/test/WXOrder.Test/PullWXOrder.Test.cs
new file mode 100644
index 0000000..95f5c3e
--- /dev/null
+++ b/test/WXOrder.Test/PullWXOrder.Test.cs
@@ -0,0 +1,28 @@
+using AllBase;
+
+namespace WXOrder.Test;
+
+public class Tests
+{
+ [SetUp]
+ public void Setup()
+ {
+ var a = BaseClass.ServerUrl;
+ BaseClass.UserName = "18990991234";
+ }
+
+ [Test]
+ public async Task Test1()
+ {
+ var pp = new Work.ERP.API.PullWxOrder.PullWXOrderServiceApi();
+ await pp.PullOrderDetail(1960967267443621583, "3722940821913342976");
+ Assert.Pass();
+ }
+ [Test]
+ public async Task Test2()
+ {
+ var pp = new Work.ERP.API.PullWxOrder.PullWXOrderServiceApi();
+ await pp.PullOrderByShopIdsAndTimeRange([1960967267443621583, 1960967267443620449], DateTime.Now.AddDays(-1), DateTime.Now);
+ Assert.Pass();
+ }
+}
\ No newline at end of file
diff --git a/test/WXOrder.Test/WXOrder.Test.csproj b/test/WXOrder.Test/WXOrder.Test.csproj
new file mode 100644
index 0000000..cc9052d
--- /dev/null
+++ b/test/WXOrder.Test/WXOrder.Test.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net8.0
+ enable
+ enable
+ x64
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+