订单列表增加 同步订单

This commit is contained in:
chfei committed 2026-08-19 15:35:42 +08:00
1 parent 4f606c3561
commit cef6300e8e
24 files changed
+2674 -1211

No files matched your search

+21
View File
@@ -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}
@@ -0,0 +1,36 @@
using System;
using System.Globalization;
using System.Windows.Data;
using Work.ERP.API;
namespace _29WxOrderWpf.Converters
{
/// <summary>
/// 订单任务状态转换:<see cref="Work.KJDServer.API.Models.OrderTask.Status"/> (int) → 中文描述。
/// 1=执行中,2=已完成,3=已人为中断。
/// </summary>
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();
}
}
}
File diff suppressed because it is too large. Load diff
@@ -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
}
}
/// <summary>
/// 拉取微信订单到任务列表
/// </summary>
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<long, List<oms_wei_order_info>> 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
@@ -0,0 +1,241 @@
<UserControl
x:Class="_29WxOrderWpf.Ctrls.OrderCtrls.OrderTaskDialogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
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:wpf="clr-namespace:_29WxOrderWpf.Common"
xmlns:wpf1="WPFCommon"
d:Background="White"
d:DataContext="{d:DesignInstance Type=local:OrderTaskDialogViewModel}"
d:DesignHeight="600"
d:DesignWidth="1300"
wpf:DialogWindowProperty.Height="600"
wpf:DialogWindowProperty.ResizeMode="CanResizeWithGrip"
wpf:DialogWindowProperty.ShowMinButton="False"
wpf:DialogWindowProperty.Width="1300"
mc:Ignorable="d">
<UserControl.Resources>
<!-- 单元格文字居中 -->
<Style x:Key="CenterCellTextStyle" TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<!-- 面板标题 -->
<Style x:Key="PanelTitleStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="#333333" />
</Style>
<!-- 工具栏按钮 -->
<Style x:Key="ToolBarButtonStyle" TargetType="Button">
<Setter Property="Height" Value="30" />
<Setter Property="Padding" Value="14,0" />
<Setter Property="Margin" Value="6,0,0,0" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Foreground" Value="#333333" />
<Setter Property="Background" Value="White" />
<Setter Property="BorderBrush" Value="#D9D9D9" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
x:Name="btnBorder"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4">
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="btnBorder" Property="Background" Value="#F0F2F5" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="btnBorder" Property="Background" Value="#E4E7ED" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- 任务状态:int (1=执行中,2=已完成,3=已人为中断) → 中文描述 -->
<converters:OrderTaskStatusConverter x:Key="OrderTaskStatusConverter" />
</UserControl.Resources>
<Grid Background="#F5F7FB">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<!-- ============ 顶部工具栏 ============ -->
<Border
Grid.Row="0"
Padding="14,10"
Background="White"
BorderBrush="#E8EAED"
BorderThickness="0,0,0,1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource PanelTitleStyle}" Text="订单同步任务列表" />
<CheckBox
Margin="20,0,0,0"
VerticalAlignment="Center"
Content="查看全部"
IsChecked="{Binding IsShowAll}" />
</StackPanel>
<!--<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button
Command="{Binding ClearFinishedCommand}"
Content="清空已完成"
Style="{StaticResource ToolBarButtonStyle}" />
<Button
Command="{Binding ClearAllCommand}"
Content="清空全部"
Style="{StaticResource ToolBarButtonStyle}" />
</StackPanel>-->
</Grid>
</Border>
<!-- ============ 任务列表 ============ -->
<DataGrid
Grid.Row="1"
Margin="10,10,10,0"
d:ItemsSource="{d:SampleData ItemCount=10}"
AlternatingRowBackground="#FAFAFA"
AutoGenerateColumns="False"
Background="White"
BorderBrush="#E8EAED"
BorderThickness="1"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
CanUserResizeRows="False"
ColumnHeaderStyle="{StaticResource BaseDataGridColumnHeaderStyle}"
FontSize="13"
Foreground="#333333"
GridLinesVisibility="Horizontal"
HeadersVisibility="Column"
HorizontalGridLinesBrush="#EEEEEE"
IsReadOnly="True"
ItemsSource="{Binding TasksView}"
RowHeight="40"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectionMode="Single"
SelectionUnit="FullRow">
<DataGrid.Columns>
<!-- 任务描述 -->
<DataGridTextColumn
Width="1.5*"
MinWidth="120"
Binding="{Binding TaskDescribe}"
ElementStyle="{StaticResource CenterCellTextStyle}"
Header="任务描述" />
<!-- 店铺 -->
<DataGridTextColumn
Width="1*"
MinWidth="100"
Binding="{Binding ShopName}"
ElementStyle="{StaticResource CenterCellTextStyle}"
Header="店铺" />
<!-- 状态 -->
<DataGridTemplateColumn
Width="1*"
MinWidth="60"
Header="状态">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding Status, Converter={StaticResource OrderTaskStatusConverter}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="#E6A23C" />
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="2">
<Setter Property="Foreground" Value="#67C23A" />
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="3">
<Setter Property="Foreground" Value="#F56C6C" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- 失败原因 -->
<DataGridTextColumn
Width="2*"
MinWidth="150"
Binding="{Binding TaskFailReason}"
ElementStyle="{StaticResource CenterCellTextStyle}"
Header="失败原因" />
<!-- 创建时间 -->
<DataGridTextColumn
Width="2*"
MinWidth="140"
Binding="{Binding CreateTime, StringFormat={}{0:yyyy-MM-dd HH:mm:ss}}"
ElementStyle="{StaticResource CenterCellTextStyle}"
Header="创建时间" />
<!-- 更新时间 -->
<DataGridTextColumn
Width="2*"
MinWidth="140"
Binding="{Binding UpdateTime, StringFormat={}{0:yyyy-MM-dd HH:mm:ss}}"
ElementStyle="{StaticResource CenterCellTextStyle}"
Header="更新时间" />
<!-- 备注 -->
<DataGridTextColumn
Width="2*"
MinWidth="140"
Binding="{Binding Remark}"
ElementStyle="{StaticResource CenterCellTextStyle}"
Header="备注" />
</DataGrid.Columns>
</DataGrid>
<Border
Grid.Row="2"
Padding="10,0"
Background="White">
<Grid VerticalAlignment="Center">
<TextBlock
HorizontalAlignment="Right"
d:Text="距离下次刷新10秒"
Text="{Binding RefreshTime, StringFormat='距离下次刷新:{0}秒'}" />
</Grid>
</Border>
</Grid>
</UserControl>
@@ -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;
/// <summary>
/// OrderTaskDialogView.xaml 的交互逻辑
/// </summary>
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();
}
}
/// <summary>
/// 任务列表 - ViewModel
/// </summary>
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;
}
/// <summary>任务列表</summary>
public ObservableCollection<OrderTask> Tasks { get; }
public ICollectionView TasksView { get; }
/// <summary>清空已完成/失败任务</summary>
public ICommand ClearFinishedCommand { get; }
/// <summary>清空全部任务</summary>
public ICommand ClearAllCommand { get; }
/// <summary>汇总文字(总数/执行中/成功/失败)</summary>
public string SummaryText
{
get => GetValue<string>();
set => SetValue(value);
}
public int RefreshTime
{
get => GetValue<int>();
set => SetValue(value);
}
public bool IsShowAll
{
get => GetValue<bool>();
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;
}
}
@@ -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,
+184
View File
@@ -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
{
/// <summary>
/// 拉取微信订单 - 任务数据服务。
/// 维护一个任务列表,每次拉取操作都会记录为一条任务,供"任务列表"界面展示;
/// 拉取请求通过 <see cref="PullWXOrderServiceApi"/> 提交,提交后返回服务器任务ID;
/// 随后循环查询任务状态,直到完成/中断/超时。任务状态查询是另一个独立API
/// (查询 task 表),见 <see cref="QueryTaskAsync"/>(占位,需自行实现)。
/// </summary>
public class PullWXOrderService
{
/// <summary>循环查询服务器任务状态的间隔(秒)</summary>
private const int TaskStatusPollIntervalSeconds = 30;
/// <summary>循环查询服务器任务状态的最大等待时间</summary>
private static readonly TimeSpan TaskStatusMaxWait = TimeSpan.FromMinutes(10);
private static readonly Lazy<PullWXOrderService> _lazy = new Lazy<PullWXOrderService>(() => new PullWXOrderService());
/// <summary>单例(全局共享同一份任务列表)</summary>
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<OrderTask>();
}
/// <summary>任务列表(线程安全,界面可直接绑定)</summary>
public ObservableCollection<OrderTask> Tasks { get; }
/// <summary>
/// 拉取指定店铺的指定订单
/// </summary>
public async Task<bool> PullOrderDetailAsync(long shopId, string orderId)
{
return await _erpApi.PullOrderDetail(shopId, orderId);
}
///// <summary>
///// 拉取指定店铺的多个订单
///// </summary>
//public Task<PullWXOrderTaskItem> PullOrdersDetailAsync(long shopId, string[] orderIds)
//{
// return RunTaskAsync("批量拉取订单", shopId.ToString(), string.Join(",", orderIds ?? new string[0]),
// () => _erpApi.PullOrdersDetail(shopId, orderIds));
//}
/// <summary>
/// 按店铺与时间范围拉取订单
/// </summary>
public Task<bool> PullOrderByShopIdsAndTimeRangeAsync(long[] shopIds, DateTime startTime, DateTime endTime)
{
return _erpApi.PullOrderByShopIdsAndTimeRange(shopIds, startTime, endTime);
}
/// <summary>
/// 拉取指定店铺的售后订单
/// </summary>
public Task<bool> PullRefundOrderByShopsAsync(long[] shopIds, DateTime startTime, DateTime endTime)
{
return _erpApi.PullRefundOrder(shopIds, startTime, endTime);
}
/// <summary>
/// 拉取指定店铺的多个售后订单
/// </summary>
public Task<bool> 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));
}
}
/// <summary>
/// 清空已完成/失败的任务(保留执行中的任务)
/// </summary>
public void ClearFinished()
{
}
/// <summary>
/// 清空所有任务
/// </summary>
public void ClearAll()
{
Tasks.Clear();
}
///// <summary>
///// 创建一个任务并执行:提交拉取请求获取服务器任务ID,再循环查询任务状态直至完成。
///// </summary>
//private async Task<PullWXOrderTaskItem> RunTaskAsync(string taskName, string shopIds, string orderIds, Func<Task<long>> 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;
//}
/// <summary>
/// 循环查询服务器任务状态,直到完成/中断/超时。
/// 每次查询都会用 task 表的可用字段刷新任务列表展示内容(任务描述/进度/失败原因等)。
/// </summary>
private async Task PollTaskStatusAsync(OrderTask task, long serverTaskId)
{
}
/// <summary>
/// 查询服务器任务信息(对应 task 表,任务状态查询接口返回的数据)。
/// TODO:任务状态查询是另一个独立API,请在这里接入你自己的查询实现,
/// 返回 <see cref="TaskInfo"/>;task 表 status 字段:1=执行中(Executing),2=已完成(Completed),3=已人为中断(ManuallyInterrupted)。
/// </summary>
//private async Task<TaskInfo> QueryTaskAsync()
//{
// await _kjdApi.GetWxTaskStatus();
// // ===================== 请在这里接入你自己的任务状态查询API =====================
// // 示例:
// // TaskInfo info = await 你的查询API.QueryTask(taskId);
// // return info;
// // ===============================================================================
// throw new NotImplementedException("任务状态查询API尚未实现,请在 PullWXOrderService.QueryTaskAsync 中接入");
//}
}
}
+19 -24
View File
@@ -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<bool> 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<string> { 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<string> { 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<int>() ?? 0;
string msg = jsonObject["AjaxResult"]?["msg"]?.Value<string>() ?? "";
if (code == 200 && msg.ToUpper() == "SUCCESS")
{
return true;
}
return false;
}
}
@@ -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; }
//}
+12
View File
@@ -227,6 +227,11 @@
<Compile Include="BuyUsers\TaoBaoBuyUser.cs" />
<Compile Include="CheckHecker.cs" />
<Compile Include="CollectionClass.cs" />
<Compile Include="ERP.API\ERPConfig.cs" />
<Compile Include="ERP.API\ERPHttp.cs" />
<Compile Include="ERP.API\Orders\ShipGiftServiceApi.cs" />
<Compile Include="ERP.API\TaskStatus.cs" />
<Compile Include="ERP.API\Orders\PullWXOrderServiceApi.cs" />
<Compile Include="GetPostTaobaoHtml.cs" />
<Compile Include="DouYinHttpWebRequest.cs" />
<Compile Include="Helper\CEFHelper.cs" />
@@ -234,6 +239,7 @@
<Compile Include="Helper\WindowStyle.cs" />
<Compile Include="ImgConvertToIcon.cs" />
<Compile Include="Initialization.cs" />
<Compile Include="KJDServer.API\Models\OrderTask.cs" />
<Compile Include="Model\BaseModel.cs" />
<Compile Include="Model\ExpressBase.cs" />
<Compile Include="MulitServicerSet.cs" />
@@ -263,6 +269,8 @@
<DependentUpon>TokenForm.cs</DependentUpon>
</Compile>
<Compile Include="UserLogin.cs" />
<Compile Include="KJDServer.API\KJDServerHttp.cs" />
<Compile Include="KJDServer.API\WXOrder\WxOrderServiceApi.cs" />
<Compile Include="_29Tools\BLL\HttpResponseBLL.cs" />
<Compile Include="_29Tools\BLL\HttpResponseWXBLL.cs" />
<Compile Include="_29Tools\BLL\HttpResponseYkdBLL.cs" />
@@ -317,6 +325,10 @@
<Project>{6461d807-b1c8-45f0-b388-e0ca1a418de0}</Project>
<Name>29WxOrderAllBase</Name>
</ProjectReference>
<ProjectReference Include="..\WxOrder.Framework\WxOrder.Framework.csproj">
<Project>{3123963c-a0ec-4ad5-9916-dc063f73490b}</Project>
<Name>WxOrder.Framework</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\29wx.ico" />
+13
View File
@@ -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";
}
}
+40
View File
@@ -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<string> e57PostResponseAsync(string _url, string _data)
{
return HttpResponseWXBLL.e57PostResponseAsync(ERPConfig.Domain + _url, _data);
}
public static async Task<T> e57PostResponseAsync<T>(string _url, string _data) where T : Result, new()
{
try
{
string content = await HttpResponseWXBLL.e57PostResponseAsync(ERPConfig.Domain + _url, _data);
return JsonConvert.DeserializeObject<T>(content);
}
catch (JsonException)
{
return new T { Code = 0, Msg = "数据解析失败" };
}
catch (Exception ex)
{
return new T { Code = 0, Msg = ex.Message };
}
}
}
}
@@ -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<FailedItem> Data { get; set; }
public class FailedItem
{
public long shopId { get; set; }
public string shopName { get; set; }
public string message { get; set; }
}
}
/// <summary>
/// 拉取微信订单
/// </summary>
public class PullWXOrderServiceApi
{
/// <summary>
/// 拉取指定店铺的指定订单
/// </summary>
/// <param name="shopId">店铺ID</param>
/// <param name="orderId">订单号</param>
/// <returns>服务器异步任务ID;为 0 表示服务器已直接完成</returns>
/// <exception cref="Exception"></exception>
public async Task<bool> 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;
}
/// <summary>
/// 拉取指定店铺的订单列表
/// </summary>
/// <param name="shopId">店铺ID</param>
/// <param name="orderIds">订单号列表</param>
/// <returns>服务器异步任务ID;为 0 表示服务器已直接完成</returns>
/// <exception cref="Exception"></exception>
public async Task<bool> 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);
}
}
/// <summary>
/// 拉取指定商铺列表时间范围内的数据
/// </summary>
/// <param name="shopIds">店铺ID列表</param>
/// <param name="startTime">开始时间</param>
/// <param name="endTime">结束时间</param>
/// <returns>服务器异步任务ID;为 0 表示服务器已直接完成</returns>
/// <exception cref="Exception"></exception>
public async Task<bool> 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);
}
}
/// <summary>
/// 拉取指定店铺的售后订单
/// </summary>
/// <param name="shopIds">店铺ID列表</param>
/// <returns>服务器异步任务ID;为 0 表示服务器已直接完成</returns>
/// <exception cref="Exception"></exception>
public async Task<bool> 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);
}
}
/// <summary>
/// 拉取指定商铺的售后订单
/// </summary>
/// <param name="shopId">店铺ID</param>
/// <param name="afterSaleOrderIds">售后订单号列表</param>
/// <returns>服务器异步任务ID;为 0 表示服务器已直接完成</returns>
/// <exception cref="Exception"></exception>
public async Task<bool> 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);
}
}
/// <summary>
/// 提交拉取请求并从返回结果中解析服务器异步任务ID。
/// 兼容 data 为纯数字、数字字符串或对象(含 taskId/task_id/id 字段)等返回格式;
/// 无法解析时返回 0(视为服务器直接完成)。
/// </summary>
private async Task<PullWXOrderResult> PostAndGetTaskIdAsync(string url, string data)
{
var result = await ERPHttp.e57PostResponseAsync<PullWXOrderResult>(url, data);
if (result.Code != 200) throw new Exception(result.Msg);
return result;
}
}
}
+39
View File
@@ -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<bool> 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<Result>("/prod-api/api/oms-api/gift/order/deliveryFor29Erp", data);
if (result.Code != 200)
{
throw new Exception(result.Msg);
}
return true;
}
}
}
+26
View File
@@ -0,0 +1,26 @@
using System.ComponentModel;
namespace Work.ERP.API
{
/// <summary>
/// 服务器异步任务状态(与任务状态表字段一致:1=执行中,2=已完成,3=已人为中断)
/// </summary>
public enum TaskStatus
{
/// <summary>
/// 执行中
/// </summary>
[Description("执行中")]
Executing = 1,
/// <summary>
/// 已完成
/// </summary>
[Description("已完成")]
Completed = 2,
/// <summary>
/// 已人为中断
/// </summary>
[Description("已人为中断")]
ManuallyInterrupted = 3
}
}
+112
View File
@@ -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<string> 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<T> PostAsync<T>(string url, string data) where T : Result, new()
{
try
{
string result = await PostAsync(url, data);
return JsonConvert.DeserializeObject<T>(result);
}
catch (JsonException)
{
return new T { Code = 0, Msg = "数据解析失败" };
}
catch (Exception ex)
{
return new T { Code = 0, Msg = ex.Message };
}
}
private static async Task<string> _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();
}
}
}
}
}
+43
View File
@@ -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; }
}
}
@@ -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<List<OrderTask>> GetWxTaskStatus()
{
var ret = await KJDServerHttp.PostAsync<Result<List<OrderTask>>>("order/wx_get_task_status_list", "");
if (ret.Code == 200)
{
return ret.Data;
}
return null;
}
}
}
+3 -18
View File
@@ -659,7 +659,7 @@ namespace Work._29Tools.BLL
return result;
}
public static async Task<string> e57PostResponseAsync(string _url, string _data, string referer)
public static async Task<string> e57PostResponseAsync(string _url, string _data)
{
//await Task.Delay(2000);
//return await Task.FromResult("<AjaxResult><msg>SUCCESS</msg><code>200</code></AjaxResult>");
@@ -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");
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _29WxOrderWpf.Common
namespace WxOrder.Framework.Commons
{
public class Result
{
@@ -7,6 +7,14 @@
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<None Remove="Resources\Fonts\iconfont.ttf" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Fonts\iconfont.ttf" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="WPFCommon" Version="1.1.0" />
</ItemGroup>
+28
View File
@@ -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();
}
}
+29
View File
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PlatformTarget>x64</PlatformTarget>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="NUnit" Version="3.14.0" />
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="System.Drawing.Common" Version="10.0.11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\29WxOrderWpf\29WxOrderWpf.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="NUnit.Framework" />
</ItemGroup>
</Project>