From 7c6f91f2072e7b88de237112be5f7db6144074e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9Cchfei=E2=80=9D?= <“chaihongfei@126.com”>
Date: Wed, 5 Aug 2026 18:55:03 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8A=A0=20=E5=88=A9?=
=?UTF-8?q?=E6=B6=A6=E7=BB=9F=E8=AE=A1Window=E3=80=82=20=E9=9A=90=E8=97=8F?=
=?UTF-8?q?=E5=88=A9=E6=B6=A6=E7=BB=9F=E8=AE=A1=E6=8C=89=E9=92=AE=20?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=20Common=20=E6=96=87=E4=BB=B6=E5=A4=B9=20?=
=?UTF-8?q?=E5=86=85=E9=83=A8=E6=98=AFWPF=E5=85=AC=E7=94=A8=E7=B1=BB?=
=?UTF-8?q?=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
29WxOrderWpf/29WxOrderWpf.csproj | 47 +-
29WxOrderWpf/App.xaml | 4 +-
29WxOrderWpf/Common/DebugVisibility.cs | 56 +
29WxOrderWpf/Common/DelegateCommand.cs | 103 +
29WxOrderWpf/Common/DelegateCommandBase.cs | 135 +
29WxOrderWpf/Common/DelegateCommand{T}.cs | 119 +
29WxOrderWpf/Common/DialogWindow.xaml | 24 +
29WxOrderWpf/Common/DialogWindow.xaml.cs | 91 +
29WxOrderWpf/Common/DialogWindowProperty.cs | 50 +
29WxOrderWpf/Common/Result.cs | 31 +
.../Ctrls/OrderCtrls/OrderListCtrl.xaml | 9 +-
.../Ctrls/OrderCtrls/OrderListCtrl.xaml.cs | 3095 ++++++-------
.../Ctrls/Statistics/Charts/Chart.xaml | 17 +
.../Statistics/Charts/RevenueLineChart.xaml | 9 +
.../Charts/RevenueLineChart.xaml.cs | 242 +
.../Statistics/Charts/RevenuePieChart.xaml | 9 +
.../Statistics/Charts/RevenuePieChart.xaml.cs | 425 ++
29WxOrderWpf/Ctrls/Statistics/General.xaml | 8 +
.../Models/ShopRevenueStatisticsModels.cs | 256 ++
.../Services/ShopRevenueStatisticsService.cs | 443 ++
.../Statistics/ShopRevenueStatisticsView.xaml | 455 ++
.../ShopRevenueStatisticsView.xaml.cs | 25 +
.../ShopRevenueStatisticsViewModel.cs | 288 ++
AllBase/BaseClass.cs | 2 +-
AllBase/GetHtml.cs | 4073 +++++++++--------
25 files changed, 6462 insertions(+), 3554 deletions(-)
create mode 100644 29WxOrderWpf/Common/DebugVisibility.cs
create mode 100644 29WxOrderWpf/Common/DelegateCommand.cs
create mode 100644 29WxOrderWpf/Common/DelegateCommandBase.cs
create mode 100644 29WxOrderWpf/Common/DelegateCommand{T}.cs
create mode 100644 29WxOrderWpf/Common/DialogWindow.xaml
create mode 100644 29WxOrderWpf/Common/DialogWindow.xaml.cs
create mode 100644 29WxOrderWpf/Common/DialogWindowProperty.cs
create mode 100644 29WxOrderWpf/Common/Result.cs
create mode 100644 29WxOrderWpf/Ctrls/Statistics/Charts/Chart.xaml
create mode 100644 29WxOrderWpf/Ctrls/Statistics/Charts/RevenueLineChart.xaml
create mode 100644 29WxOrderWpf/Ctrls/Statistics/Charts/RevenueLineChart.xaml.cs
create mode 100644 29WxOrderWpf/Ctrls/Statistics/Charts/RevenuePieChart.xaml
create mode 100644 29WxOrderWpf/Ctrls/Statistics/Charts/RevenuePieChart.xaml.cs
create mode 100644 29WxOrderWpf/Ctrls/Statistics/General.xaml
create mode 100644 29WxOrderWpf/Ctrls/Statistics/Models/ShopRevenueStatisticsModels.cs
create mode 100644 29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs
create mode 100644 29WxOrderWpf/Ctrls/Statistics/ShopRevenueStatisticsView.xaml
create mode 100644 29WxOrderWpf/Ctrls/Statistics/ShopRevenueStatisticsView.xaml.cs
create mode 100644 29WxOrderWpf/Ctrls/Statistics/ViewModels/ShopRevenueStatisticsViewModel.cs
diff --git a/29WxOrderWpf/29WxOrderWpf.csproj b/29WxOrderWpf/29WxOrderWpf.csproj
index 4694fc4..6965a2c 100644
--- a/29WxOrderWpf/29WxOrderWpf.csproj
+++ b/29WxOrderWpf/29WxOrderWpf.csproj
@@ -68,7 +68,7 @@
true
- ..\..\KJD Cef138\Bin\
+ ..\..\KJD\Bin\
TRACE
true
pdbonly
@@ -140,6 +140,12 @@
+
+
+
+
+
+
@@ -153,6 +159,9 @@
PDDBuyerSelectCtrl.xaml
+
+ DialogWindow.xaml
+
OrderListRowCtrl.xaml
@@ -168,6 +177,18 @@
ShopListCtrl.xaml
+
+ RevenueLineChart.xaml
+
+
+ RevenuePieChart.xaml
+
+
+
+
+ ShopRevenueStatisticsView.xaml
+
+
UcWaterMarkTextBox.xaml
@@ -202,6 +223,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
MSBuild:Compile
Designer
@@ -222,6 +247,26 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/29WxOrderWpf/App.xaml b/29WxOrderWpf/App.xaml
index b8a97d1..bcd645e 100644
--- a/29WxOrderWpf/App.xaml
+++ b/29WxOrderWpf/App.xaml
@@ -28,8 +28,8 @@
-
-
+
+
diff --git a/29WxOrderWpf/Common/DebugVisibility.cs b/29WxOrderWpf/Common/DebugVisibility.cs
new file mode 100644
index 0000000..cc604a7
--- /dev/null
+++ b/29WxOrderWpf/Common/DebugVisibility.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace _29WxOrderWpf.Common
+{
+ public static class DebugVisibility
+ {
+ // 定义一个附加属性
+ public static readonly DependencyProperty EnableProperty =
+ DependencyProperty.RegisterAttached(
+ "Enable",
+ typeof(bool),
+ typeof(DebugVisibility),
+ new FrameworkPropertyMetadata(
+ true, FrameworkPropertyMetadataOptions.AffectsArrange,
+ OnEnableChanged, OnEnableCoerceCall));
+
+ private static object OnEnableCoerceCall(DependencyObject d, object baseValue)
+ {
+ if (d is UIElement element)
+ {
+#if DEBUG
+ // Debug 模式下,根据属性值决定可见性
+ element.Visibility = (bool)baseValue ? Visibility.Visible : Visibility.Collapsed;
+#else
+ // Release 模式下,隐藏所有标记了 IsDebug 的元素
+ element.Visibility = Visibility.Collapsed;
+#endif
+ }
+
+ return baseValue;
+ }
+
+ private static void OnEnableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is UIElement element)
+ {
+#if DEBUG
+ // Debug 模式下,根据属性值决定可见性
+ element.Visibility = (bool)e.NewValue ? Visibility.Visible : Visibility.Collapsed;
+#else
+ // Release 模式下,隐藏所有标记了 IsDebug 的元素
+ element.Visibility = Visibility.Collapsed;
+#endif
+ }
+ }
+
+ public static bool GetEnable(DependencyObject obj) => (bool)obj.GetValue(EnableProperty);
+ public static void SetEnable(DependencyObject obj, bool value) => obj.SetValue(EnableProperty, value);
+
+ }
+}
diff --git a/29WxOrderWpf/Common/DelegateCommand.cs b/29WxOrderWpf/Common/DelegateCommand.cs
new file mode 100644
index 0000000..498d8db
--- /dev/null
+++ b/29WxOrderWpf/Common/DelegateCommand.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Linq.Expressions;
+using System.Windows.Input;
+
+namespace _29WxOrderWpf.Commands
+{
+ ///
+ /// An whose delegates do not take any parameters for and .
+ ///
+ ///
+ ///
+ public class DelegateCommand : DelegateCommandBase
+ {
+ Action _executeMethod;
+ Func _canExecuteMethod;
+
+ ///
+ /// Creates a new instance of with the to invoke on execution.
+ ///
+ /// The to invoke when is called.
+ public DelegateCommand(Action executeMethod)
+ : this(executeMethod, () => true)
+ {
+
+ }
+
+ ///
+ /// Creates a new instance of with the to invoke on execution
+ /// and a to query for determining if the command can execute.
+ ///
+ /// The to invoke when is called.
+ /// The to invoke when is called
+ public DelegateCommand(Action executeMethod, Func canExecuteMethod)
+ : base()
+ {
+ if (executeMethod == null || canExecuteMethod == null)
+ throw new ArgumentNullException(nameof(executeMethod), "Delegate Command Delegates Cannot Be Null");
+
+ _executeMethod = executeMethod;
+ _canExecuteMethod = canExecuteMethod;
+ }
+
+ ///
+ /// Executes the command.
+ ///
+ public void Execute()
+ {
+ _executeMethod();
+ }
+
+ ///
+ /// Determines if the command can be executed.
+ ///
+ /// Returns if the command can execute,otherwise returns .
+ public bool CanExecute()
+ {
+ return _canExecuteMethod();
+ }
+
+ ///
+ /// Handle the internal invocation of
+ ///
+ /// Command Parameter
+ protected override void Execute(object parameter)
+ {
+ Execute();
+ }
+
+ ///
+ /// Handle the internal invocation of
+ ///
+ ///
+ /// if the Command Can Execute, otherwise
+ protected override bool CanExecute(object parameter)
+ {
+ return CanExecute();
+ }
+
+ ///
+ /// Observes a property that implements INotifyPropertyChanged, and automatically calls DelegateCommandBase.RaiseCanExecuteChanged on property changed notifications.
+ ///
+ /// The object type containing the property specified in the expression.
+ /// The property expression. Example: ObservesProperty(() => PropertyName).
+ /// The current instance of DelegateCommand
+ public DelegateCommand ObservesProperty(Expression> propertyExpression)
+ {
+ ObservesPropertyInternal(propertyExpression);
+ return this;
+ }
+
+ ///
+ /// Observes a property that is used to determine if this command can execute, and if it implements INotifyPropertyChanged it will automatically call DelegateCommandBase.RaiseCanExecuteChanged on property changed notifications.
+ ///
+ /// The property expression. Example: ObservesCanExecute(() => PropertyName).
+ /// The current instance of DelegateCommand
+ public DelegateCommand ObservesCanExecute(Expression> canExecuteExpression)
+ {
+ _canExecuteMethod = canExecuteExpression.Compile();
+ ObservesPropertyInternal(canExecuteExpression);
+ return this;
+ }
+ }
+}
diff --git a/29WxOrderWpf/Common/DelegateCommandBase.cs b/29WxOrderWpf/Common/DelegateCommandBase.cs
new file mode 100644
index 0000000..3f26b66
--- /dev/null
+++ b/29WxOrderWpf/Common/DelegateCommandBase.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace _29WxOrderWpf.Commands
+{
+ public abstract class DelegateCommandBase : ICommand
+ {
+ private bool _isActive;
+
+ private SynchronizationContext _synchronizationContext;
+ private readonly HashSet _observedPropertiesExpressions = new HashSet();
+
+ ///
+ /// Creates a new instance of a , specifying both the execute action and the can execute function.
+ ///
+ protected DelegateCommandBase()
+ {
+ _synchronizationContext = SynchronizationContext.Current;
+ }
+
+ ///
+ /// Occurs when changes occur that affect whether or not the command should execute.
+ ///
+ public virtual event EventHandler CanExecuteChanged;
+
+ ///
+ /// Raises so every
+ /// command invoker can requery .
+ ///
+ protected virtual void OnCanExecuteChanged()
+ {
+ var handler = CanExecuteChanged;
+ if (handler != null)
+ {
+ if (_synchronizationContext != null && _synchronizationContext != SynchronizationContext.Current)
+ _synchronizationContext.Post((o) => handler.Invoke(this, EventArgs.Empty), null);
+ else
+ handler.Invoke(this, EventArgs.Empty);
+ }
+ }
+
+ ///
+ /// Raises so every command invoker
+ /// can requery to check if the command can execute.
+ ///
+ /// Note that this will trigger the execution of once for each invoker.
+ [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
+ public void RaiseCanExecuteChanged()
+ {
+ OnCanExecuteChanged();
+ }
+
+ void ICommand.Execute(object parameter)
+ {
+ Execute(parameter);
+ }
+
+ bool ICommand.CanExecute(object parameter)
+ {
+ return CanExecute(parameter);
+ }
+
+ ///
+ /// Handle the internal invocation of
+ ///
+ /// Command Parameter
+ protected abstract void Execute(object parameter);
+
+ ///
+ /// Handle the internal invocation of
+ ///
+ ///
+ /// if the Command Can Execute, otherwise
+ protected abstract bool CanExecute(object parameter);
+
+ ///
+ /// Observes a property that implements INotifyPropertyChanged, and automatically calls DelegateCommandBase.RaiseCanExecuteChanged on property changed notifications.
+ ///
+ /// The object type containing the property specified in the expression.
+ /// The property expression. Example: ObservesProperty(() => PropertyName).
+ protected internal void ObservesPropertyInternal(Expression> propertyExpression)
+ {
+ if (_observedPropertiesExpressions.Contains(propertyExpression.ToString()))
+ {
+ throw new ArgumentException($"{propertyExpression.ToString()} is already being observed.",
+ nameof(propertyExpression));
+ }
+ else
+ {
+ _observedPropertiesExpressions.Add(propertyExpression.ToString());
+ }
+ }
+
+ #region IsActive
+
+ ///
+ /// Gets or sets a value indicating whether the object is active.
+ ///
+ /// if the object is active; otherwise .
+ public bool IsActive
+ {
+ get { return _isActive; }
+ set
+ {
+ if (_isActive != value)
+ {
+ _isActive = value;
+ OnIsActiveChanged();
+ }
+ }
+ }
+
+ ///
+ /// Fired if the property changes.
+ ///
+ public virtual event EventHandler IsActiveChanged;
+
+ ///
+ /// This raises the event.
+ ///
+ protected virtual void OnIsActiveChanged()
+ {
+ IsActiveChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ #endregion
+ }
+}
diff --git a/29WxOrderWpf/Common/DelegateCommand{T}.cs b/29WxOrderWpf/Common/DelegateCommand{T}.cs
new file mode 100644
index 0000000..8e29aa6
--- /dev/null
+++ b/29WxOrderWpf/Common/DelegateCommand{T}.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Windows.Input;
+
+namespace _29WxOrderWpf.Commands
+{
+
+ public class DelegateCommand : DelegateCommandBase
+ {
+ readonly Action _executeMethod;
+ Func _canExecuteMethod;
+
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.
+ /// will always return true.
+ public DelegateCommand(Action executeMethod)
+ : this(executeMethod, (o) => true)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.
+ /// Delegate to execute when CanExecute is called on the command. This can be null.
+ /// When both and are .
+ public DelegateCommand(Action executeMethod, Func canExecuteMethod)
+ : base()
+ {
+ if (executeMethod == null || canExecuteMethod == null)
+ throw new ArgumentNullException(nameof(executeMethod), "Delegate Command Delegates Cannot Be Null");
+
+ TypeInfo genericTypeInfo = typeof(T).GetTypeInfo();
+
+ // DelegateCommand allows object or Nullable<>.
+ // note: Nullable<> is a struct so we cannot use a class constraint.
+ if (genericTypeInfo.IsValueType)
+ {
+ if (!genericTypeInfo.IsGenericType || !typeof(Nullable<>).GetTypeInfo().IsAssignableFrom(genericTypeInfo.GetGenericTypeDefinition().GetTypeInfo()))
+ {
+ throw new InvalidCastException("Delegate CommandInvalid Generic Payload Type");
+ }
+ }
+
+ _executeMethod = executeMethod;
+ _canExecuteMethod = canExecuteMethod;
+ }
+
+ ///
+ ///Executes the command and invokes the provided during construction.
+ ///
+ ///Data used by the command.
+ public void Execute(T parameter)
+ {
+ _executeMethod(parameter);
+ }
+
+ ///
+ ///Determines if the command can execute by invoked the provided during construction.
+ ///
+ ///Data used by the command to determine if it can execute.
+ ///
+ /// if this command can be executed; otherwise, .
+ ///
+ public bool CanExecute(T parameter)
+ {
+ return _canExecuteMethod(parameter);
+ }
+
+ ///
+ /// Handle the internal invocation of
+ ///
+ /// Command Parameter
+ protected override void Execute(object parameter)
+ {
+ Execute((T)parameter);
+ }
+
+ ///
+ /// Handle the internal invocation of
+ ///
+ ///
+ /// if the Command Can Execute, otherwise
+ protected override bool CanExecute(object parameter)
+ {
+ return CanExecute((T)parameter);
+ }
+
+ ///
+ /// Observes a property that implements INotifyPropertyChanged, and automatically calls DelegateCommandBase.RaiseCanExecuteChanged on property changed notifications.
+ ///
+ /// The type of the return value of the method that this delegate encapsulates
+ /// The property expression. Example: ObservesProperty(() => PropertyName).
+ /// The current instance of DelegateCommand
+ public DelegateCommand ObservesProperty(Expression> propertyExpression)
+ {
+ ObservesPropertyInternal(propertyExpression);
+ return this;
+ }
+
+ ///
+ /// Observes a property that is used to determine if this command can execute, and if it implements INotifyPropertyChanged it will automatically call DelegateCommandBase.RaiseCanExecuteChanged on property changed notifications.
+ ///
+ /// The property expression. Example: ObservesCanExecute(() => PropertyName).
+ /// The current instance of DelegateCommand
+ public DelegateCommand ObservesCanExecute(Expression> canExecuteExpression)
+ {
+ Expression> expression = Expression.Lambda>(canExecuteExpression.Body, Expression.Parameter(typeof(T), "o"));
+ _canExecuteMethod = expression.Compile();
+ ObservesPropertyInternal(canExecuteExpression);
+ return this;
+ }
+ }
+
+
+}
diff --git a/29WxOrderWpf/Common/DialogWindow.xaml b/29WxOrderWpf/Common/DialogWindow.xaml
new file mode 100644
index 0000000..74fa3bf
--- /dev/null
+++ b/29WxOrderWpf/Common/DialogWindow.xaml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/29WxOrderWpf/Common/DialogWindow.xaml.cs b/29WxOrderWpf/Common/DialogWindow.xaml.cs
new file mode 100644
index 0000000..5190abe
--- /dev/null
+++ b/29WxOrderWpf/Common/DialogWindow.xaml.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+
+
+namespace _29WxOrderWpf.Common
+{
+ ///
+ /// DialogWindow.xaml 的交互逻辑
+ ///
+ public partial class DialogWindow : Window
+ {
+ private readonly Style dialogWindowStyle;
+ private bool isConstructorSuccessful = false;
+ public DialogWindow()
+ {
+ InitializeComponent();
+ Owner = Application.Current.MainWindow;
+ isConstructorSuccessful = true;
+ dialogWindowStyle = (Style)TryFindResource("DialogWindowStyle");
+
+ Loaded += DialogWindow_Loaded;
+ }
+ private void DialogWindow_Loaded(object sender, RoutedEventArgs e)
+ {
+ Loaded -= DialogWindow_Loaded;
+
+ }
+ protected override void OnContentChanged(object oldContent, object newContent)
+ {
+ this.Style = dialogWindowStyle;
+ if (newContent is System.Windows.Controls.UserControl control)
+ {
+
+ Setter widthSetter = this.Style.Setters.OfType().FirstOrDefault(a => a.Property == WidthProperty);
+ if (widthSetter == null)
+ {
+ if (double.IsNaN(control.Width))
+ {
+ this.Width = DialogWindowProperty.GetWidth(control);
+ }
+ else
+ {
+ this.Width = control.Width;
+ control.Width = double.NaN;
+ }
+ }
+
+
+ Setter heightSetter = this.Style.Setters.OfType().FirstOrDefault(a => a.Property == HeightProperty);
+ if (heightSetter == null)
+ {
+ if (double.IsNaN(control.Height))
+ {
+ this.Height = DialogWindowProperty.GetHeight(control);
+ }
+ else
+ {
+ this.Height = control.Height;
+ control.Height = double.NaN;
+ }
+ }
+
+
+ ResizeMode resizeExt = DialogWindowProperty.GetResizeMode(control);
+ if (resizeExt != ResizeMode.CanResize)
+ {
+ this.ResizeMode = resizeExt;
+ }
+
+ }
+ base.OnContentChanged(oldContent, newContent);
+ }
+
+ protected override void OnStyleChanged(Style oldStyle, Style newStyle)
+ {
+ if (newStyle.TargetType == typeof(Window))
+ {
+ if (isConstructorSuccessful)
+ {
+ //dialogWindowStyle.Merge(newStyle);
+ }
+ return;
+ }
+ base.OnStyleChanged(oldStyle, newStyle);
+ }
+ }
+}
diff --git a/29WxOrderWpf/Common/DialogWindowProperty.cs b/29WxOrderWpf/Common/DialogWindowProperty.cs
new file mode 100644
index 0000000..4c287d3
--- /dev/null
+++ b/29WxOrderWpf/Common/DialogWindowProperty.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace _29WxOrderWpf.Common
+{
+ ///
+ /// 弹出窗口属性值
+ ///
+ public class DialogWindowProperty
+ {
+ public static readonly DependencyProperty WindowStartupLocationProperty = DependencyProperty.RegisterAttached(
+ "WindowStartupLocation", typeof(WindowStartupLocation), typeof(DialogWindowProperty), new PropertyMetadata(WindowStartupLocation.CenterScreen));
+ public static void SetWindowStartupLocation(DependencyObject element, WindowStartupLocation value)
+ => element.SetValue(WindowStartupLocationProperty, value);
+ public static WindowStartupLocation GetWindowStartupLocation(DependencyObject element)
+ => (WindowStartupLocation)element.GetValue(WindowStartupLocationProperty);
+
+
+ public static readonly DependencyProperty ResizeModeProperty = DependencyProperty.RegisterAttached(
+ "ResizeMode", typeof(ResizeMode), typeof(DialogWindowProperty), new PropertyMetadata(ResizeMode.CanResize));
+ public static void SetResizeMode(DependencyObject element, ResizeMode value)
+ => element.SetValue(ResizeModeProperty, value);
+ public static ResizeMode GetResizeMode(DependencyObject element)
+ => (ResizeMode)element.GetValue(ResizeModeProperty);
+
+
+
+ public static readonly DependencyProperty WidthProperty = DependencyProperty.RegisterAttached(
+ "Width", typeof(double), typeof(DialogWindowProperty), new PropertyMetadata(double.NaN));
+ public static void SetWidth(DependencyObject element, double value)
+ => element.SetValue(WidthProperty, value);
+ public static double GetWidth(DependencyObject element)
+ => (double)element.GetValue(WidthProperty);
+
+
+
+ public static readonly DependencyProperty HeightProperty = DependencyProperty.RegisterAttached(
+ "Height", typeof(double), typeof(DialogWindowProperty), new PropertyMetadata(double.NaN));
+ public static void SetHeight(DependencyObject element, double value)
+ => element.SetValue(HeightProperty, value);
+ public static double GetHeight(DependencyObject element)
+ => (double)element.GetValue(HeightProperty);
+
+
+ }
+}
diff --git a/29WxOrderWpf/Common/Result.cs b/29WxOrderWpf/Common/Result.cs
new file mode 100644
index 0000000..43f7e9e
--- /dev/null
+++ b/29WxOrderWpf/Common/Result.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace _29WxOrderWpf.Common
+{
+ public class Result
+ {
+ public Result()
+ {
+
+ }
+ public Result(int code, string msg)
+ {
+ Code = code;
+ Msg = msg;
+ }
+
+ public int Code { get; set; }
+ public string Msg { get; set; }
+
+ }
+
+ public class Result : Result
+ {
+ public TData Data { get; set; }
+ }
+
+}
diff --git a/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml b/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml
index b41a87f..20e4fae 100644
--- a/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml
+++ b/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml
@@ -2,6 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:c="clr-namespace:_29WxOrderWpf.Common"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:_29WxOrderWpf.Ctrls.OrderCtrls"
xmlns:utils="clr-namespace:_29WxOrderWpf.Utils"
@@ -37,7 +38,8 @@
-
+
+
@@ -93,7 +95,12 @@
+
+
+
diff --git a/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml.cs b/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml.cs
index a454768..04092b1 100644
--- a/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml.cs
+++ b/29WxOrderWpf/Ctrls/OrderCtrls/OrderListCtrl.xaml.cs
@@ -1,5 +1,7 @@
using _29WxOrderWpf.BaseWindows;
+using _29WxOrderWpf.Common;
using _29WxOrderWpf.Ctrls.BuyerCtrls;
+using _29WxOrderWpf.Ctrls.Statistics;
using _29WxOrderWpf.Utils;
using AllBase;
using AllBase.Extension;
@@ -37,1545 +39,1556 @@ using static System.Net.Mime.MediaTypeNames;
namespace _29WxOrderWpf.Ctrls.OrderCtrls
{
- ///
- /// OrderListCtrl.xaml 的交互逻辑
- ///
- public partial class OrderListCtrl : UserControl
- {
- public CheckBox chkSelectAll = null;
-
- public bool IsAutoReadOrder = true;
- public DateTime nextGetOrderTime = DateTime.MinValue;
-
- public string strSearchAll = "";
- public List lstFilterText { get; set; }
-
- public OrderListCtrl()
- {
- InitializeComponent();
- DataContext = this;
- }
-
- private void Window_Loaded(object sender, RoutedEventArgs e)
- {
- lbxOrder.ItemsSource = GlobalConfig.lstFilterOrder;
-
- dateStart.SelectedDate = DateTime.Now.Date.AddDays(-7);
- dateEnd.SelectedDate = DateTime.Now.Date.AddDays(1).AddSeconds(-1);
-
- borderFilterRemarkSelect.Visibility = Visibility.Collapsed;
-
- AutoGetOrder();
- }
-
- public void GetOrderTest()
- {
- for (int i = 0; i < 10000; i++)
- {
- //lstOrder.Add(new oms_wei_order_info() { id = 1, IsSelect = false, order_id = ("3737033423685556736".ParseToLong() + Randomx.GetId(0,100)).ParseToString(), shop_name = "媛卡曦工厂优选" });
- GlobalConfig.lstOrder.Add(new oms_wei_order_info() { id = 1, IsSelect = false, order_id = Randomx.GetId(1000, 10000).ParseToString(), shop_name = "媛卡曦工厂优选" });
- }
- //GlobalConfig.lstOrder.SortDesc(o => o.order_id.ParseToLong());
- }
-
- public void AutoGetOrder()
- {
- Task.Run(() =>
- {
- Thread.Sleep(5000);
- while (true)
- {
- if (!IsAutoReadOrder)
- {
- Thread.Sleep(1000);
- Dispatcher.Invoke(new Action(() =>
- {
- btnSearch.Content = "自动读单暂停中";
- imgLoading.Visibility = Visibility.Collapsed;
- }));
- continue;
- }
-
- if (DateTime.Now > nextGetOrderTime)
- {
- GetOrder();
-
- nextGetOrderTime = DateTime.Now.AddMinutes(25);
- }
- Thread.Sleep(1000);
- Dispatcher.Invoke(new Action(() =>
- {
- var ticks = nextGetOrderTime - DateTime.Now;
- btnSearch.Content = "读单 " + ticks.Minutes.ToString("00") + ":" + ticks.Seconds.ToString("00");
- }));
- }
- });
- }
-
-
- public bool hasReadOrder = false;
- ///
- ///
- ///
- /// 按过滤条件读取读取服务端订单
- public void GetOrder(string orderIds = "", bool filterGetCondition = false)
- {
- Dispatcher.Invoke(new Action(() =>
- {
- imgLoading.Visibility = Visibility.Visible;
- btnSearch.IsEnabled = false;
- }));
- int page = 0;
- int totalPage = 1;
- int pageSize = 50;
-
- while (true && (IsAutoReadOrder || !string.IsNullOrEmpty(orderIds)))
- {
- if (page >= totalPage)
- {
- break;
- }
- Dispatcher.Invoke(new Action(() =>
- {
- imgLoading.Visibility = Visibility.Visible;
- btnSearch.IsEnabled = false;
- }));
-
- page++;
- var url = BaseClass.Build29WxObjString("order/get_erp_order_list");
- var data = UserLogin.GetSignaturex() + "&page=" + page;
- if (!string.IsNullOrEmpty(orderIds))
- data += "&erp_order_id_in=" + orderIds;
- if (page > 1)
- data += "&is_not_count=true";
- data += "&page_size=" + pageSize;
- var shop_id = string.Join(",", GlobalConfig.ShopLoginList.Select(s => s.ErpShopId).Where(s => !s.IsNullOrEmpty()));
- //指定订单id的查询,不再查询店铺id
- if (string.IsNullOrEmpty(orderIds))
- data += "&erp_shop_id_in=" + shop_id;
- Dispatcher.Invoke(new Action(() =>
- {
- // 按过滤条件读取
- if (filterGetCondition)
- {
- if (!string.IsNullOrEmpty(txtShopName.Text.Trim()))
- {
- var shopNames = txtShopName.Text.Trim().Split(';').Where(s => !s.IsNullOrEmpty()).ToList();
- shop_id = string.Join(",", GlobalConfig.ShopLoginList.Where(s => shopNames.Contains(s.ShopAccount)).Select(s => s.ErpShopId).Where(s => !s.IsNullOrEmpty()));
- }
- }
- var startTime = BaseClass.DateTimeToTimestampSeconds(dateStart.SelectedDate.Value);
- var endTime = BaseClass.DateTimeToTimestampSeconds(dateEnd.SelectedDate.Value.AddDays(1));
- if (!chkEndDate.IsChecked.ParseToBool())
- endTime = BaseClass.DateTimeToTimestampSeconds(DateTime.Now.Date.AddDays(1));
- data += "&start_time=" + startTime;
- data += "&end_time=" + endTime;
- }));
- Thread.Sleep(200);
- var html = GetHtml.PostUtf8(url, data);
- if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
- html = GetHtml.PostUtf8(url, data);
- if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
- {
- BaseMsgWindow.ShowError("订单读取失败 " + BaseRegex.GetStringJson(ref html, "msg"));
- break;
- }
- var seconds = BaseRegex.GetDecimalJson(ref html, "seconds");
-
- var jArr = JObject.Parse(html)["data"];
- if (jArr.Count() == 0)
- break;
-
- var order_ids = string.Join(",", jArr.Select(a => a["order_id"].ParseToString()));
-
- // 读取订单详情
- if (string.IsNullOrEmpty(order_ids))
- Thread.Sleep(100);
- List orderItems = GetOrderItemInfo(order_ids);
-
- // 读取售后单
- if (string.IsNullOrEmpty(order_ids))
- Thread.Sleep(100);
- List refunds = GetOrderRefundInfo(order_ids);
-
- // 读订单扩展
- if (string.IsNullOrEmpty(order_ids))
- Thread.Sleep(100);
- List orderItemExts = GetOrderItemExts(order_ids);
- if (string.IsNullOrEmpty(order_ids))
- {
- foreach (var oie in orderItemExts)
- {
- // 移除订单物流异常信息,每次批量读单最后要去微信获取
- oie.abnormal_text = "";
- }
- }
-
- // 读取中转仓拍单订单
- var url3 = BaseClass.Build29WxObjString("order/wx_get_transit_order");
- var data3 = UserLogin.GetSignaturex();
- data3 += "&order_no=" + order_ids;
- var html3 = GetHtml.PostUtf8(url3, data3);
- if (string.IsNullOrEmpty(html3) || !html3.Contains("\"code\":200"))
- html3 = GetHtml.PostUtf8(url3, data3);
- if (string.IsNullOrEmpty(html3) || !html3.Contains("\"code\":200"))
- {
- BaseMsgWindow.ShowError("订单读取失败 " + BaseRegex.GetStringJson(ref html3, "msg"));
- break;
- }
- List transitOrderList = new List();
- try
- {
- transitOrderList = JsonHelper.DeserializeJsonToList(JObject.Parse(html3)["data"].ParseToString());
- }
- catch { }
-
- // 读取暂时记录的买手订单,后面想办法放到中转订单库里去
- var url4 = BaseClass.Build29WxObjString("order/wx_get_buyer_order_list");
- var data4 = UserLogin.GetSignaturex();
- data4 += "&wx_order_id_in=" + order_ids;
- var html4 = GetHtml.PostUtf8(url4, data4);
- if (string.IsNullOrEmpty(html4) || !html4.Contains("\"code\":200"))
- html4 = GetHtml.PostUtf8(url4, data4);
- if (string.IsNullOrEmpty(html4) || !html4.Contains("\"code\":200"))
- {
- Dispatcher.Invoke(new Action(() =>
- {
- BaseMsgWindow.ShowError("订单读取失败(买手) " + BaseRegex.GetStringJson(ref html4, "msg"));
- }));
- break;
- }
- List pddBuyerOrders = new List();
- try
- {
- pddBuyerOrders = JsonHelper.DeserializeJsonToList(JObject.Parse(html4)["data"].ParseToString())
- .OrderByDescending(p => p.TransitCreateTime).ToList();
- }
- catch { }
-
- // 读取暂时记录的买手售后单,后面想办法放到中转订单库里去
- var url6 = BaseClass.Build29WxObjString("order/wx_get_buyer_after_sale_list");
- var data6 = UserLogin.GetSignaturex();
- data6 += "&wx_order_id_in=" + order_ids;
- List pddBuyerAfterSales = new List();
- if (!string.IsNullOrEmpty(order_ids))
- {
- var html6 = GetHtml.PostUtf8(url6, data6);
- if (string.IsNullOrEmpty(html6) || !html6.Contains("\"code\":200"))
- html6 = GetHtml.PostUtf8(url6, data6);
- if (string.IsNullOrEmpty(html6) || !html6.Contains("\"code\":200"))
- {
- BaseMsgWindow.ShowError("订单读取失败(买手售后) " + BaseRegex.GetStringJson(ref html6, "msg"));
- break;
- }
- try
- {
- pddBuyerAfterSales = JsonHelper.DeserializeJsonToList(JObject.Parse(html6)["data"].ParseToString())
- .OrderByDescending(p => p.TransitCreateTime).ToList();
- }
- catch
- {
- }
- }
-
- // 读取中转仓处理售后单
- var url5 = BaseClass.Build29WxObjString("order/wx_get_transit_warehouse_aftersale_list");
- var data5 = UserLogin.GetSignaturex();
- data5 += "&wx_order_id_in=" + order_ids;
- var html5 = GetHtml.PostUtf8(url5, data5);
- if (string.IsNullOrEmpty(html5) || !html5.Contains("\"code\":200"))
- html5 = GetHtml.PostUtf8(url5, data5);
- if (string.IsNullOrEmpty(html5) || !html5.Contains("\"code\":200"))
- {
- Dispatcher.Invoke(new Action(() =>
- {
- BaseMsgWindow.ShowError("订单读取失败 " + BaseRegex.GetStringJson(ref html5, "msg"));
- }));
- break;
- }
- List transitAfterSaleList = new List();
- try
- {
- transitAfterSaleList = JsonHelper.DeserializeJsonToList(JObject.Parse(html5)["data"].ParseToString())
- .OrderByDescending(p => p.created_time).ToList();
- }
- catch { }
-
-
- // 读取关联拍单商品
- var urlMap = BaseClass.Build29WxObjString("order/wx_get_buy_prod_map");
- var dataMap = UserLogin.GetSignaturex()
- + "&spu_codes=" + string.Join(",", orderItems.Select(oi => GetHtml.UrlEncodeUtf8(oi.out_product_id))) + "," + string.Join(",", orderItems.Select(oi => oi.product_id));
- dataMap += "&main_user_name=" + BaseClass.MainUserName;
- var resultMap = GetHtml.PostUtf8(urlMap, dataMap);
- if (string.IsNullOrEmpty(resultMap) || !resultMap.Contains("\"code\":200"))
- resultMap = GetHtml.PostUtf8(urlMap, dataMap);
- if (string.IsNullOrEmpty(resultMap) || !resultMap.Contains("\"code\":200"))
- {
- Dispatcher.Invoke(new Action(() =>
- {
- BaseMsgWindow.ShowError("订单读取失败 " + BaseRegex.GetStringJson(ref resultMap, "msg"));
- }));
- break;
- }
- List byuMapList = new List();
- try { byuMapList = JsonHelper.DeserializeJsonToList(JObject.Parse(resultMap)["data"].ParseToString()); } catch { }
-
-
- // 装载订单
- foreach (JObject jObj in jArr)
- {
- try
- {
- oms_wei_order_info order = null;
- order = JsonHelper.DeserializeJsonToObject(JsonHelper.SerializeObject(jObj));
-
- //装载订单商品详情
- order.orderItems = new ObservableCollection();
- foreach (var item in orderItems.Where(oi => oi.order_id == order.order_id))
- {
- // 订单商品
- item.ItemOrder = order;
- order.orderItems.Add(item);
-
- item.OrderItemExt = orderItemExts.FirstOrDefault(ext => ext.order_id == item.order_id && item.sku_id == item.sku_id);
-
- // 已放到赋值函数中处理
- // 更新店铺是否加入代发情况
- //item.Shop = GlobalConfig.ShopLoginList.FirstOrDefault(s => s.ErpShopId == item.order_id);
- //Dispatcher.Invoke(new Action(() => { item.UpdateOrderItemBuyButton(); }));
-
- // 关联拍单关系 // 危险物品禁止拍单,仅关联安全商品
- if (!GlobalConfig.lstDangerItemWord.Any(d => (item.title).ParseToString().Contains(d)))
- {
- item.BuyMap = byuMapList.FirstOrDefault(b => b.sku_code == item.out_sku_id && b.spu_code == item.out_product_id);
- if (item.BuyMap == null)
- item.BuyMap = byuMapList.FirstOrDefault(b => b.sku_code == item.sku_attr_str && b.spu_code == item.out_product_id);
- if (item.BuyMap == null)
- item.BuyMap = byuMapList.FirstOrDefault(b => b.sku_code == item.out_sku_id && b.spu_code == item.product_id);
- if (item.BuyMap == null)
- item.BuyMap = byuMapList.FirstOrDefault(b => b.sku_code == item.sku_attr_str && b.spu_code == item.product_id);
- }
-
- // 中转仓订单
- if (item.ItemOrder.orderItems.Count > 1)
- item.ItemTransitOrders.AddRange(transitOrderList.Where(t => t.order_no == item.order_id && t.order_sku_id == item.sku_id));
- else
- item.ItemTransitOrders.AddRange(transitOrderList.Where(t => t.order_no == item.order_id));
- // 中转仓退货包裹订单
- item.ItemTransitOrderAfterSales = transitAfterSaleList.Where(a => item.ItemTransitOrders.Any(t => t.out_order_no == a.order_code)).ToList();
-
- // 中转仓买手订单(wx_send_type等于0)
- item.PddBuyerOrders = pddBuyerOrders.Where(po => po.wx_order_id == item.order_id && po.wx_sku_id == item.sku_id && po.wx_send_type == 0).ToList();
- // 中转仓买手退货订单(wx_send_type等于0)
- item.PddBuyerAfterSales = pddBuyerAfterSales.Where(po => po.wx_order_id == item.order_id && po.wx_sku_id == item.sku_id && po.wx_send_type == 0).ToList();
- // 直发买手订单(wx_send_type等于1)
- item.PddBuyerOrders = pddBuyerOrders.Where(po => po.wx_order_id == item.order_id && po.wx_sku_id == item.sku_id && po.wx_send_type == 1).ToList();
- // 直发买手退款订单(wx_send_type等于1)
- item.DirectPddBuyerAfterSales = pddBuyerAfterSales.Where(po => po.wx_order_id == item.order_id && po.wx_sku_id == item.sku_id && po.wx_send_type == 1).ToList();
- }
-
- // 装载订单售后详情
- order.refundItems = new ObservableCollection(refunds.Where(of => of.order_id == order.order_id));
-
- // 读取订单后立即赋值,防止滚动时实时赋值造成卡顿
- foreach (var orderItem in order.orderItems)
- {
- orderItem.SetOrderItemTextProperty();
- }
- order.SetOrderTextProperty();
-
- // 删除再添加,触发更新。 todo: 如果已存在相同订单,则直接修改更新
- var orderExist = GlobalConfig.lstOrder.FirstOrDefault(o => o.order_id == order.order_id);
- while (orderExist != null)
- {
- GlobalConfig.lstOrder.Remove(orderExist);
- orderExist = GlobalConfig.lstOrder.FirstOrDefault(o => o.order_id == order.order_id);
- }
- GlobalConfig.lstOrder.Add(order);
-
- Dispatcher.Invoke(new Action(() =>
- {
- FilterOneOrder(order);
- }));
- }
- catch (Exception ex)
- {
- }
- }
-
- Dispatcher.Invoke(new Action(() =>
- {
- disPlayOrderTabOrderCount();
- }));
-
- var totalCount = BaseRegex.GetIntJson(ref html, "count");
- if (totalCount > 0)
- totalPage = Math.Ceiling(1m * totalCount / pageSize).ParseToInt();
- else
- {
-
- }
- }
-
- if (string.IsNullOrEmpty(orderIds))
- GetShopWaybillExceptionOrder();
-
- if (string.IsNullOrEmpty(orderIds))
- hasReadOrder = true;
-
- Dispatcher.Invoke(new Action(() =>
- {
- imgLoading.Visibility = Visibility.Collapsed;
- btnSearch.IsEnabled = true;
- }));
- }
-
- ///
- /// 读取订单详情信息
- ///
- ///
- ///
- public static List GetOrderItemInfo(string order_ids)
- {
- if (string.IsNullOrEmpty(order_ids))
- return new List();
- var url = BaseClass.Build29WxObjString("order/get_erp_order_item_list");
- var data = UserLogin.GetSignaturex();
- data += "&erp_order_id_in=" + order_ids;
- data += "&page_size=" + 2500;
- var html = GetHtml.PostUtf8(url, data);
- if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
- html = GetHtml.PostUtf8(url, data);
- if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
- {
- BaseMsgWindow.ShowAnimateMessage("订单详情读取失败 " + BaseRegex.GetStringJson(ref html, "msg"), "Error", 5);
- }
- List orderItems = new List();
- try
- {
- orderItems = JsonHelper.DeserializeJsonToList(JObject.Parse(html)["data"].ParseToString());
- if (orderItems == null)
- orderItems = new List();
- }
- catch (Exception ex)
- {
- orderItems = new List();
- BaseMsgWindow.ShowAnimateMessage("订单详情读取失败 " + ex.Message, "Error", 5);
- }
- return orderItems;
- }
-
- public static List GetOrderItemExts(string order_ids)
- {
- List existOrderExtList = new List();
- if (!string.IsNullOrEmpty(order_ids))
- {
- var url = BaseClass.Build29WxObjString("order/wx_get_order_item_ext_info");
- var data = UserLogin.GetSignaturex();
- data += "&wx_order_id_in=" + order_ids;
- var html = GetHtml.PostUtf8(url, data);
- if (!html.Contains("\"code\":200"))
- html = GetHtml.PostUtf8(url, data);
- if (!html.Contains("\"code\":200"))
- {
- BaseMsgWindow.ShowAnimateMessage("订单扩展信息查询失败 " + BaseRegex.GetStringJson(ref html, "msg"), "Error", 5);
- }
- existOrderExtList = JsonHelper.DeserializeJsonToList(JsonHelper.JObjectParse(html)["data"].ParseToString());
- }
- return existOrderExtList;
- }
-
- ///
- /// 读取售后单
- ///
- ///
- ///
- public static List GetOrderRefundInfo(string order_ids)
- {
- if (string.IsNullOrEmpty(order_ids))
- return new List();
- Thread.Sleep(100);
- var url2 = BaseClass.Build29WxObjString("order/get_erp_refund_list");
- var data2 = UserLogin.GetSignaturex();
- data2 += "&erp_order_id_in=" + order_ids;
- var html2 = GetHtml.PostUtf8(url2, data2);
- if (string.IsNullOrEmpty(html2) || !html2.Contains("\"code\":200"))
- html2 = GetHtml.PostUtf8(url2, data2);
- if (string.IsNullOrEmpty(html2) || !html2.Contains("\"code\":200"))
- {
- //BaseMsgWindow.ShowError(MainWindow.Instance, "订单读取失败 " + BaseRegex.GetStringJson(ref html, "msg"));
- //break;
- }
- List refunds = new List();
- try { refunds = JsonHelper.DeserializeJsonToList(JObject.Parse(html2)["data"].ParseToString()); } catch { }
- return refunds;
- }
-
- public void GetShopWaybillExceptionOrder()
- {
- foreach (var shop in GlobalConfig.ShopLoginList)
- {
- if (shop.LoginStatus == "登录成功")
- ShopBLL.CheckShopLogin(shop);
- if (shop.LoginStatus != "登录成功")
- continue;
-
- var rst = WxSimAbnormalOrderSeach(shop, 100);
- //Thread.Sleep(Randomx.GetId(50, 150));
- if (rst.Contains("\"code\":0"))
- {
- try
- {
- JObject jObj = JsonHelper.JObjectParse(rst);
- var wxOrderIdIn = string.Join(",", jObj["orderList"].Select(j => j["commonInfo"]["orderId"].ParseToString()));
- var wxSkuIdIn = string.Join(",", jObj["orderList"].Select(j => (j["orderProductInfo"].FirstOrDefault()?["skuId"]).ParseToString()));
-
- // 异常单
- List existOrderExtList = new List();
- if (!string.IsNullOrEmpty(wxOrderIdIn) && !string.IsNullOrEmpty(wxSkuIdIn))
- {
- var url = BaseClass.Build29WxObjString("order/wx_get_order_item_ext_info");
- var data = UserLogin.GetSignaturex();
- data += "&wx_order_id_in=" + wxOrderIdIn;
- data += "&wx_sku_id_in=" + wxSkuIdIn;
- var html = GetHtml.PostUtf8(url, data);
- if (!html.Contains("\"code\":200"))
- html = GetHtml.PostUtf8(url, data);
- if (!html.Contains("\"code\":200"))
- {
- BaseMsgWindow.ShowAnimateMessage("订单扩展信息查询失败 " + BaseRegex.GetStringJson(ref html, "msg"), "Error", 5);
- continue;
- }
- existOrderExtList = JsonHelper.DeserializeJsonToList(JsonHelper.JObjectParse(html)["data"].ParseToString());
- }
-
- // 先把已经物流异常但未查询到的订单改为正常
- var waybillExceptionOrders = GlobalConfig.lstOrder.Where(o => o.shop_id.ParseToString() == shop.ErpShopId && o.orderItems.Any(oi => oi.ShopWaybillExceptionStr == "物流异常")).ToList();
- foreach (var waybillExceptionOrder in waybillExceptionOrders)
- {
- if (!existOrderExtList.Any(oExt => oExt.order_id == waybillExceptionOrder.order_id))
- {
- foreach (var orderItem in waybillExceptionOrder.orderItems)
- {
- if (orderItem.OrderItemExt != null)
- {
- orderItem.OrderItemExt.abnormal_text = "";
- orderItem.ShopWaybillExceptionStr = "";
- }
- }
-
- // 更新显示
- Dispatcher.Invoke(new Action(() =>
- {
- foreach (var oi in waybillExceptionOrder.orderItems)
- oi.SetOrderItemTextProperty();
- waybillExceptionOrder.SetOrderTextProperty();
-
- MainWindow.Instance.orderListCtrl.FilterOneOrder(waybillExceptionOrder, true);
- }));
-
- var orderId = waybillExceptionOrder.order_id;
- order_item_ext orderExt = new order_item_ext() { order_id = orderId, shop_app_id = shop.ShopId, shop_name = shop.ShopAccount, abnormal_text = "物流异常" };
-
- var url1 = BaseClass.Build29WxObjString("order/wx_mdy_order_item_ext_info");
- var data1 = UserLogin.GetSignaturex();
- data1 += "&wx_order_id=" + orderExt.order_id;
- data1 += "&abnormal_text=";
- var html1 = GetHtml.PostUtf8(url1, data1);
- if (string.IsNullOrEmpty(html1) || !html1.Contains("\"code\":200"))
- html1 = GetHtml.PostUtf8(url1, data1);
- }
- }
-
- foreach (var od in jObj["orderList"])
- {
- var oStr = JsonHelper.SerializeObject(od);
-
- //var orderId = o["commonInfo"]["orderId"].ParseToString();
- var orderId = BaseRegex.GetStringJson(ref oStr, "orderId");
-
- if (orderId == "3737914129536416512")
- {
-
- }
- var skuId = BaseRegex.GetStringJson(ref oStr, "skuId");
-
- // 存在状态完全一样的订单异常信息就跳过
- order_item_ext orderExt = new order_item_ext() { order_id = orderId, sku_id = skuId, shop_app_id = shop.ShopId, shop_name = shop.ShopAccount, abnormal_text = "物流异常" };
-
- if (!existOrderExtList.Any(eoe => eoe.order_id == orderExt.order_id && eoe.sku_id == orderExt.sku_id && eoe.abnormal_text == orderExt.abnormal_text))
- {
- var url1 = BaseClass.Build29WxObjString("order/wx_add_order_item_ext_info");
- if (existOrderExtList.Any(eoe => eoe.order_id == orderExt.order_id && eoe.sku_id == orderExt.sku_id))
- url1 = BaseClass.Build29WxObjString("order/wx_mdy_order_item_ext_info");
- var data1 = UserLogin.GetSignaturex();
- data1 += "&wx_order_id=" + orderExt.order_id;
- data1 += "&wx_sku_id=" + orderExt.sku_id;
- data1 += "&shop_app_id=" + orderExt.shop_app_id;
- data1 += "&shop_name=" + orderExt.shop_name;
- data1 += "&abnormal_text=" + orderExt.abnormal_text;
- var html1 = GetHtml.PostUtf8(url1, data1);
- if (string.IsNullOrEmpty(html1) || !html1.Contains("\"code\":200"))
- {
- BaseMsgWindow.ShowAnimateMessage("订单扩展信息写入失败 " + BaseRegex.GetStringJson(ref html1, "msg"), "Error", 5);
- break;
- }
- }
- else
- {
- orderExt = existOrderExtList.FirstOrDefault(eoe => eoe.order_id == orderExt.order_id && eoe.sku_id == orderExt.sku_id && eoe.abnormal_text == orderExt.abnormal_text);
- }
-
- // 更新订单附加信息
- if (orderExt.order_id == "3737845591459133952")
- {
-
- }
- var order = GlobalConfig.lstOrder.FirstOrDefault(o => o.order_id == orderExt.order_id);
- if (order != null)
- {
- var orderItem = order.orderItems.FirstOrDefault(oi => oi.sku_id == orderExt.sku_id);
- if (orderItem != null)
- {
- orderItem.OrderItemExt = orderExt;
- Dispatcher.Invoke(new Action(() =>
- {
- foreach (var oi in order.orderItems)
- oi.SetOrderItemTextProperty();
- order.SetOrderTextProperty();
-
- MainWindow.Instance.orderListCtrl.FilterOneOrder(order, true);
- }));
- }
- }
- }
- }
- catch (Exception ex)
- {
- BaseMsgWindow.ShowAnimateMessage("订单扩展信息查询失败 " + ex.Message, "Error", 5);
- }
- }
- }
- }
-
- public void disPlayOrderTabOrderCount()
- {
-
- var orders = string.Join("','", GlobalConfig.lstFilterOrder.Select(o => o.order_id));
- var orders1 = string.Join(",", GlobalConfig.lstFilterOrder.Select(o => o.order_id));
-
-
-
- var tabItems = this.tabOrderType.Items.Cast();
- var tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("待采购"));
- var userOrderLst = GlobalConfig.lstOrder.Where(o => GlobalConfig.ShopLoginList.Any(s => s.ErpShopId.ParseToLong() == o.shop_id)).ToList();
- if (tabItem != null)
- {
- var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "待采购")));
- //tabItem.Header = "待采购(" + userOrderLst.Where(r => r.IsWaitBuy).Count() + "|" + filteLstTmp.Where(r => r.IsWaitBuy).Count() + ")";
- tabItem.Header = "待采购(" + userOrderLst.Where(r => r.IsWaitBuy).Count() + "|" + filteLstTmp.Count() + ")";
- }
- tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("待发货"));
- if (tabItem != null)
- {
- var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "待发货")));
- //tabItem.Header = "待发货(" + userOrderLst.Where(r => r.IsWaitSend).Count() + "|" + filteLstTmp.Where(r => r.IsWaitSend).Count() + ")";
- tabItem.Header = "待发货(" + userOrderLst.Where(r => r.IsWaitSend).Count() + "|" + filteLstTmp.Count() + ")";
- }
- tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("待收货"));
- if (tabItem != null)
- {
- var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "待收货")));
- //tabItem.Header = "待收货(" + userOrderLst.Where(r => r.IsWaitReceive).Count() + "|" + filteLstTmp.Where(r => r.IsWaitReceive).Count() + ")";
- tabItem.Header = "待收货(" + userOrderLst.Where(r => r.IsWaitReceive).Count() + "|" + filteLstTmp.Count() + ")";
- }
- tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("售后完成单"));
- if (tabItem != null)
- {
- var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "售后完成单")));
- //tabItem.Header = "售后完成单(" + userOrderLst.Where(r => r.IsRefund).Count() + "|" + filteLstTmp.Where(r => r.IsRefund).Count() + ")";
- tabItem.Header = "售后完成单(" + userOrderLst.Where(r => r.IsRefund).Count() + "|" + filteLstTmp.Count() + ")";
- }
- tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("需处理售后单"));
- if (tabItem != null)
- {
- var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "需处理售后单")));
- //tabItem.Header = "需处理售后单(" + userOrderLst.Where(r => r.IsEmergency).Count() + "|" + filteLstTmp.Where(r => r.IsEmergency).Count() + ")";
- tabItem.Header = "需处理售后单(" + userOrderLst.Where(r => r.IsEmergency).Count() + "|" + filteLstTmp.Count() + ")";
- }
- tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("异常单"));
- if (tabItem != null)
- {
- var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "异常单")));
- //tabItem.Header = "异常单(" + userOrderLst.Where(r => r.isAbnormal).Count() + "|" + filteLstTmp.Where(r => r.isAbnormal).Count() + ")";
- tabItem.Header = "异常单(" + userOrderLst.Where(r => r.isAbnormal).Count() + "|" + filteLstTmp.Count() + ")";
- }
- tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("全部订单"));
- if (tabItem != null)
- {
- var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "全部订单")));
- tabItem.Header = "全部订单(" + userOrderLst.Count() + "|" + filteLstTmp.Count() + ")";
- }
- //txtMsg.Text = "当前条件共计 " + GlobalConfig.lstFilterOrder.Count() + " 条订单记录";
- }
-
- public void FilterOrders()
- {
- try
- {
- if (this.lbxOrder == null)
- return;
-
- Dispatcher.Invoke(new Action(() =>
- {
- if (GlobalConfig.OrderTabHeaderStr.StartsWith("需处理售后单"))
- GlobalConfig.lstFilterOrder = new ObservableCollectionThreadSafe(GlobalConfig.lstOrder.Where(o => !GetOrderIsFilter(o)).OrderByDescending(o => o.RefundDatetime));
- else if (GlobalConfig.OrderTabHeaderStr.StartsWith("异常单"))
- GlobalConfig.lstFilterOrder = new ObservableCollectionThreadSafe(GlobalConfig.lstOrder.Where(o => !GetOrderIsFilter(o)).OrderByDescending(o => o.update_time));
- else
- GlobalConfig.lstFilterOrder = new ObservableCollectionThreadSafe(GlobalConfig.lstOrder.Where(o => !GetOrderIsFilter(o)).OrderByDescending(o => o.create_time));
- this.lbxOrder.ItemsSource = GlobalConfig.lstFilterOrder;
-
- disPlayOrderTabOrderCount();
- }));
- }
- catch (Exception ex)
- {
- }
- }
-
- public void FilterOneOrder(oms_wei_order_info order, bool updateTabCount = false)
- {
- var orderExist = GlobalConfig.lstFilterOrder.FirstOrDefault(o => o.order_id == order.order_id);
- while (orderExist != null)
- {
- GlobalConfig.lstFilterOrder.Remove(orderExist);
- orderExist = GlobalConfig.lstFilterOrder.FirstOrDefault(o => o.order_id == order.order_id);
- }
-
- if (!GetOrderIsFilter(order))
- {
- oms_wei_order_info nextOrder = null;
- if (GlobalConfig.OrderTabHeaderStr.StartsWith("需处理售后单"))
- nextOrder = GlobalConfig.lstFilterOrder.FirstOrDefault(o => o.RefundDatetime < order.RefundDatetime);
- else if (GlobalConfig.OrderTabHeaderStr.StartsWith("异常单"))
- nextOrder = GlobalConfig.lstFilterOrder.FirstOrDefault(o => o.update_time < order.update_time);
- else
- nextOrder = GlobalConfig.lstFilterOrder.FirstOrDefault(o => o.create_time < order.create_time);
-
- if (nextOrder != null)
- {
- GlobalConfig.lstFilterOrder.Insert(GlobalConfig.lstFilterOrder.IndexOf(nextOrder), order);
- }
- else
- {
- GlobalConfig.lstFilterOrder.Add(order);
- }
- }
-
- if (updateTabCount)
- {
- Dispatcher.Invoke(new Action(() =>
- {
- disPlayOrderTabOrderCount();
- }));
- }
- }
-
- bool GetOrderIsFilter(oms_wei_order_info order, string filterHeadStr = null)
- {
- if (order == null)
- return true;
-
- if (!GlobalConfig.ShopLoginList.Any(s => s.ErpShopId.ParseToLong() == order.shop_id))
- return true;
-
- if (!string.IsNullOrEmpty(strSearchAll))
- {
- bool isFilter = true;
- // 买手物流
- if (order.orderItems.Any(oi => oi.ItemTransitOrders.Any(t => t.express_1_waybill.ParseToString().Contains(strSearchAll))))
- isFilter = false;
- // 仓库物流
- else if (order.orderItems.Any(oi => oi.ItemTransitOrders.Any(t => t.express_2_waybill.ParseToString().Contains(strSearchAll))))
- isFilter = false;
- // 退货物流
- else if (order.refundItems.Any(ri => ri.return_waybill_id.ParseToString().Contains(strSearchAll)))
- isFilter = false;
- // 退货单号
- else if (order.refundItems.Any(ri => ri.after_sale_order_id.ParseToString().Contains(strSearchAll)))
- isFilter = false;
- // 仓库采购单号
- else if (order.orderItems.Any(oi => oi.ItemTransitOrders.Any(t => t.out_order_no.ParseToString().Contains(strSearchAll))))
- isFilter = false;
- // 仓库退款单号
- else if (order.orderItems.Any(oi => oi.ItemTransitOrderAfterSales.Any(t => t.refund_waybill.ParseToString().Contains(strSearchAll))))
- isFilter = false;
- if (isFilter)
- return true;
- }
-
- // 过滤店铺名称
- if (!string.IsNullOrEmpty(txtShopName.Text.Trim()) && !(";" + txtShopName.Text.Trim() + ";").Contains(";" + order.shop_name + ";"))
- {
- return true;
- }
- // 过滤商品名称
- if (!string.IsNullOrEmpty(txtGoodsName.Text.Trim()) && !order.orderItems.Any(it => it.title.Contains(txtGoodsName.Text.Trim())))
- {
- return true;
- }
- // 过滤id
- if (!string.IsNullOrEmpty(txtOrderId.Text.Trim()) && !(";" + txtOrderId.Text.Trim().Replace(' ', ';').Replace(',', ';') + ";").Contains(";" + order.order_id + ";"))
- {
- return true;
- }
- // 过滤多子单订单
- if (chkNoMultiOrder.IsChecked.ParseToBool() && order.orderItems.Count() > 1)
- {
- return true;
- }
- // 过滤非中转仓订单
- if (chkOnlyWarehouseOrder.IsChecked.ParseToBool() && !order.IsWaitBuy &&
- order.orderItems.All(oi => oi.ItemTransitOrderWithVoid == null) && order.orderItems.All(oi => oi.OrderItemExt?.buy_type != "直发"))
- {
- return true;
- }
- // 过滤备注
- if (chkFilterRemark.IsChecked == true && !string.IsNullOrEmpty(txtFilterRemark.Text))
- {
- if (cmbFilterRemark.SelectedItem is ComboBoxItem comboBoxItem)
- {
- if (comboBoxItem.Content is TextBlock tb)
- {
- if (tb.Text == "店铺备注包含" && !lstFilterText.Contains(order.shop_remark))
- return true;
- else if (tb.Text == "软件备注包含" && !lstFilterText.Contains(order.soft_remark))
- return true;
- else if (tb.Text == "店铺备注不含" && lstFilterText.Contains(order.shop_remark))
- return true;
- else if (tb.Text == "软件备注不含" && lstFilterText.Contains(order.soft_remark))
- return true;
- }
- }
- }
- if (!chkDirectOrder.IsChecked == true && order.OrderBuyType == "直发")
- return true;
- if (!chkTransitOrder.IsChecked == true && order.OrderBuyType == "云仓")
- return true;
- if (!chkTransitChangeDirectOrder.IsChecked == true && order.OrderBuyType == "云改直")
- return true;
-
- // 过滤时间范围
- if (cmbTimeType.SelectedItem is ComboBoxItem cbi)
- {
- if (cbi.Content is TextBlock tb)
- {
- if (tb.Text == "更新时间")
- {
- if (order.UpdateDateTime < dateStart.SelectedDate.Value)
- return true;
- if (chkEndDate.IsChecked == true && order.UpdateDateTime > dateEnd.SelectedDate.Value)
- return true;
- }
- if (tb.Text == "创建时间")
- {
- if (order.CreateDateTime < dateStart.SelectedDate.Value)
- return true;
- if (chkEndDate.IsChecked == true && order.CreateDateTime > dateEnd.SelectedDate.Value)
- return true;
- }
- }
- }
-
- // 过滤标签页
- if (filterHeadStr.IsNullOrEmpty())
- filterHeadStr = GlobalConfig.OrderTabHeaderStr;
-
- if (filterHeadStr.StartsWith("全部订单"))
- {
- return false;
- }
- if (filterHeadStr.StartsWith("待采购"))
- {
- if (!order.IsWaitBuy)
- return true;
- //if (order.IsRefund)
- // return true;
- if (chkMapProdOnly.IsChecked == true && order.orderItems.All(oi => oi.BuyMap == null))
- return true;
- if (chkNoMapProdOnly.IsChecked == true && order.orderItems.All(oi => oi.BuyMap != null))
- return true;
- }
- if (filterHeadStr.StartsWith("待发货") && !order.IsWaitSend)
- {
- return true;
- }
- if (filterHeadStr.StartsWith("待收货"))
- {
- if (!order.IsWaitReceive)
- return true;
-
- if (chkWaitReceiveBuyerIsNotSend.IsChecked == true && order.orderItems.All(oi => oi.BuyerTransitWaybillStatusStr != "买手未发货"))
- return true;
- if (chkWaitReceiveBuyerIsSend.IsChecked == true && order.orderItems.All(oi => oi.BuyerTransitWaybillStatusStr != "买手已发货"))
- return true;
- if (chkWaitReceiveBuyerIsInWarehouse.IsChecked == true && order.orderItems.All(oi => oi.BuyerTransitWaybillStatusStr != "买手已送达"))
- return true;
-
- if (chkWaitReceiveWarehouseIsNotPickup.IsChecked == true && order.orderItems.All(oi => oi.WarehouseWaybillStatusStr != "中转待取号"))
- return true;
- if (chkWaitReceiveWarehouseIsPickup.IsChecked == true && order.orderItems.All(oi => oi.WarehouseWaybillStatusStr != "中转提前取号" && oi.WarehouseWaybillStatusStr != "中转已取号" && oi.WarehouseWaybillStatusStr != "中转已入库"))
- return true;
- if (chkWaitReceiveWarehouseIsSendOut.IsChecked == true && order.orderItems.All(oi => oi.WarehouseWaybillStatusStr != "中转已出库"))
- return true;
- }
- if (filterHeadStr.StartsWith("异常单") && !order.isAbnormal)
- {
- return true;
- }
- if (filterHeadStr.StartsWith("需处理售后单"))
- {
- if (!order.IsEmergency)
- return true;
-
- if (chkEmergencyBuyerWaitAfterSale.IsChecked == true && order.orderItems.All(oi => !oi.TransitRefundStatusStr.Contains("需手动申请售后")))
- return true;
- else if (chkEmergencyBuyerWaitSendBack.IsChecked == true && order.orderItems.All(oi => !oi.TransitRefundStatusStr.Contains("待用户发货")))
- return true;
- else if (chkEmergencyBuyerWaitSupplierRefund.IsChecked == true && order.orderItems.All(oi => !oi.TransitRefundStatusStr.Contains("商家处理中")))
- return true;
- else if (chkEmergencyBuyerRefundFail.IsChecked == true && order.orderItems.All(oi => !oi.TransitRefundStatusStr.Contains("退款失败")))
- return true;
-
- if (chkEmergencyShopCustomRefundHasWaybill.IsChecked == true && order.orderItems.Any(oi => oi.ReturnWaybillIdStr.IsNullOrEmpty()))
- return true;
- else if (chkEmergencyShopCustomRefundNoWaybill.IsChecked == true && order.orderItems.All(oi => !oi.ReturnWaybillIdStr.IsNullOrEmpty()))
- return true;
-
- if (order.order_id == "3737838342857424896")
- {
-
- }
-
- // 退款完成
- if (chkEmergencyShopAfterSaleSuccess.IsChecked == true && order.DeliveryDeadlineDtatusStr != "退款完成")
- return true;
- // 退款中
- else if (chkEmergencyShopInAfterSale.IsChecked == true && (order.DeliveryDeadlineDtatusStr != "退款中"))
- return true;
-
- //// 退货退款
- //if (chkEmergencyReturn.IsChecked == true && !(order.refundItems.OrderByDescending(or => or.create_time).FirstOrDefault()?.RefundStatusStr).ParseToString().Contains("退货"))
- // return true;
- //// 仅退款
- //else if (chkEmergencyRefund.IsChecked == true && (order.refundItems.OrderByDescending(or => or.create_time).FirstOrDefault()?.RefundStatusStr).ParseToString().Contains("退货"))
- // return true;
- // 退货退款
- if (chkEmergencyReturn.IsChecked == true && !(order.refundItems.OrderByDescending(or => or.create_time).FirstOrDefault()?.type).ParseToString().Contains("RETURN"))
- return true;
- // 仅退款
- else if (chkEmergencyRefund.IsChecked == true && !(order.refundItems.OrderByDescending(or => or.create_time).FirstOrDefault()?.type).ParseToString().Contains("REFUND"))
- return true;
- }
- if (filterHeadStr.StartsWith("售后完成单"))
- {
- if (!order.IsRefund)
- return true;
-
- if (chkAftersaleIsSend.IsChecked == true && !order.DeliveryDeadlineStr.Contains("已发货"))
- return true;
- else if (chkAftersaleIsNotSend.IsChecked == true && !order.DeliveryDeadlineStr.Contains("未发货"))
- return true;
-
- if (chkAftersaleBuyerIsBuy.IsChecked == true && order.orderItems.All(oi => oi.BuyerTransitWaybillStatusStr.IsNullOrEmpty()))
- return true;
- if (chkAftersaleWarehouseIsNotPickup.IsChecked == true && order.orderItems.All(oi => oi.WarehouseWaybillStatusStr != "中转待取号" && !oi.WarehouseWaybillStatusStr.Contains("取号异常")))
- return true;
- if (chkAftersaleWarehouseIsPickup.IsChecked == true && order.orderItems.All(oi => oi.WarehouseWaybillStatusStr != "中转提前取号" && oi.WarehouseWaybillStatusStr != "中转已取号" &&
- oi.WarehouseWaybillStatusStr != "中转已入库" && oi.WarehouseWaybillStatusStr != "中转已出库"))
- return true;
- }
-
- return false;
- }
-
- private void btnMultiShopChoice_Click(object sender, RoutedEventArgs e)
- {
- MainWindow.Instance.shopListCtrl.IsVisibleChanged -= ShopListCtrl_IsVisibleChanged;
- MainWindow.Instance.shopListCtrl.Visibility = Visibility.Visible;
- MainWindow.Instance.shopListCtrl.IsVisibleChanged += ShopListCtrl_IsVisibleChanged;
- }
-
- private void ShopListCtrl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
- {
- if (!MainWindow.Instance.shopListCtrl.IsVisible && MainWindow.Instance.shopListCtrl.IsAcceptChoiceShop == true)
- {
- var list = MainWindow.Instance.shopListCtrl.lbxShop.ItemsSource as ObservableCollection;
- if (list != null)
- this.txtShopName.Text = string.Join(";", list.Where(s => s.IsSelect == true).Select(s => s.ShopAccount));
-
- FilterOrders();
-
- }
- MainWindow.Instance.shopListCtrl.IsVisibleChanged -= ShopListCtrl_IsVisibleChanged;
- }
-
- private void btnSearch_Click(object sender, RoutedEventArgs e)
- {
- this.btnSearch.IsEnabled = false;
-
- Task.Run(() =>
- {
- Thread.Sleep(5000);
- Dispatcher.Invoke(new Action(() => { this.btnSearch.IsEnabled = true; }));
- });
- Task.Run(() =>
- {
- while (!MainWindow.Instance.hasReadShop)
- {
- Thread.Sleep(100);
- }
-
- GetOrder();
- nextGetOrderTime = DateTime.Now.AddMinutes(25);
- });
- }
-
- private void btnFilter_Click(object sender, RoutedEventArgs e)
- {
- FilterOrders();
- }
-
- private void dgOrderHeader_ColumnDisplayIndexChanged(object sender, DataGridColumnEventArgs e)
- {
- }
-
- private void dgOrderHeader_LayoutUpdated(object sender, EventArgs e)
- {
- foreach (var item in lbxOrder.Items)
- {
- ListBoxItem container = (ListBoxItem)lbxOrder.ItemContainerGenerator.ContainerFromIndex(lbxOrder.Items.IndexOf(item));
- if (container != null)
- {
- // 找到grid控件并修改列大小
- var grids = UiCtrlUtils.FindVisualChildAll(container, "gridListItem");
- foreach (var grid in grids)
- {
- for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
- {
- if (dgOrderHeader.Columns.Count > i)
- {
- // 最后一列因滚动条变窄,已在表头补偿
- if (i == grid.ColumnDefinitions.Count - 1)
- grid.ColumnDefinitions[i].Width = new GridLength(Math.Max(0, dgOrderHeader.Columns[i].ActualWidth - 0));
- else
- grid.ColumnDefinitions[i].Width = new GridLength(dgOrderHeader.Columns[i].ActualWidth);
- }
- }
- }
- }
- }
- }
-
- private void ChkSelectAll_Checked(object sender, RoutedEventArgs e)
- {
- foreach (var order in GlobalConfig.lstOrder.ToList())
- {
- order.IsSelect = true;
- }
- }
-
- private void ChkSelectAll_Unchecked(object sender, RoutedEventArgs e)
- {
- foreach (var order in GlobalConfig.lstOrder.ToList())
- {
- order.IsSelect = false;
- }
- }
-
- private void ChkSelectAll_Loaded(object sender, RoutedEventArgs e)
- {
- chkSelectAll = sender as CheckBox;
- }
-
- public void UpdateChkAllBox ()
- {
- chkSelectAll.Checked -= ChkSelectAll_Checked;
- chkSelectAll.Unchecked -= ChkSelectAll_Unchecked;
- if (GlobalConfig.lstFilterOrder.All(s => s.IsSelect))
- chkSelectAll.IsChecked = true;
- else if (GlobalConfig.lstFilterOrder.All(s => !s.IsSelect))
- chkSelectAll.IsChecked = false;
- else
- chkSelectAll.IsChecked = null;
- chkSelectAll.Checked += ChkSelectAll_Checked;
- chkSelectAll.Unchecked += ChkSelectAll_Unchecked;
- }
-
- private void txtSearchAll_TextChanged(object sender, TextChangedEventArgs e)
- {
- strSearchAll = txtSearchAll.Text.Trim();
- }
-
- private void tabOrderType_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- GlobalConfig.OrderTabHeaderStr = ((tabOrderType.SelectedItem as TabItem)?.Header).ParseToString();
- FilterOrders();
- }
-
- private void chkMapProdOnly_Click(object sender, RoutedEventArgs e)
- {
- if (chkMapProdOnly.IsChecked == true)
- chkNoMapProdOnly.IsChecked = false;
- FilterOrders();
- }
- private void chkNoMapProdOnly_Click(object sender, RoutedEventArgs e)
- {
- if (chkNoMapProdOnly.IsChecked == true)
- chkMapProdOnly.IsChecked = false;
- FilterOrders();
- }
-
- public static string addNotes(ShopLoginInfo shop, string orderId, string notes, int tagColor = -1)
- {
- string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeorder/common/cgi/batchMerchantNotes?token=&lang=zh_CN";
- string body = @"{""items"":[{""orderId"":""" + orderId + @""",""merchantNotes"":""" + notes + @""",""merchantNotesTagColor"":" + tagColor + @"}]}";
- if (tagColor == -1)
- body = @"{""items"":[{""orderId"":""" + orderId + @""",""merchantNotes"":""" + notes + @"""}]}";
-
- string refere = "https://store.weixin.qq.com/shop/order/list";
- var result = HttpResponseWXBLL.WeiXinPostResponse(shop, url, body, refere);
- return result;
- }
- public static string addNotesFlag(ShopLoginInfo shop, string orderId, string notes, int tagColor = 0)
- {
- string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeorder/common/cgi/batchMerchantNotes?token=&lang=zh_CN";
- string body = @"{""items"":[{""orderId"":""" + orderId + @""",""merchantNotesTagColor"":" + tagColor + @"}]}";
-
- string refere = "https://store.weixin.qq.com/shop/order/list";
- var result = HttpResponseWXBLL.WeiXinPostResponse(shop, url, body, refere);
- return result;
- }
-
- private void chkAutoReadBuyerOrder_CheckedChanged(object sender, RoutedEventArgs e)
- {
- IsAutoReadOrder = chkAutoReadOrder.IsChecked == true;
- }
-
- private void TabItem_SizeChanged(object sender, SizeChangedEventArgs e)
- {
- var tabItems = this.tabOrderType.Items.Cast();
- wpFilter.Margin = new Thickness(tabItems.Sum(t => t.ActualWidth) + 18, wpFilter.Margin.Top, wpFilter.Margin.Right, wpFilter.Margin.Bottom);
-
- Point position1 = txtFilterRemark.TranslatePoint(new Point(0, 0), gridOrderListCtrl);
- Point position2 = txtFilterRemark.TranslatePoint(new Point(0, 0), wpFilter);
- borderFilterRemarkSelect.Margin = new Thickness(tabItems.Sum(t => t.ActualWidth) + 16 + position2.X, position1.Y + txtFilterRemark.ActualHeight + 3, 0, 0);
- }
-
- private void chkSubFilterSonditions_Checked(object sender, RoutedEventArgs e)
- {
- FilterOrders();
- }
-
- ///
- /// 待处理订单买手售后状态过滤
- ///
- private void chkEmergencyBuyerAfterSale_Click(object sender, RoutedEventArgs e)
- {
- if (sender is CheckBox chk)
- {
- var isCheck = !chk.IsChecked.ParseToBool();
- chkEmergencyBuyerWaitAfterSale.IsChecked = chkEmergencyBuyerWaitSendBack.IsChecked = chkEmergencyBuyerWaitSupplierRefund.IsChecked = chkEmergencyBuyerRefundFail.IsChecked = false;
- chk.IsChecked = !isCheck;
- }
- FilterOrders();
- }
- ///
- /// 待处理订单店铺买家售后物流状态过滤
- ///
- private void chkEmergencyShopCustomRefundWaybill_Click(object sender, RoutedEventArgs e)
- {
- if (sender is CheckBox chk)
- {
- var isCheck = !chk.IsChecked.ParseToBool();
- chkEmergencyShopCustomRefundHasWaybill.IsChecked = chkEmergencyShopCustomRefundNoWaybill.IsChecked = false;
- chk.IsChecked = !isCheck;
- }
- FilterOrders();
- }
- ///
- /// 待处理订单店铺售后状态过滤
- ///
- ///
- ///
- private void chkEmergencyShopAfterSale_Click(object sender, RoutedEventArgs e)
- {
- if (sender is CheckBox chk)
- {
- var isCheck = !chk.IsChecked.ParseToBool();
- chkEmergencyShopAfterSaleSuccess.IsChecked = chkEmergencyShopInAfterSale.IsChecked = false;
- chk.IsChecked = !isCheck;
- }
- FilterOrders();
- }
-
- ///
- /// 待收货 买手发货状态
- ///
- ///
- ///
- private void chkWaitReceiveBuyerStatus_Click(object sender, RoutedEventArgs e)
- {
- if (sender is CheckBox chk)
- {
- var isCheck = !chk.IsChecked.ParseToBool();
- chkWaitReceiveBuyerIsSend.IsChecked = chkWaitReceiveBuyerIsNotSend.IsChecked = chkWaitReceiveBuyerIsInWarehouse.IsChecked = false;
- chk.IsChecked = !isCheck;
- }
- FilterOrders();
- }
-
- private void chkWaitReceiveWarehouseStatus_Click(object sender, RoutedEventArgs e)
- {
- if (sender is CheckBox chk)
- {
- var isCheck = !chk.IsChecked.ParseToBool();
- chkWaitReceiveWarehouseIsNotPickup.IsChecked = chkWaitReceiveWarehouseIsPickup.IsChecked = chkWaitReceiveWarehouseIsSendOut.IsChecked = false;
- chk.IsChecked = !isCheck;
- }
- FilterOrders();
- }
-
- private void chkAftersaleSendStatus_Click(object sender, RoutedEventArgs e)
- {
- if (sender is CheckBox chk)
- {
- var isCheck = !chk.IsChecked.ParseToBool();
- chkAftersaleIsSend.IsChecked = chkAftersaleIsNotSend.IsChecked = false;
- chk.IsChecked = !isCheck;
- }
- FilterOrders();
- }
-
- private void chkAftersaleBuyerStatus_Click(object sender, RoutedEventArgs e)
- {
- if (sender is CheckBox chk)
- {
- var isCheck = !chk.IsChecked.ParseToBool();
- chkAftersaleBuyerIsBuy.IsChecked = false;
- chk.IsChecked = !isCheck;
- }
- FilterOrders();
- }
-
- private void chkAftersaleWarehouseStatus_Click(object sender, RoutedEventArgs e)
- {
- if (sender is CheckBox chk)
- {
- var isCheck = !chk.IsChecked.ParseToBool();
- chkAftersaleWarehouseIsPickup.IsChecked = chkAftersaleWarehouseIsNotPickup.IsChecked = false;
- chk.IsChecked = !isCheck;
- }
- FilterOrders();
- }
-
- private async void btnBatchRefund_Click(object sender, RoutedEventArgs e)
- {
- var orders = GlobalConfig.lstFilterOrder.Where(o => o.IsSelect == true);
- List tmpOrderItems = new List();
- foreach (var order in orders)
- {
- foreach (var orderItem in order.orderItems)
- {
- if (orderItem.ItemOrder?.OrderBuyType == "云仓")
- if (orderItem != null && !string.IsNullOrEmpty(orderItem.ItemTransitOrderWithVoid?.out_order_no) && orderItem.PddBuyerAfterSaleAddressStr.IsNullOrEmpty() &&
- (orderItem.TransitRefundStatusStr.Contains("需手动申请售后") || orderItem.TransitRefundStatusStr.Contains("待用户发货")))
- tmpOrderItems.Add(orderItem);
-
- if (orderItem.ItemOrder?.OrderBuyType == "直发" || orderItem.ItemOrder?.OrderBuyType == "云改直")
- if (orderItem != null && !string.IsNullOrEmpty(orderItem.ItemOrder?.out_order_no) && orderItem.PddBuyerAfterSaleAddressStr.IsNullOrEmpty() &&
- ((orderItem.ItemOrder?.out_after_sale_status).ParseToString().Contains("需手动申请售后") || (orderItem.ItemOrder?.out_after_sale_status).ParseToString().Contains("待用户发货")))
- tmpOrderItems.Add(orderItem);
- }
- }
- if (tmpOrderItems.Count == 0)
- {
- BaseMsgWindow.ShowAnimateMessage("未选中需要需手动申请售后的订单", "Error", 3);
- return;
- }
-
- await Task.Run(() =>
- {
- int index = 0;
- foreach (var tmpOrderItem in tmpOrderItems)
- {
- Dispatcher.Invoke(new Action(() => { txtMsg.Text = "正在处理买手退货,总计:" + tmpOrderItems.Count + ",已处理:" + index++; }));
-
- var pddOrderSn = "";
- if (tmpOrderItem.ItemOrder?.OrderBuyType == "云仓")
- pddOrderSn = tmpOrderItem.ItemTransitOrderWithVoid?.out_order_no;
- else if (tmpOrderItem.ItemOrder?.OrderBuyType == "直发" || tmpOrderItem.ItemOrder?.OrderBuyType == "云改直")
- pddOrderSn = tmpOrderItem.ItemOrder?.out_order_no;
-
- BuyerLoginInfo buyer = null;
- if (tmpOrderItem.ItemOrder?.OrderBuyType == "云仓")
- Dispatcher.Invoke(new Action(() => { buyer = GlobalConfig.PDDBuyerLoginList.FirstOrDefault(b => b.buyer_nick == tmpOrderItem.ItemTransitOrderWithVoid.buyer_account); }));
- else if (tmpOrderItem.ItemOrder?.OrderBuyType == "直发" || tmpOrderItem.ItemOrder?.OrderBuyType == "云改直")
- Dispatcher.Invoke(new Action(() => { buyer = GlobalConfig.PDDBuyerLoginList.FirstOrDefault(b => b.buyer_nick == tmpOrderItem.ItemOrder?.out_account); }));
- if (buyer == null)
- {
- BaseMsgWindow.ShowAnimateMessage("买手单:" + pddOrderSn + " 买手不在当前账户下,跳过", "Error", 3);
- }
-
- // 检测一下买手号
- if (buyer.status == "在线")
- {
- PddMobileLoginForm.CheckBuyerLogin(buyer);
- }
- if (buyer.status != "在线")
- {
- BaseMsgWindow.ShowAnimateMessage("买手单:" + pddOrderSn + " 买手号掉线,跳过", "Error", 3);
- continue;
- }
-
- MainWindow.Instance.orderListCtrl.GetOrder(tmpOrderItem.order_id);
-
- oms_wei_order_info order = null;
- Dispatcher.Invoke(new Action(() => { order = GlobalConfig.lstOrder.FirstOrDefault(oi => oi.order_id == tmpOrderItem.order_id); }));
- if (order == null)
- continue;
- oms_wei_order_item_info orderItem = null;
- Dispatcher.Invoke(new Action(() => { orderItem = order.orderItems.FirstOrDefault(oi => oi.order_id == tmpOrderItem.order_id && oi.sku_id == tmpOrderItem.sku_id); }));
- if (orderItem == null)
- continue;
-
- string refundStatusStr = "";
- string outOrderNo = "";
- if (order.OrderBuyType == "云仓")
- {
- outOrderNo = (orderItem.ItemTransitOrderWithVoid?.out_order_no).ParseToString();
- refundStatusStr = (orderItem?.TransitRefundStatusStr).ParseToString();
- }
- else if (order.OrderBuyType == "直发" || order.OrderBuyType == "云改直")
- {
- outOrderNo = (order.out_order_no).ParseToString();
- refundStatusStr = (order.out_after_sale_status).ParseToString();
- }
- if (orderItem == null || string.IsNullOrEmpty(outOrderNo) || !orderItem.PddBuyerAfterSaleAddressStr.IsNullOrEmpty() ||
- (!refundStatusStr.Contains("需手动申请售后") && !refundStatusStr.Contains("待用户发货")))
- continue;
-
- PddBuyerOrderLiteInfo pddBuyerOrderLiteInfo = new PddBuyerOrderLiteInfo();
- pddBuyerOrderLiteInfo.ShopOrderIdStr = orderItem.order_id;
- pddBuyerOrderLiteInfo.order_sn = pddOrderSn;
-
- if (order.OrderBuyType == "云仓")
- pddBuyerOrderLiteInfo.order_amount = orderItem.ItemTransitOrderWithVoid?.out_amount;
- else if (order.OrderBuyType == "直发" || order.OrderBuyType == "云改直")
- pddBuyerOrderLiteInfo.order_amount = order.out_amount;
-
- order_pdd_buyer_after_sale pddBuyerAfterSale = new order_pdd_buyer_after_sale()
- {
- wx_order_id = orderItem.order_id,
- wx_sku_id = orderItem.sku_id,
- TransitCreateTime = orderItem.ItemTransitOrderWithVoid?.created_time == null ? DateTime.MinValue : orderItem.ItemTransitOrderWithVoid.created_time,
- pre_allocated_order_no = orderItem.ItemTransitOrderWithVoid?.pre_allocated_order_no,
- buyerId = buyer.buyer_id,
- buyerName = buyer.buyer_name,
- orderSn = pddOrderSn,
- orderAmount = pddBuyerOrderLiteInfo.order_amount,
- refundAmount = pddBuyerOrderLiteInfo.order_amount,
- orderDate = pddOrderSn.ParseToString().Split('-').FirstOrDefault().ParseToInt(),
- };
- if (orderItem.PddBuyerAfterSale != null)
- pddBuyerAfterSale = orderItem.PddBuyerAfterSale;
-
- bool isSimPddAfterSaleSuccess = true;
- if (refundStatusStr.Contains("需手动申请售后"))
- {
- isSimPddAfterSaleSuccess = false;
- // pddBuyerAfterSale作为参数传入,获取退货退款金额
- var rst = PDDBuyerOrderReadCtrl.SimPddAfterSaleWithReturnGoods(buyer, pddBuyerOrderLiteInfo, pddBuyerAfterSale);
-
- var afterSalesStatus = BaseRegex.GetIntJson(ref rst, "after_sales_status");
- var afterSalesId = BaseRegex.GetLongJson(ref rst, "after_sales_id");
- pddBuyerAfterSale.afterSalesId = afterSalesId.ToString();
- pddBuyerAfterSale.statusText = "待用户发货";
-
- if (afterSalesStatus == 0)
- {
- var msg = BaseRegex.GetStringJsonByRegs(ref rst, rst, "msg", "err_msg", "error_msg", "errorMsg", "errMsg");
- BaseMsgWindow.ShowAnimateMessage(msg, "Error", 3);
- Thread.Sleep(5000);
- }
- else
- {
- if (order.OrderBuyType == "云仓")
- {
- var e57Rst = PDDBuyerOrderReadCtrl.SendTransitAfterSaleE57(pddBuyerOrderLiteInfo, "待用户发货");
- if (e57Rst.Contains("0") || e57Rst.Contains("200"))
- {
- BaseMsgWindow.ShowAnimateMessage("买手退款信息更新成功", "Msg", 3);
- isSimPddAfterSaleSuccess = true;
- Thread.Sleep(Randomx.GetId(10000, 12001));
- }
- else
- {
- var msg = BaseRegex.GetStringXml(ref e57Rst, "msg");
- BaseMsgWindow.ShowAnimateMessage("买手退款信息更新失败,服务端返回 " + msg, "Error", 3);
- }
- }
- else if (order.OrderBuyType == "直发" || order.OrderBuyType == "云改直")
- {
- var e57Rst = PDDBuyerOrderReadCtrl.SendAfterSaleE57NeedManual(pddBuyerOrderLiteInfo, "待用户发货");
- if (e57Rst.Contains("0") || e57Rst.Contains("200"))
- {
- BaseMsgWindow.ShowAnimateMessage("买手退款信息更新成功", "Msg", 3);
- isSimPddAfterSaleSuccess = true;
- Thread.Sleep(Randomx.GetId(10000, 12001));
- }
- else
- {
- var msg = BaseRegex.GetStringXml(ref e57Rst, "msg");
- BaseMsgWindow.ShowAnimateMessage("买手退款信息更新失败,服务端返回 " + msg, "Error", 3);
- }
- }
- }
- }
- if (isSimPddAfterSaleSuccess)
- {
- var addressRst = YkdBuyerOrder.GetAfterSaleAddress(buyer, pddOrderSn, pddBuyerAfterSale.afterSalesId.ParseToString());
- var merchantReceiverInfo = BaseRegex.GetOneJsonObjStrJson(ref addressRst, "merchantReceiverInfo");
- string address = "";
- if (merchantReceiverInfo != null)
- {
- address = BaseRegex.GetStringJson(ref merchantReceiverInfo, "copyValue");
- }
-
- var url3 = BaseClass.Build29WxObjString("order/wx_add_mdy_buyer_after_sale");
- var data3 = UserLogin.GetSignaturex();
- data3 += "&wx_order_id=" + pddBuyerAfterSale.wx_order_id;
- data3 += "&wx_sku_id=" + pddBuyerAfterSale.wx_sku_id;
- if (pddBuyerAfterSale.TransitCreateTime != DateTime.MinValue)
- data3 += "&TransitCreateTime=" + pddBuyerAfterSale.TransitCreateTime.ToString("yyyy-MM-dd HH:mm:ss");
- data3 += "&pre_allocated_order_no=" + pddBuyerAfterSale.pre_allocated_order_no;
- data3 += "&buyerId=" + pddBuyerAfterSale.buyerId;
- data3 += "&buyerName=" + pddBuyerAfterSale.buyerName;
- data3 += "&orderAmount=" + pddBuyerAfterSale.orderAmount;
- data3 += "&orderSn=" + pddBuyerAfterSale.orderSn;
- data3 += "&afterSalesId=" + pddBuyerAfterSale.afterSalesId;
- data3 += "&orderDate=" + pddBuyerAfterSale.orderDate;
- //data3 += "&TransitPickupTime=" + pddBuyerOrder.TransitPickupTime.ToString("yyyy-MM-dd HH:mm:ss");
- data3 += "&refundAmount=" + pddBuyerAfterSale.refundAmount;
- data3 += "&statusText=" + pddBuyerAfterSale.statusText;
- if (!string.IsNullOrEmpty(address))
- data3 += "&afterSaleAddress=" + address;
- if (order.OrderBuyType == "直发" || order.OrderBuyType == "云改直") // 云仓 0 直发 1
- data3 += "&wx_send_type=1";
- //data3 += "&is_mdy=true";
- var html3 = GetHtml.PostUtf8(url3, data3);
- if (string.IsNullOrEmpty(html3) || !html3.Contains("\"code\":200"))
- html3 = GetHtml.PostUtf8(url3, data3);
- }
- MainWindow.Instance.orderListCtrl.GetOrder(tmpOrderItem.order_id);
- Dispatcher.Invoke(new Action(() => { txtMsg.Text = "正在处理买手退货,总计:" + tmpOrderItems.Count + ",已处理:" + index; }));
- }
-
- Dispatcher.Invoke(new Action(() => { txtMsg.Text = "买手退货处理完成,总计:" + tmpOrderItems.Count + ",已处理:" + index; }));
- });
- }
-
-
- public static string WxSimAbnormalOrderSeach(ShopLoginInfo shop, int page = 1)
- {
- string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeorder/list/cgi/orderSearch?token=&lang=zh_CN";
- string referer = "https://store.weixin.qq.com/shop/order/list";
- string body = @"{""isSearch"":false,""pageSize"":100,""overTime"":0,""pengingShipOneDay"":0,""pengingShipSixHour"":0,""expediteDelivery"":0," +
- @"""stockoutPunishAlert"":0,""appointmentInstall"":0,""waybillStatus"":3,""isUserBookingDelivery"":0,""pageNum"":" + page + @",""onAftersaleOrderExist"":0,""orderStatus"":30}";
- var result = HttpResponseWXBLL.WeiXinPostResponse(shop, url, body, referer);
- return result;
- }
-
- private void btnMultiRemark_Click(object sender, RoutedEventArgs e)
- {
- wpFilterRemarkSelect.Children.Clear();
- List txts = txtFilterRemark.Text.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries).ToList();
- var remarks = GlobalConfig.lstOrder.Select(o => o.shop_remark).Distinct().ToList();
- remarks.AddRange(GlobalConfig.lstOrder.Select(o => o.soft_remark).Distinct().ToList());
- remarks = remarks.Distinct().ToList();
- foreach (var remark in remarks)
- {
- if (string.IsNullOrWhiteSpace(remark))
- continue;
- wpFilterRemarkSelect.Children.Add(new CheckBox() { Content = remark, IsChecked = txts.Contains(remark), Margin = new Thickness(2) });
- }
-
- Point position = txtFilterRemark.TranslatePoint(new Point(0, 0), gridOrderListCtrl);
- borderFilterRemarkSelect.Margin = new Thickness(position.X - 2, position.Y + txtFilterRemark.ActualHeight + 3, 0, 0);
-
- if (borderFilterRemarkSelect.Visibility == Visibility.Visible)
- borderFilterRemarkSelect.Visibility = Visibility.Collapsed;
- else
- borderFilterRemarkSelect.Visibility = Visibility.Visible;
- }
-
- private void btnCancelFilterRemark_Click(object sender, RoutedEventArgs e)
- {
- borderFilterRemarkSelect.Visibility = Visibility.Collapsed;
- }
-
- private void btnApplyFilterRemark_Click(object sender, RoutedEventArgs e)
- {
- string txt = "";
- foreach (UIElement element in wpFilterRemarkSelect.Children)
- {
- if (element is CheckBox box && box.IsChecked == true)
- {
- txt += box.Content.ParseToString() + ";";
- }
- }
- txtFilterRemark.Text = txt.TrimEnd(';');
- borderFilterRemarkSelect.Visibility = Visibility.Collapsed;
- }
-
- private void btnFilterRemarkSelectAll_Click(object sender, RoutedEventArgs e)
- {
- foreach (UIElement element in wpFilterRemarkSelect.Children)
- {
- if (element is CheckBox box)
- {
- box.IsChecked = true;
- }
- }
- }
-
- private void btnFilterRemarkUnSelectAll_Click(object sender, RoutedEventArgs e)
- {
- foreach (UIElement element in wpFilterRemarkSelect.Children)
- {
- if (element is CheckBox box)
- {
- box.IsChecked = false;
- }
- }
- }
-
- private void txtFilterRemark_TextChanged(object sender, TextChangedEventArgs e)
- {
- lstFilterText = txtFilterRemark.Text.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList();
- }
-
- private void chkEmergencyReturnOrRefund_Click(object sender, RoutedEventArgs e)
- {
- if (sender is CheckBox chk)
- {
- var isCheck = !chk.IsChecked.ParseToBool();
- chkEmergencyReturn.IsChecked = chkEmergencyRefund.IsChecked = false;
- chk.IsChecked = !isCheck;
- }
- FilterOrders();
- }
- }
+ ///
+ /// OrderListCtrl.xaml 的交互逻辑
+ ///
+ public partial class OrderListCtrl : UserControl
+ {
+ public CheckBox chkSelectAll = null;
+
+ public bool IsAutoReadOrder = true;
+ public DateTime nextGetOrderTime = DateTime.MinValue;
+
+ public string strSearchAll = "";
+ public List lstFilterText { get; set; }
+
+ public OrderListCtrl()
+ {
+ InitializeComponent();
+ DataContext = this;
+ }
+
+ private void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ lbxOrder.ItemsSource = GlobalConfig.lstFilterOrder;
+
+ dateStart.SelectedDate = DateTime.Now.Date.AddDays(-7);
+ dateEnd.SelectedDate = DateTime.Now.Date.AddDays(1).AddSeconds(-1);
+
+ borderFilterRemarkSelect.Visibility = Visibility.Collapsed;
+
+ AutoGetOrder();
+ }
+
+ public void GetOrderTest()
+ {
+ for (int i = 0; i < 10000; i++)
+ {
+ //lstOrder.Add(new oms_wei_order_info() { id = 1, IsSelect = false, order_id = ("3737033423685556736".ParseToLong() + Randomx.GetId(0,100)).ParseToString(), shop_name = "媛卡曦工厂优选" });
+ GlobalConfig.lstOrder.Add(new oms_wei_order_info() { id = 1, IsSelect = false, order_id = Randomx.GetId(1000, 10000).ParseToString(), shop_name = "媛卡曦工厂优选" });
+ }
+ //GlobalConfig.lstOrder.SortDesc(o => o.order_id.ParseToLong());
+ }
+
+ public void AutoGetOrder()
+ {
+ Task.Run(() =>
+ {
+ Thread.Sleep(5000);
+ while (true)
+ {
+ if (!IsAutoReadOrder)
+ {
+ Thread.Sleep(1000);
+ Dispatcher.Invoke(new Action(() =>
+ {
+ btnSearch.Content = "自动读单暂停中";
+ imgLoading.Visibility = Visibility.Collapsed;
+ }));
+ continue;
+ }
+
+ if (DateTime.Now > nextGetOrderTime)
+ {
+ GetOrder();
+
+ nextGetOrderTime = DateTime.Now.AddMinutes(25);
+ }
+ Thread.Sleep(1000);
+ Dispatcher.Invoke(new Action(() =>
+ {
+ var ticks = nextGetOrderTime - DateTime.Now;
+ btnSearch.Content = "读单 " + ticks.Minutes.ToString("00") + ":" + ticks.Seconds.ToString("00");
+ }));
+ }
+ });
+ }
+
+
+ public bool hasReadOrder = false;
+ ///
+ ///
+ ///
+ /// 按过滤条件读取读取服务端订单
+ public void GetOrder(string orderIds = "", bool filterGetCondition = false)
+ {
+ Dispatcher.Invoke(new Action(() =>
+ {
+ imgLoading.Visibility = Visibility.Visible;
+ btnSearch.IsEnabled = false;
+ }));
+ int page = 0;
+ int totalPage = 1;
+ int pageSize = 50;
+
+ while (true && (IsAutoReadOrder || !string.IsNullOrEmpty(orderIds)))
+ {
+ if (page >= totalPage)
+ {
+ break;
+ }
+ Dispatcher.Invoke(new Action(() =>
+ {
+ imgLoading.Visibility = Visibility.Visible;
+ btnSearch.IsEnabled = false;
+ }));
+
+ page++;
+ var url = BaseClass.Build29WxObjString("order/get_erp_order_list");
+ var data = UserLogin.GetSignaturex() + "&page=" + page;
+ if (!string.IsNullOrEmpty(orderIds))
+ data += "&erp_order_id_in=" + orderIds;
+ if (page > 1)
+ data += "&is_not_count=true";
+ data += "&page_size=" + pageSize;
+ var shop_id = string.Join(",", GlobalConfig.ShopLoginList.Select(s => s.ErpShopId).Where(s => !s.IsNullOrEmpty()));
+ //指定订单id的查询,不再查询店铺id
+ if (string.IsNullOrEmpty(orderIds))
+ data += "&erp_shop_id_in=" + shop_id;
+ Dispatcher.Invoke(new Action(() =>
+ {
+ // 按过滤条件读取
+ if (filterGetCondition)
+ {
+ if (!string.IsNullOrEmpty(txtShopName.Text.Trim()))
+ {
+ var shopNames = txtShopName.Text.Trim().Split(';').Where(s => !s.IsNullOrEmpty()).ToList();
+ shop_id = string.Join(",", GlobalConfig.ShopLoginList.Where(s => shopNames.Contains(s.ShopAccount)).Select(s => s.ErpShopId).Where(s => !s.IsNullOrEmpty()));
+ }
+ }
+ var startTime = BaseClass.DateTimeToTimestampSeconds(dateStart.SelectedDate.Value);
+ var endTime = BaseClass.DateTimeToTimestampSeconds(dateEnd.SelectedDate.Value.AddDays(1));
+ if (!chkEndDate.IsChecked.ParseToBool())
+ endTime = BaseClass.DateTimeToTimestampSeconds(DateTime.Now.Date.AddDays(1));
+ data += "&start_time=" + startTime;
+ data += "&end_time=" + endTime;
+ }));
+ Thread.Sleep(200);
+ var html = GetHtml.PostUtf8(url, data);
+ if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
+ html = GetHtml.PostUtf8(url, data);
+ if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
+ {
+ BaseMsgWindow.ShowError("订单读取失败 " + BaseRegex.GetStringJson(ref html, "msg"));
+ break;
+ }
+ var seconds = BaseRegex.GetDecimalJson(ref html, "seconds");
+
+ var jArr = JObject.Parse(html)["data"];
+ if (jArr.Count() == 0)
+ break;
+
+ var order_ids = string.Join(",", jArr.Select(a => a["order_id"].ParseToString()));
+
+ // 读取订单详情
+ if (string.IsNullOrEmpty(order_ids))
+ Thread.Sleep(100);
+ List orderItems = GetOrderItemInfo(order_ids);
+
+ // 读取售后单
+ if (string.IsNullOrEmpty(order_ids))
+ Thread.Sleep(100);
+ List refunds = GetOrderRefundInfo(order_ids);
+
+ // 读订单扩展
+ if (string.IsNullOrEmpty(order_ids))
+ Thread.Sleep(100);
+ List orderItemExts = GetOrderItemExts(order_ids);
+ if (string.IsNullOrEmpty(order_ids))
+ {
+ foreach (var oie in orderItemExts)
+ {
+ // 移除订单物流异常信息,每次批量读单最后要去微信获取
+ oie.abnormal_text = "";
+ }
+ }
+
+ // 读取中转仓拍单订单
+ var url3 = BaseClass.Build29WxObjString("order/wx_get_transit_order");
+ var data3 = UserLogin.GetSignaturex();
+ data3 += "&order_no=" + order_ids;
+ var html3 = GetHtml.PostUtf8(url3, data3);
+ if (string.IsNullOrEmpty(html3) || !html3.Contains("\"code\":200"))
+ html3 = GetHtml.PostUtf8(url3, data3);
+ if (string.IsNullOrEmpty(html3) || !html3.Contains("\"code\":200"))
+ {
+ BaseMsgWindow.ShowError("订单读取失败 " + BaseRegex.GetStringJson(ref html3, "msg"));
+ break;
+ }
+ List transitOrderList = new List();
+ try
+ {
+ transitOrderList = JsonHelper.DeserializeJsonToList(JObject.Parse(html3)["data"].ParseToString());
+ }
+ catch { }
+
+ // 读取暂时记录的买手订单,后面想办法放到中转订单库里去
+ var url4 = BaseClass.Build29WxObjString("order/wx_get_buyer_order_list");
+ var data4 = UserLogin.GetSignaturex();
+ data4 += "&wx_order_id_in=" + order_ids;
+ var html4 = GetHtml.PostUtf8(url4, data4);
+ if (string.IsNullOrEmpty(html4) || !html4.Contains("\"code\":200"))
+ html4 = GetHtml.PostUtf8(url4, data4);
+ if (string.IsNullOrEmpty(html4) || !html4.Contains("\"code\":200"))
+ {
+ Dispatcher.Invoke(new Action(() =>
+ {
+ BaseMsgWindow.ShowError("订单读取失败(买手) " + BaseRegex.GetStringJson(ref html4, "msg"));
+ }));
+ break;
+ }
+ List pddBuyerOrders = new List();
+ try
+ {
+ pddBuyerOrders = JsonHelper.DeserializeJsonToList(JObject.Parse(html4)["data"].ParseToString())
+ .OrderByDescending(p => p.TransitCreateTime).ToList();
+ }
+ catch { }
+
+ // 读取暂时记录的买手售后单,后面想办法放到中转订单库里去
+ var url6 = BaseClass.Build29WxObjString("order/wx_get_buyer_after_sale_list");
+ var data6 = UserLogin.GetSignaturex();
+ data6 += "&wx_order_id_in=" + order_ids;
+ List pddBuyerAfterSales = new List();
+ if (!string.IsNullOrEmpty(order_ids))
+ {
+ var html6 = GetHtml.PostUtf8(url6, data6);
+ if (string.IsNullOrEmpty(html6) || !html6.Contains("\"code\":200"))
+ html6 = GetHtml.PostUtf8(url6, data6);
+ if (string.IsNullOrEmpty(html6) || !html6.Contains("\"code\":200"))
+ {
+ BaseMsgWindow.ShowError("订单读取失败(买手售后) " + BaseRegex.GetStringJson(ref html6, "msg"));
+ break;
+ }
+ try
+ {
+ pddBuyerAfterSales = JsonHelper.DeserializeJsonToList(JObject.Parse(html6)["data"].ParseToString())
+ .OrderByDescending(p => p.TransitCreateTime).ToList();
+ }
+ catch
+ {
+ }
+ }
+
+ // 读取中转仓处理售后单
+ var url5 = BaseClass.Build29WxObjString("order/wx_get_transit_warehouse_aftersale_list");
+ var data5 = UserLogin.GetSignaturex();
+ data5 += "&wx_order_id_in=" + order_ids;
+ var html5 = GetHtml.PostUtf8(url5, data5);
+ if (string.IsNullOrEmpty(html5) || !html5.Contains("\"code\":200"))
+ html5 = GetHtml.PostUtf8(url5, data5);
+ if (string.IsNullOrEmpty(html5) || !html5.Contains("\"code\":200"))
+ {
+ Dispatcher.Invoke(new Action(() =>
+ {
+ BaseMsgWindow.ShowError("订单读取失败 " + BaseRegex.GetStringJson(ref html5, "msg"));
+ }));
+ break;
+ }
+ List transitAfterSaleList = new List();
+ try
+ {
+ transitAfterSaleList = JsonHelper.DeserializeJsonToList(JObject.Parse(html5)["data"].ParseToString())
+ .OrderByDescending(p => p.created_time).ToList();
+ }
+ catch { }
+
+
+ // 读取关联拍单商品
+ var urlMap = BaseClass.Build29WxObjString("order/wx_get_buy_prod_map");
+ var dataMap = UserLogin.GetSignaturex()
+ + "&spu_codes=" + string.Join(",", orderItems.Select(oi => GetHtml.UrlEncodeUtf8(oi.out_product_id))) + "," + string.Join(",", orderItems.Select(oi => oi.product_id));
+ dataMap += "&main_user_name=" + BaseClass.MainUserName;
+ var resultMap = GetHtml.PostUtf8(urlMap, dataMap);
+ if (string.IsNullOrEmpty(resultMap) || !resultMap.Contains("\"code\":200"))
+ resultMap = GetHtml.PostUtf8(urlMap, dataMap);
+ if (string.IsNullOrEmpty(resultMap) || !resultMap.Contains("\"code\":200"))
+ {
+ Dispatcher.Invoke(new Action(() =>
+ {
+ BaseMsgWindow.ShowError("订单读取失败 " + BaseRegex.GetStringJson(ref resultMap, "msg"));
+ }));
+ break;
+ }
+ List byuMapList = new List();
+ try { byuMapList = JsonHelper.DeserializeJsonToList(JObject.Parse(resultMap)["data"].ParseToString()); } catch { }
+
+
+ // 装载订单
+ foreach (JObject jObj in jArr)
+ {
+ try
+ {
+ oms_wei_order_info order = null;
+ order = JsonHelper.DeserializeJsonToObject(JsonHelper.SerializeObject(jObj));
+
+ //装载订单商品详情
+ order.orderItems = new ObservableCollection();
+ foreach (var item in orderItems.Where(oi => oi.order_id == order.order_id))
+ {
+ // 订单商品
+ item.ItemOrder = order;
+ order.orderItems.Add(item);
+
+ item.OrderItemExt = orderItemExts.FirstOrDefault(ext => ext.order_id == item.order_id && item.sku_id == item.sku_id);
+
+ // 已放到赋值函数中处理
+ // 更新店铺是否加入代发情况
+ //item.Shop = GlobalConfig.ShopLoginList.FirstOrDefault(s => s.ErpShopId == item.order_id);
+ //Dispatcher.Invoke(new Action(() => { item.UpdateOrderItemBuyButton(); }));
+
+ // 关联拍单关系 // 危险物品禁止拍单,仅关联安全商品
+ if (!GlobalConfig.lstDangerItemWord.Any(d => (item.title).ParseToString().Contains(d)))
+ {
+ item.BuyMap = byuMapList.FirstOrDefault(b => b.sku_code == item.out_sku_id && b.spu_code == item.out_product_id);
+ if (item.BuyMap == null)
+ item.BuyMap = byuMapList.FirstOrDefault(b => b.sku_code == item.sku_attr_str && b.spu_code == item.out_product_id);
+ if (item.BuyMap == null)
+ item.BuyMap = byuMapList.FirstOrDefault(b => b.sku_code == item.out_sku_id && b.spu_code == item.product_id);
+ if (item.BuyMap == null)
+ item.BuyMap = byuMapList.FirstOrDefault(b => b.sku_code == item.sku_attr_str && b.spu_code == item.product_id);
+ }
+
+ // 中转仓订单
+ if (item.ItemOrder.orderItems.Count > 1)
+ item.ItemTransitOrders.AddRange(transitOrderList.Where(t => t.order_no == item.order_id && t.order_sku_id == item.sku_id));
+ else
+ item.ItemTransitOrders.AddRange(transitOrderList.Where(t => t.order_no == item.order_id));
+ // 中转仓退货包裹订单
+ item.ItemTransitOrderAfterSales = transitAfterSaleList.Where(a => item.ItemTransitOrders.Any(t => t.out_order_no == a.order_code)).ToList();
+
+ // 中转仓买手订单(wx_send_type等于0)
+ item.PddBuyerOrders = pddBuyerOrders.Where(po => po.wx_order_id == item.order_id && po.wx_sku_id == item.sku_id && po.wx_send_type == 0).ToList();
+ // 中转仓买手退货订单(wx_send_type等于0)
+ item.PddBuyerAfterSales = pddBuyerAfterSales.Where(po => po.wx_order_id == item.order_id && po.wx_sku_id == item.sku_id && po.wx_send_type == 0).ToList();
+ // 直发买手订单(wx_send_type等于1)
+ item.PddBuyerOrders = pddBuyerOrders.Where(po => po.wx_order_id == item.order_id && po.wx_sku_id == item.sku_id && po.wx_send_type == 1).ToList();
+ // 直发买手退款订单(wx_send_type等于1)
+ item.DirectPddBuyerAfterSales = pddBuyerAfterSales.Where(po => po.wx_order_id == item.order_id && po.wx_sku_id == item.sku_id && po.wx_send_type == 1).ToList();
+ }
+
+ // 装载订单售后详情
+ order.refundItems = new ObservableCollection(refunds.Where(of => of.order_id == order.order_id));
+
+ // 读取订单后立即赋值,防止滚动时实时赋值造成卡顿
+ foreach (var orderItem in order.orderItems)
+ {
+ orderItem.SetOrderItemTextProperty();
+ }
+ order.SetOrderTextProperty();
+
+ // 删除再添加,触发更新。 todo: 如果已存在相同订单,则直接修改更新
+ var orderExist = GlobalConfig.lstOrder.FirstOrDefault(o => o.order_id == order.order_id);
+ while (orderExist != null)
+ {
+ GlobalConfig.lstOrder.Remove(orderExist);
+ orderExist = GlobalConfig.lstOrder.FirstOrDefault(o => o.order_id == order.order_id);
+ }
+ GlobalConfig.lstOrder.Add(order);
+
+ Dispatcher.Invoke(new Action(() =>
+ {
+ FilterOneOrder(order);
+ }));
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+
+ Dispatcher.Invoke(new Action(() =>
+ {
+ disPlayOrderTabOrderCount();
+ }));
+
+ var totalCount = BaseRegex.GetIntJson(ref html, "count");
+ if (totalCount > 0)
+ totalPage = Math.Ceiling(1m * totalCount / pageSize).ParseToInt();
+ else
+ {
+
+ }
+ }
+
+ if (string.IsNullOrEmpty(orderIds))
+ GetShopWaybillExceptionOrder();
+
+ if (string.IsNullOrEmpty(orderIds))
+ hasReadOrder = true;
+
+ Dispatcher.Invoke(new Action(() =>
+ {
+ imgLoading.Visibility = Visibility.Collapsed;
+ btnSearch.IsEnabled = true;
+ }));
+ }
+
+ ///
+ /// 读取订单详情信息
+ ///
+ ///
+ ///
+ public static List GetOrderItemInfo(string order_ids)
+ {
+ if (string.IsNullOrEmpty(order_ids))
+ return new List();
+ var url = BaseClass.Build29WxObjString("order/get_erp_order_item_list");
+ var data = UserLogin.GetSignaturex();
+ data += "&erp_order_id_in=" + order_ids;
+ data += "&page_size=" + 2500;
+ var html = GetHtml.PostUtf8(url, data);
+ if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
+ html = GetHtml.PostUtf8(url, data);
+ if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
+ {
+ BaseMsgWindow.ShowAnimateMessage("订单详情读取失败 " + BaseRegex.GetStringJson(ref html, "msg"), "Error", 5);
+ }
+ List orderItems = new List();
+ try
+ {
+ orderItems = JsonHelper.DeserializeJsonToList(JObject.Parse(html)["data"].ParseToString());
+ if (orderItems == null)
+ orderItems = new List();
+ }
+ catch (Exception ex)
+ {
+ orderItems = new List();
+ BaseMsgWindow.ShowAnimateMessage("订单详情读取失败 " + ex.Message, "Error", 5);
+ }
+ return orderItems;
+ }
+
+ public static List GetOrderItemExts(string order_ids)
+ {
+ List existOrderExtList = new List();
+ if (!string.IsNullOrEmpty(order_ids))
+ {
+ var url = BaseClass.Build29WxObjString("order/wx_get_order_item_ext_info");
+ var data = UserLogin.GetSignaturex();
+ data += "&wx_order_id_in=" + order_ids;
+ var html = GetHtml.PostUtf8(url, data);
+ if (!html.Contains("\"code\":200"))
+ html = GetHtml.PostUtf8(url, data);
+ if (!html.Contains("\"code\":200"))
+ {
+ BaseMsgWindow.ShowAnimateMessage("订单扩展信息查询失败 " + BaseRegex.GetStringJson(ref html, "msg"), "Error", 5);
+ }
+ existOrderExtList = JsonHelper.DeserializeJsonToList(JsonHelper.JObjectParse(html)["data"].ParseToString());
+ }
+ return existOrderExtList;
+ }
+
+ ///
+ /// 读取售后单
+ ///
+ ///
+ ///
+ public static List GetOrderRefundInfo(string order_ids)
+ {
+ if (string.IsNullOrEmpty(order_ids))
+ return new List();
+ Thread.Sleep(100);
+ var url2 = BaseClass.Build29WxObjString("order/get_erp_refund_list");
+ var data2 = UserLogin.GetSignaturex();
+ data2 += "&erp_order_id_in=" + order_ids;
+ var html2 = GetHtml.PostUtf8(url2, data2);
+ if (string.IsNullOrEmpty(html2) || !html2.Contains("\"code\":200"))
+ html2 = GetHtml.PostUtf8(url2, data2);
+ if (string.IsNullOrEmpty(html2) || !html2.Contains("\"code\":200"))
+ {
+ //BaseMsgWindow.ShowError(MainWindow.Instance, "订单读取失败 " + BaseRegex.GetStringJson(ref html, "msg"));
+ //break;
+ }
+ List refunds = new List();
+ try { refunds = JsonHelper.DeserializeJsonToList(JObject.Parse(html2)["data"].ParseToString()); } catch { }
+ return refunds;
+ }
+
+ public void GetShopWaybillExceptionOrder()
+ {
+ foreach (var shop in GlobalConfig.ShopLoginList)
+ {
+ if (shop.LoginStatus == "登录成功")
+ ShopBLL.CheckShopLogin(shop);
+ if (shop.LoginStatus != "登录成功")
+ continue;
+
+ var rst = WxSimAbnormalOrderSeach(shop, 100);
+ //Thread.Sleep(Randomx.GetId(50, 150));
+ if (rst.Contains("\"code\":0"))
+ {
+ try
+ {
+ JObject jObj = JsonHelper.JObjectParse(rst);
+ var wxOrderIdIn = string.Join(",", jObj["orderList"].Select(j => j["commonInfo"]["orderId"].ParseToString()));
+ var wxSkuIdIn = string.Join(",", jObj["orderList"].Select(j => (j["orderProductInfo"].FirstOrDefault()?["skuId"]).ParseToString()));
+
+ // 异常单
+ List existOrderExtList = new List();
+ if (!string.IsNullOrEmpty(wxOrderIdIn) && !string.IsNullOrEmpty(wxSkuIdIn))
+ {
+ var url = BaseClass.Build29WxObjString("order/wx_get_order_item_ext_info");
+ var data = UserLogin.GetSignaturex();
+ data += "&wx_order_id_in=" + wxOrderIdIn;
+ data += "&wx_sku_id_in=" + wxSkuIdIn;
+ var html = GetHtml.PostUtf8(url, data);
+ if (!html.Contains("\"code\":200"))
+ html = GetHtml.PostUtf8(url, data);
+ if (!html.Contains("\"code\":200"))
+ {
+ BaseMsgWindow.ShowAnimateMessage("订单扩展信息查询失败 " + BaseRegex.GetStringJson(ref html, "msg"), "Error", 5);
+ continue;
+ }
+ existOrderExtList = JsonHelper.DeserializeJsonToList(JsonHelper.JObjectParse(html)["data"].ParseToString());
+ }
+
+ // 先把已经物流异常但未查询到的订单改为正常
+ var waybillExceptionOrders = GlobalConfig.lstOrder.Where(o => o.shop_id.ParseToString() == shop.ErpShopId && o.orderItems.Any(oi => oi.ShopWaybillExceptionStr == "物流异常")).ToList();
+ foreach (var waybillExceptionOrder in waybillExceptionOrders)
+ {
+ if (!existOrderExtList.Any(oExt => oExt.order_id == waybillExceptionOrder.order_id))
+ {
+ foreach (var orderItem in waybillExceptionOrder.orderItems)
+ {
+ if (orderItem.OrderItemExt != null)
+ {
+ orderItem.OrderItemExt.abnormal_text = "";
+ orderItem.ShopWaybillExceptionStr = "";
+ }
+ }
+
+ // 更新显示
+ Dispatcher.Invoke(new Action(() =>
+ {
+ foreach (var oi in waybillExceptionOrder.orderItems)
+ oi.SetOrderItemTextProperty();
+ waybillExceptionOrder.SetOrderTextProperty();
+
+ MainWindow.Instance.orderListCtrl.FilterOneOrder(waybillExceptionOrder, true);
+ }));
+
+ var orderId = waybillExceptionOrder.order_id;
+ order_item_ext orderExt = new order_item_ext() { order_id = orderId, shop_app_id = shop.ShopId, shop_name = shop.ShopAccount, abnormal_text = "物流异常" };
+
+ var url1 = BaseClass.Build29WxObjString("order/wx_mdy_order_item_ext_info");
+ var data1 = UserLogin.GetSignaturex();
+ data1 += "&wx_order_id=" + orderExt.order_id;
+ data1 += "&abnormal_text=";
+ var html1 = GetHtml.PostUtf8(url1, data1);
+ if (string.IsNullOrEmpty(html1) || !html1.Contains("\"code\":200"))
+ html1 = GetHtml.PostUtf8(url1, data1);
+ }
+ }
+
+ foreach (var od in jObj["orderList"])
+ {
+ var oStr = JsonHelper.SerializeObject(od);
+
+ //var orderId = o["commonInfo"]["orderId"].ParseToString();
+ var orderId = BaseRegex.GetStringJson(ref oStr, "orderId");
+
+ if (orderId == "3737914129536416512")
+ {
+
+ }
+ var skuId = BaseRegex.GetStringJson(ref oStr, "skuId");
+
+ // 存在状态完全一样的订单异常信息就跳过
+ order_item_ext orderExt = new order_item_ext() { order_id = orderId, sku_id = skuId, shop_app_id = shop.ShopId, shop_name = shop.ShopAccount, abnormal_text = "物流异常" };
+
+ if (!existOrderExtList.Any(eoe => eoe.order_id == orderExt.order_id && eoe.sku_id == orderExt.sku_id && eoe.abnormal_text == orderExt.abnormal_text))
+ {
+ var url1 = BaseClass.Build29WxObjString("order/wx_add_order_item_ext_info");
+ if (existOrderExtList.Any(eoe => eoe.order_id == orderExt.order_id && eoe.sku_id == orderExt.sku_id))
+ url1 = BaseClass.Build29WxObjString("order/wx_mdy_order_item_ext_info");
+ var data1 = UserLogin.GetSignaturex();
+ data1 += "&wx_order_id=" + orderExt.order_id;
+ data1 += "&wx_sku_id=" + orderExt.sku_id;
+ data1 += "&shop_app_id=" + orderExt.shop_app_id;
+ data1 += "&shop_name=" + orderExt.shop_name;
+ data1 += "&abnormal_text=" + orderExt.abnormal_text;
+ var html1 = GetHtml.PostUtf8(url1, data1);
+ if (string.IsNullOrEmpty(html1) || !html1.Contains("\"code\":200"))
+ {
+ BaseMsgWindow.ShowAnimateMessage("订单扩展信息写入失败 " + BaseRegex.GetStringJson(ref html1, "msg"), "Error", 5);
+ break;
+ }
+ }
+ else
+ {
+ orderExt = existOrderExtList.FirstOrDefault(eoe => eoe.order_id == orderExt.order_id && eoe.sku_id == orderExt.sku_id && eoe.abnormal_text == orderExt.abnormal_text);
+ }
+
+ // 更新订单附加信息
+ if (orderExt.order_id == "3737845591459133952")
+ {
+
+ }
+ var order = GlobalConfig.lstOrder.FirstOrDefault(o => o.order_id == orderExt.order_id);
+ if (order != null)
+ {
+ var orderItem = order.orderItems.FirstOrDefault(oi => oi.sku_id == orderExt.sku_id);
+ if (orderItem != null)
+ {
+ orderItem.OrderItemExt = orderExt;
+ Dispatcher.Invoke(new Action(() =>
+ {
+ foreach (var oi in order.orderItems)
+ oi.SetOrderItemTextProperty();
+ order.SetOrderTextProperty();
+
+ MainWindow.Instance.orderListCtrl.FilterOneOrder(order, true);
+ }));
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ BaseMsgWindow.ShowAnimateMessage("订单扩展信息查询失败 " + ex.Message, "Error", 5);
+ }
+ }
+ }
+ }
+
+ public void disPlayOrderTabOrderCount()
+ {
+
+ var orders = string.Join("','", GlobalConfig.lstFilterOrder.Select(o => o.order_id));
+ var orders1 = string.Join(",", GlobalConfig.lstFilterOrder.Select(o => o.order_id));
+
+
+
+ var tabItems = this.tabOrderType.Items.Cast();
+ var tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("待采购"));
+ var userOrderLst = GlobalConfig.lstOrder.Where(o => GlobalConfig.ShopLoginList.Any(s => s.ErpShopId.ParseToLong() == o.shop_id)).ToList();
+ if (tabItem != null)
+ {
+ var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "待采购")));
+ //tabItem.Header = "待采购(" + userOrderLst.Where(r => r.IsWaitBuy).Count() + "|" + filteLstTmp.Where(r => r.IsWaitBuy).Count() + ")";
+ tabItem.Header = "待采购(" + userOrderLst.Where(r => r.IsWaitBuy).Count() + "|" + filteLstTmp.Count() + ")";
+ }
+ tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("待发货"));
+ if (tabItem != null)
+ {
+ var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "待发货")));
+ //tabItem.Header = "待发货(" + userOrderLst.Where(r => r.IsWaitSend).Count() + "|" + filteLstTmp.Where(r => r.IsWaitSend).Count() + ")";
+ tabItem.Header = "待发货(" + userOrderLst.Where(r => r.IsWaitSend).Count() + "|" + filteLstTmp.Count() + ")";
+ }
+ tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("待收货"));
+ if (tabItem != null)
+ {
+ var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "待收货")));
+ //tabItem.Header = "待收货(" + userOrderLst.Where(r => r.IsWaitReceive).Count() + "|" + filteLstTmp.Where(r => r.IsWaitReceive).Count() + ")";
+ tabItem.Header = "待收货(" + userOrderLst.Where(r => r.IsWaitReceive).Count() + "|" + filteLstTmp.Count() + ")";
+ }
+ tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("售后完成单"));
+ if (tabItem != null)
+ {
+ var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "售后完成单")));
+ //tabItem.Header = "售后完成单(" + userOrderLst.Where(r => r.IsRefund).Count() + "|" + filteLstTmp.Where(r => r.IsRefund).Count() + ")";
+ tabItem.Header = "售后完成单(" + userOrderLst.Where(r => r.IsRefund).Count() + "|" + filteLstTmp.Count() + ")";
+ }
+ tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("需处理售后单"));
+ if (tabItem != null)
+ {
+ var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "需处理售后单")));
+ //tabItem.Header = "需处理售后单(" + userOrderLst.Where(r => r.IsEmergency).Count() + "|" + filteLstTmp.Where(r => r.IsEmergency).Count() + ")";
+ tabItem.Header = "需处理售后单(" + userOrderLst.Where(r => r.IsEmergency).Count() + "|" + filteLstTmp.Count() + ")";
+ }
+ tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("异常单"));
+ if (tabItem != null)
+ {
+ var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "异常单")));
+ //tabItem.Header = "异常单(" + userOrderLst.Where(r => r.isAbnormal).Count() + "|" + filteLstTmp.Where(r => r.isAbnormal).Count() + ")";
+ tabItem.Header = "异常单(" + userOrderLst.Where(r => r.isAbnormal).Count() + "|" + filteLstTmp.Count() + ")";
+ }
+ tabItem = tabItems.FirstOrDefault(t => t.Header.ParseToString().StartsWith("全部订单"));
+ if (tabItem != null)
+ {
+ var filteLstTmp = new ObservableCollection(userOrderLst.Where(o => !GetOrderIsFilter(o, "全部订单")));
+ tabItem.Header = "全部订单(" + userOrderLst.Count() + "|" + filteLstTmp.Count() + ")";
+ }
+ //txtMsg.Text = "当前条件共计 " + GlobalConfig.lstFilterOrder.Count() + " 条订单记录";
+ }
+
+ public void FilterOrders()
+ {
+ try
+ {
+ if (this.lbxOrder == null)
+ return;
+
+ Dispatcher.Invoke(new Action(() =>
+ {
+ if (GlobalConfig.OrderTabHeaderStr.StartsWith("需处理售后单"))
+ GlobalConfig.lstFilterOrder = new ObservableCollectionThreadSafe(GlobalConfig.lstOrder.Where(o => !GetOrderIsFilter(o)).OrderByDescending(o => o.RefundDatetime));
+ else if (GlobalConfig.OrderTabHeaderStr.StartsWith("异常单"))
+ GlobalConfig.lstFilterOrder = new ObservableCollectionThreadSafe(GlobalConfig.lstOrder.Where(o => !GetOrderIsFilter(o)).OrderByDescending(o => o.update_time));
+ else
+ GlobalConfig.lstFilterOrder = new ObservableCollectionThreadSafe(GlobalConfig.lstOrder.Where(o => !GetOrderIsFilter(o)).OrderByDescending(o => o.create_time));
+ this.lbxOrder.ItemsSource = GlobalConfig.lstFilterOrder;
+
+ disPlayOrderTabOrderCount();
+ }));
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+
+ public void FilterOneOrder(oms_wei_order_info order, bool updateTabCount = false)
+ {
+ var orderExist = GlobalConfig.lstFilterOrder.FirstOrDefault(o => o.order_id == order.order_id);
+ while (orderExist != null)
+ {
+ GlobalConfig.lstFilterOrder.Remove(orderExist);
+ orderExist = GlobalConfig.lstFilterOrder.FirstOrDefault(o => o.order_id == order.order_id);
+ }
+
+ if (!GetOrderIsFilter(order))
+ {
+ oms_wei_order_info nextOrder = null;
+ if (GlobalConfig.OrderTabHeaderStr.StartsWith("需处理售后单"))
+ nextOrder = GlobalConfig.lstFilterOrder.FirstOrDefault(o => o.RefundDatetime < order.RefundDatetime);
+ else if (GlobalConfig.OrderTabHeaderStr.StartsWith("异常单"))
+ nextOrder = GlobalConfig.lstFilterOrder.FirstOrDefault(o => o.update_time < order.update_time);
+ else
+ nextOrder = GlobalConfig.lstFilterOrder.FirstOrDefault(o => o.create_time < order.create_time);
+
+ if (nextOrder != null)
+ {
+ GlobalConfig.lstFilterOrder.Insert(GlobalConfig.lstFilterOrder.IndexOf(nextOrder), order);
+ }
+ else
+ {
+ GlobalConfig.lstFilterOrder.Add(order);
+ }
+ }
+
+ if (updateTabCount)
+ {
+ Dispatcher.Invoke(new Action(() =>
+ {
+ disPlayOrderTabOrderCount();
+ }));
+ }
+ }
+
+ bool GetOrderIsFilter(oms_wei_order_info order, string filterHeadStr = null)
+ {
+ if (order == null)
+ return true;
+
+ if (!GlobalConfig.ShopLoginList.Any(s => s.ErpShopId.ParseToLong() == order.shop_id))
+ return true;
+
+ if (!string.IsNullOrEmpty(strSearchAll))
+ {
+ bool isFilter = true;
+ // 买手物流
+ if (order.orderItems.Any(oi => oi.ItemTransitOrders.Any(t => t.express_1_waybill.ParseToString().Contains(strSearchAll))))
+ isFilter = false;
+ // 仓库物流
+ else if (order.orderItems.Any(oi => oi.ItemTransitOrders.Any(t => t.express_2_waybill.ParseToString().Contains(strSearchAll))))
+ isFilter = false;
+ // 退货物流
+ else if (order.refundItems.Any(ri => ri.return_waybill_id.ParseToString().Contains(strSearchAll)))
+ isFilter = false;
+ // 退货单号
+ else if (order.refundItems.Any(ri => ri.after_sale_order_id.ParseToString().Contains(strSearchAll)))
+ isFilter = false;
+ // 仓库采购单号
+ else if (order.orderItems.Any(oi => oi.ItemTransitOrders.Any(t => t.out_order_no.ParseToString().Contains(strSearchAll))))
+ isFilter = false;
+ // 仓库退款单号
+ else if (order.orderItems.Any(oi => oi.ItemTransitOrderAfterSales.Any(t => t.refund_waybill.ParseToString().Contains(strSearchAll))))
+ isFilter = false;
+ if (isFilter)
+ return true;
+ }
+
+ // 过滤店铺名称
+ if (!string.IsNullOrEmpty(txtShopName.Text.Trim()) && !(";" + txtShopName.Text.Trim() + ";").Contains(";" + order.shop_name + ";"))
+ {
+ return true;
+ }
+ // 过滤商品名称
+ if (!string.IsNullOrEmpty(txtGoodsName.Text.Trim()) && !order.orderItems.Any(it => it.title.Contains(txtGoodsName.Text.Trim())))
+ {
+ return true;
+ }
+ // 过滤id
+ if (!string.IsNullOrEmpty(txtOrderId.Text.Trim()) && !(";" + txtOrderId.Text.Trim().Replace(' ', ';').Replace(',', ';') + ";").Contains(";" + order.order_id + ";"))
+ {
+ return true;
+ }
+ // 过滤多子单订单
+ if (chkNoMultiOrder.IsChecked.ParseToBool() && order.orderItems.Count() > 1)
+ {
+ return true;
+ }
+ // 过滤非中转仓订单
+ if (chkOnlyWarehouseOrder.IsChecked.ParseToBool() && !order.IsWaitBuy &&
+ order.orderItems.All(oi => oi.ItemTransitOrderWithVoid == null) && order.orderItems.All(oi => oi.OrderItemExt?.buy_type != "直发"))
+ {
+ return true;
+ }
+ // 过滤备注
+ if (chkFilterRemark.IsChecked == true && !string.IsNullOrEmpty(txtFilterRemark.Text))
+ {
+ if (cmbFilterRemark.SelectedItem is ComboBoxItem comboBoxItem)
+ {
+ if (comboBoxItem.Content is TextBlock tb)
+ {
+ if (tb.Text == "店铺备注包含" && !lstFilterText.Contains(order.shop_remark))
+ return true;
+ else if (tb.Text == "软件备注包含" && !lstFilterText.Contains(order.soft_remark))
+ return true;
+ else if (tb.Text == "店铺备注不含" && lstFilterText.Contains(order.shop_remark))
+ return true;
+ else if (tb.Text == "软件备注不含" && lstFilterText.Contains(order.soft_remark))
+ return true;
+ }
+ }
+ }
+ if (!chkDirectOrder.IsChecked == true && order.OrderBuyType == "直发")
+ return true;
+ if (!chkTransitOrder.IsChecked == true && order.OrderBuyType == "云仓")
+ return true;
+ if (!chkTransitChangeDirectOrder.IsChecked == true && order.OrderBuyType == "云改直")
+ return true;
+
+ // 过滤时间范围
+ if (cmbTimeType.SelectedItem is ComboBoxItem cbi)
+ {
+ if (cbi.Content is TextBlock tb)
+ {
+ if (tb.Text == "更新时间")
+ {
+ if (order.UpdateDateTime < dateStart.SelectedDate.Value)
+ return true;
+ if (chkEndDate.IsChecked == true && order.UpdateDateTime > dateEnd.SelectedDate.Value)
+ return true;
+ }
+ if (tb.Text == "创建时间")
+ {
+ if (order.CreateDateTime < dateStart.SelectedDate.Value)
+ return true;
+ if (chkEndDate.IsChecked == true && order.CreateDateTime > dateEnd.SelectedDate.Value)
+ return true;
+ }
+ }
+ }
+
+ // 过滤标签页
+ if (filterHeadStr.IsNullOrEmpty())
+ filterHeadStr = GlobalConfig.OrderTabHeaderStr;
+
+ if (filterHeadStr.StartsWith("全部订单"))
+ {
+ return false;
+ }
+ if (filterHeadStr.StartsWith("待采购"))
+ {
+ if (!order.IsWaitBuy)
+ return true;
+ //if (order.IsRefund)
+ // return true;
+ if (chkMapProdOnly.IsChecked == true && order.orderItems.All(oi => oi.BuyMap == null))
+ return true;
+ if (chkNoMapProdOnly.IsChecked == true && order.orderItems.All(oi => oi.BuyMap != null))
+ return true;
+ }
+ if (filterHeadStr.StartsWith("待发货") && !order.IsWaitSend)
+ {
+ return true;
+ }
+ if (filterHeadStr.StartsWith("待收货"))
+ {
+ if (!order.IsWaitReceive)
+ return true;
+
+ if (chkWaitReceiveBuyerIsNotSend.IsChecked == true && order.orderItems.All(oi => oi.BuyerTransitWaybillStatusStr != "买手未发货"))
+ return true;
+ if (chkWaitReceiveBuyerIsSend.IsChecked == true && order.orderItems.All(oi => oi.BuyerTransitWaybillStatusStr != "买手已发货"))
+ return true;
+ if (chkWaitReceiveBuyerIsInWarehouse.IsChecked == true && order.orderItems.All(oi => oi.BuyerTransitWaybillStatusStr != "买手已送达"))
+ return true;
+
+ if (chkWaitReceiveWarehouseIsNotPickup.IsChecked == true && order.orderItems.All(oi => oi.WarehouseWaybillStatusStr != "中转待取号"))
+ return true;
+ if (chkWaitReceiveWarehouseIsPickup.IsChecked == true && order.orderItems.All(oi => oi.WarehouseWaybillStatusStr != "中转提前取号" && oi.WarehouseWaybillStatusStr != "中转已取号" && oi.WarehouseWaybillStatusStr != "中转已入库"))
+ return true;
+ if (chkWaitReceiveWarehouseIsSendOut.IsChecked == true && order.orderItems.All(oi => oi.WarehouseWaybillStatusStr != "中转已出库"))
+ return true;
+ }
+ if (filterHeadStr.StartsWith("异常单") && !order.isAbnormal)
+ {
+ return true;
+ }
+ if (filterHeadStr.StartsWith("需处理售后单"))
+ {
+ if (!order.IsEmergency)
+ return true;
+
+ if (chkEmergencyBuyerWaitAfterSale.IsChecked == true && order.orderItems.All(oi => !oi.TransitRefundStatusStr.Contains("需手动申请售后")))
+ return true;
+ else if (chkEmergencyBuyerWaitSendBack.IsChecked == true && order.orderItems.All(oi => !oi.TransitRefundStatusStr.Contains("待用户发货")))
+ return true;
+ else if (chkEmergencyBuyerWaitSupplierRefund.IsChecked == true && order.orderItems.All(oi => !oi.TransitRefundStatusStr.Contains("商家处理中")))
+ return true;
+ else if (chkEmergencyBuyerRefundFail.IsChecked == true && order.orderItems.All(oi => !oi.TransitRefundStatusStr.Contains("退款失败")))
+ return true;
+
+ if (chkEmergencyShopCustomRefundHasWaybill.IsChecked == true && order.orderItems.Any(oi => oi.ReturnWaybillIdStr.IsNullOrEmpty()))
+ return true;
+ else if (chkEmergencyShopCustomRefundNoWaybill.IsChecked == true && order.orderItems.All(oi => !oi.ReturnWaybillIdStr.IsNullOrEmpty()))
+ return true;
+
+ if (order.order_id == "3737838342857424896")
+ {
+
+ }
+
+ // 退款完成
+ if (chkEmergencyShopAfterSaleSuccess.IsChecked == true && order.DeliveryDeadlineDtatusStr != "退款完成")
+ return true;
+ // 退款中
+ else if (chkEmergencyShopInAfterSale.IsChecked == true && (order.DeliveryDeadlineDtatusStr != "退款中"))
+ return true;
+
+ //// 退货退款
+ //if (chkEmergencyReturn.IsChecked == true && !(order.refundItems.OrderByDescending(or => or.create_time).FirstOrDefault()?.RefundStatusStr).ParseToString().Contains("退货"))
+ // return true;
+ //// 仅退款
+ //else if (chkEmergencyRefund.IsChecked == true && (order.refundItems.OrderByDescending(or => or.create_time).FirstOrDefault()?.RefundStatusStr).ParseToString().Contains("退货"))
+ // return true;
+ // 退货退款
+ if (chkEmergencyReturn.IsChecked == true && !(order.refundItems.OrderByDescending(or => or.create_time).FirstOrDefault()?.type).ParseToString().Contains("RETURN"))
+ return true;
+ // 仅退款
+ else if (chkEmergencyRefund.IsChecked == true && !(order.refundItems.OrderByDescending(or => or.create_time).FirstOrDefault()?.type).ParseToString().Contains("REFUND"))
+ return true;
+ }
+ if (filterHeadStr.StartsWith("售后完成单"))
+ {
+ if (!order.IsRefund)
+ return true;
+
+ if (chkAftersaleIsSend.IsChecked == true && !order.DeliveryDeadlineStr.Contains("已发货"))
+ return true;
+ else if (chkAftersaleIsNotSend.IsChecked == true && !order.DeliveryDeadlineStr.Contains("未发货"))
+ return true;
+
+ if (chkAftersaleBuyerIsBuy.IsChecked == true && order.orderItems.All(oi => oi.BuyerTransitWaybillStatusStr.IsNullOrEmpty()))
+ return true;
+ if (chkAftersaleWarehouseIsNotPickup.IsChecked == true && order.orderItems.All(oi => oi.WarehouseWaybillStatusStr != "中转待取号" && !oi.WarehouseWaybillStatusStr.Contains("取号异常")))
+ return true;
+ if (chkAftersaleWarehouseIsPickup.IsChecked == true && order.orderItems.All(oi => oi.WarehouseWaybillStatusStr != "中转提前取号" && oi.WarehouseWaybillStatusStr != "中转已取号" &&
+ oi.WarehouseWaybillStatusStr != "中转已入库" && oi.WarehouseWaybillStatusStr != "中转已出库"))
+ return true;
+ }
+
+ return false;
+ }
+
+ private void btnMultiShopChoice_Click(object sender, RoutedEventArgs e)
+ {
+ MainWindow.Instance.shopListCtrl.IsVisibleChanged -= ShopListCtrl_IsVisibleChanged;
+ MainWindow.Instance.shopListCtrl.Visibility = Visibility.Visible;
+ MainWindow.Instance.shopListCtrl.IsVisibleChanged += ShopListCtrl_IsVisibleChanged;
+ }
+
+ private void ShopListCtrl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ if (!MainWindow.Instance.shopListCtrl.IsVisible && MainWindow.Instance.shopListCtrl.IsAcceptChoiceShop == true)
+ {
+ var list = MainWindow.Instance.shopListCtrl.lbxShop.ItemsSource as ObservableCollection;
+ if (list != null)
+ this.txtShopName.Text = string.Join(";", list.Where(s => s.IsSelect == true).Select(s => s.ShopAccount));
+
+ FilterOrders();
+
+ }
+ MainWindow.Instance.shopListCtrl.IsVisibleChanged -= ShopListCtrl_IsVisibleChanged;
+ }
+
+ private void btnSearch_Click(object sender, RoutedEventArgs e)
+ {
+ this.btnSearch.IsEnabled = false;
+
+ Task.Run(() =>
+ {
+ Thread.Sleep(5000);
+ Dispatcher.Invoke(new Action(() => { this.btnSearch.IsEnabled = true; }));
+ });
+ Task.Run(() =>
+ {
+ while (!MainWindow.Instance.hasReadShop)
+ {
+ Thread.Sleep(100);
+ }
+
+ GetOrder();
+ nextGetOrderTime = DateTime.Now.AddMinutes(25);
+ });
+ }
+
+ private void btnFilter_Click(object sender, RoutedEventArgs e)
+ {
+ FilterOrders();
+ }
+
+ private void dgOrderHeader_ColumnDisplayIndexChanged(object sender, DataGridColumnEventArgs e)
+ {
+ }
+
+ private void dgOrderHeader_LayoutUpdated(object sender, EventArgs e)
+ {
+ foreach (var item in lbxOrder.Items)
+ {
+ ListBoxItem container = (ListBoxItem)lbxOrder.ItemContainerGenerator.ContainerFromIndex(lbxOrder.Items.IndexOf(item));
+ if (container != null)
+ {
+ // 找到grid控件并修改列大小
+ var grids = UiCtrlUtils.FindVisualChildAll(container, "gridListItem");
+ foreach (var grid in grids)
+ {
+ for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
+ {
+ if (dgOrderHeader.Columns.Count > i)
+ {
+ // 最后一列因滚动条变窄,已在表头补偿
+ if (i == grid.ColumnDefinitions.Count - 1)
+ grid.ColumnDefinitions[i].Width = new GridLength(Math.Max(0, dgOrderHeader.Columns[i].ActualWidth - 0));
+ else
+ grid.ColumnDefinitions[i].Width = new GridLength(dgOrderHeader.Columns[i].ActualWidth);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void ChkSelectAll_Checked(object sender, RoutedEventArgs e)
+ {
+ foreach (var order in GlobalConfig.lstOrder.ToList())
+ {
+ order.IsSelect = true;
+ }
+ }
+
+ private void ChkSelectAll_Unchecked(object sender, RoutedEventArgs e)
+ {
+ foreach (var order in GlobalConfig.lstOrder.ToList())
+ {
+ order.IsSelect = false;
+ }
+ }
+
+ private void ChkSelectAll_Loaded(object sender, RoutedEventArgs e)
+ {
+ chkSelectAll = sender as CheckBox;
+ }
+
+ public void UpdateChkAllBox()
+ {
+ chkSelectAll.Checked -= ChkSelectAll_Checked;
+ chkSelectAll.Unchecked -= ChkSelectAll_Unchecked;
+ if (GlobalConfig.lstFilterOrder.All(s => s.IsSelect))
+ chkSelectAll.IsChecked = true;
+ else if (GlobalConfig.lstFilterOrder.All(s => !s.IsSelect))
+ chkSelectAll.IsChecked = false;
+ else
+ chkSelectAll.IsChecked = null;
+ chkSelectAll.Checked += ChkSelectAll_Checked;
+ chkSelectAll.Unchecked += ChkSelectAll_Unchecked;
+ }
+
+ private void txtSearchAll_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ strSearchAll = txtSearchAll.Text.Trim();
+ }
+
+ private void tabOrderType_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ GlobalConfig.OrderTabHeaderStr = ((tabOrderType.SelectedItem as TabItem)?.Header).ParseToString();
+ FilterOrders();
+ }
+
+ private void chkMapProdOnly_Click(object sender, RoutedEventArgs e)
+ {
+ if (chkMapProdOnly.IsChecked == true)
+ chkNoMapProdOnly.IsChecked = false;
+ FilterOrders();
+ }
+ private void chkNoMapProdOnly_Click(object sender, RoutedEventArgs e)
+ {
+ if (chkNoMapProdOnly.IsChecked == true)
+ chkMapProdOnly.IsChecked = false;
+ FilterOrders();
+ }
+
+ public static string addNotes(ShopLoginInfo shop, string orderId, string notes, int tagColor = -1)
+ {
+ string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeorder/common/cgi/batchMerchantNotes?token=&lang=zh_CN";
+ string body = @"{""items"":[{""orderId"":""" + orderId + @""",""merchantNotes"":""" + notes + @""",""merchantNotesTagColor"":" + tagColor + @"}]}";
+ if (tagColor == -1)
+ body = @"{""items"":[{""orderId"":""" + orderId + @""",""merchantNotes"":""" + notes + @"""}]}";
+
+ string refere = "https://store.weixin.qq.com/shop/order/list";
+ var result = HttpResponseWXBLL.WeiXinPostResponse(shop, url, body, refere);
+ return result;
+ }
+ public static string addNotesFlag(ShopLoginInfo shop, string orderId, string notes, int tagColor = 0)
+ {
+ string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeorder/common/cgi/batchMerchantNotes?token=&lang=zh_CN";
+ string body = @"{""items"":[{""orderId"":""" + orderId + @""",""merchantNotesTagColor"":" + tagColor + @"}]}";
+
+ string refere = "https://store.weixin.qq.com/shop/order/list";
+ var result = HttpResponseWXBLL.WeiXinPostResponse(shop, url, body, refere);
+ return result;
+ }
+
+ private void chkAutoReadBuyerOrder_CheckedChanged(object sender, RoutedEventArgs e)
+ {
+ IsAutoReadOrder = chkAutoReadOrder.IsChecked == true;
+ }
+
+ private void TabItem_SizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ var tabItems = this.tabOrderType.Items.Cast();
+ wpFilter.Margin = new Thickness(tabItems.Sum(t => t.ActualWidth) + 18, wpFilter.Margin.Top, wpFilter.Margin.Right, wpFilter.Margin.Bottom);
+
+ Point position1 = txtFilterRemark.TranslatePoint(new Point(0, 0), gridOrderListCtrl);
+ Point position2 = txtFilterRemark.TranslatePoint(new Point(0, 0), wpFilter);
+ borderFilterRemarkSelect.Margin = new Thickness(tabItems.Sum(t => t.ActualWidth) + 16 + position2.X, position1.Y + txtFilterRemark.ActualHeight + 3, 0, 0);
+ }
+
+ private void chkSubFilterSonditions_Checked(object sender, RoutedEventArgs e)
+ {
+ FilterOrders();
+ }
+
+ ///
+ /// 待处理订单买手售后状态过滤
+ ///
+ private void chkEmergencyBuyerAfterSale_Click(object sender, RoutedEventArgs e)
+ {
+ if (sender is CheckBox chk)
+ {
+ var isCheck = !chk.IsChecked.ParseToBool();
+ chkEmergencyBuyerWaitAfterSale.IsChecked = chkEmergencyBuyerWaitSendBack.IsChecked = chkEmergencyBuyerWaitSupplierRefund.IsChecked = chkEmergencyBuyerRefundFail.IsChecked = false;
+ chk.IsChecked = !isCheck;
+ }
+ FilterOrders();
+ }
+ ///
+ /// 待处理订单店铺买家售后物流状态过滤
+ ///
+ private void chkEmergencyShopCustomRefundWaybill_Click(object sender, RoutedEventArgs e)
+ {
+ if (sender is CheckBox chk)
+ {
+ var isCheck = !chk.IsChecked.ParseToBool();
+ chkEmergencyShopCustomRefundHasWaybill.IsChecked = chkEmergencyShopCustomRefundNoWaybill.IsChecked = false;
+ chk.IsChecked = !isCheck;
+ }
+ FilterOrders();
+ }
+ ///
+ /// 待处理订单店铺售后状态过滤
+ ///
+ ///
+ ///
+ private void chkEmergencyShopAfterSale_Click(object sender, RoutedEventArgs e)
+ {
+ if (sender is CheckBox chk)
+ {
+ var isCheck = !chk.IsChecked.ParseToBool();
+ chkEmergencyShopAfterSaleSuccess.IsChecked = chkEmergencyShopInAfterSale.IsChecked = false;
+ chk.IsChecked = !isCheck;
+ }
+ FilterOrders();
+ }
+
+ ///
+ /// 待收货 买手发货状态
+ ///
+ ///
+ ///
+ private void chkWaitReceiveBuyerStatus_Click(object sender, RoutedEventArgs e)
+ {
+ if (sender is CheckBox chk)
+ {
+ var isCheck = !chk.IsChecked.ParseToBool();
+ chkWaitReceiveBuyerIsSend.IsChecked = chkWaitReceiveBuyerIsNotSend.IsChecked = chkWaitReceiveBuyerIsInWarehouse.IsChecked = false;
+ chk.IsChecked = !isCheck;
+ }
+ FilterOrders();
+ }
+
+ private void chkWaitReceiveWarehouseStatus_Click(object sender, RoutedEventArgs e)
+ {
+ if (sender is CheckBox chk)
+ {
+ var isCheck = !chk.IsChecked.ParseToBool();
+ chkWaitReceiveWarehouseIsNotPickup.IsChecked = chkWaitReceiveWarehouseIsPickup.IsChecked = chkWaitReceiveWarehouseIsSendOut.IsChecked = false;
+ chk.IsChecked = !isCheck;
+ }
+ FilterOrders();
+ }
+
+ private void chkAftersaleSendStatus_Click(object sender, RoutedEventArgs e)
+ {
+ if (sender is CheckBox chk)
+ {
+ var isCheck = !chk.IsChecked.ParseToBool();
+ chkAftersaleIsSend.IsChecked = chkAftersaleIsNotSend.IsChecked = false;
+ chk.IsChecked = !isCheck;
+ }
+ FilterOrders();
+ }
+
+ private void chkAftersaleBuyerStatus_Click(object sender, RoutedEventArgs e)
+ {
+ if (sender is CheckBox chk)
+ {
+ var isCheck = !chk.IsChecked.ParseToBool();
+ chkAftersaleBuyerIsBuy.IsChecked = false;
+ chk.IsChecked = !isCheck;
+ }
+ FilterOrders();
+ }
+
+ private void chkAftersaleWarehouseStatus_Click(object sender, RoutedEventArgs e)
+ {
+ if (sender is CheckBox chk)
+ {
+ var isCheck = !chk.IsChecked.ParseToBool();
+ chkAftersaleWarehouseIsPickup.IsChecked = chkAftersaleWarehouseIsNotPickup.IsChecked = false;
+ chk.IsChecked = !isCheck;
+ }
+ FilterOrders();
+ }
+
+ private async void btnBatchRefund_Click(object sender, RoutedEventArgs e)
+ {
+ var orders = GlobalConfig.lstFilterOrder.Where(o => o.IsSelect == true);
+ List tmpOrderItems = new List();
+ foreach (var order in orders)
+ {
+ foreach (var orderItem in order.orderItems)
+ {
+ if (orderItem.ItemOrder?.OrderBuyType == "云仓")
+ if (orderItem != null && !string.IsNullOrEmpty(orderItem.ItemTransitOrderWithVoid?.out_order_no) && orderItem.PddBuyerAfterSaleAddressStr.IsNullOrEmpty() &&
+ (orderItem.TransitRefundStatusStr.Contains("需手动申请售后") || orderItem.TransitRefundStatusStr.Contains("待用户发货")))
+ tmpOrderItems.Add(orderItem);
+
+ if (orderItem.ItemOrder?.OrderBuyType == "直发" || orderItem.ItemOrder?.OrderBuyType == "云改直")
+ if (orderItem != null && !string.IsNullOrEmpty(orderItem.ItemOrder?.out_order_no) && orderItem.PddBuyerAfterSaleAddressStr.IsNullOrEmpty() &&
+ ((orderItem.ItemOrder?.out_after_sale_status).ParseToString().Contains("需手动申请售后") || (orderItem.ItemOrder?.out_after_sale_status).ParseToString().Contains("待用户发货")))
+ tmpOrderItems.Add(orderItem);
+ }
+ }
+ if (tmpOrderItems.Count == 0)
+ {
+ BaseMsgWindow.ShowAnimateMessage("未选中需要需手动申请售后的订单", "Error", 3);
+ return;
+ }
+
+ await Task.Run(() =>
+ {
+ int index = 0;
+ foreach (var tmpOrderItem in tmpOrderItems)
+ {
+ Dispatcher.Invoke(new Action(() => { txtMsg.Text = "正在处理买手退货,总计:" + tmpOrderItems.Count + ",已处理:" + index++; }));
+
+ var pddOrderSn = "";
+ if (tmpOrderItem.ItemOrder?.OrderBuyType == "云仓")
+ pddOrderSn = tmpOrderItem.ItemTransitOrderWithVoid?.out_order_no;
+ else if (tmpOrderItem.ItemOrder?.OrderBuyType == "直发" || tmpOrderItem.ItemOrder?.OrderBuyType == "云改直")
+ pddOrderSn = tmpOrderItem.ItemOrder?.out_order_no;
+
+ BuyerLoginInfo buyer = null;
+ if (tmpOrderItem.ItemOrder?.OrderBuyType == "云仓")
+ Dispatcher.Invoke(new Action(() => { buyer = GlobalConfig.PDDBuyerLoginList.FirstOrDefault(b => b.buyer_nick == tmpOrderItem.ItemTransitOrderWithVoid.buyer_account); }));
+ else if (tmpOrderItem.ItemOrder?.OrderBuyType == "直发" || tmpOrderItem.ItemOrder?.OrderBuyType == "云改直")
+ Dispatcher.Invoke(new Action(() => { buyer = GlobalConfig.PDDBuyerLoginList.FirstOrDefault(b => b.buyer_nick == tmpOrderItem.ItemOrder?.out_account); }));
+ if (buyer == null)
+ {
+ BaseMsgWindow.ShowAnimateMessage("买手单:" + pddOrderSn + " 买手不在当前账户下,跳过", "Error", 3);
+ }
+
+ // 检测一下买手号
+ if (buyer.status == "在线")
+ {
+ PddMobileLoginForm.CheckBuyerLogin(buyer);
+ }
+ if (buyer.status != "在线")
+ {
+ BaseMsgWindow.ShowAnimateMessage("买手单:" + pddOrderSn + " 买手号掉线,跳过", "Error", 3);
+ continue;
+ }
+
+ MainWindow.Instance.orderListCtrl.GetOrder(tmpOrderItem.order_id);
+
+ oms_wei_order_info order = null;
+ Dispatcher.Invoke(new Action(() => { order = GlobalConfig.lstOrder.FirstOrDefault(oi => oi.order_id == tmpOrderItem.order_id); }));
+ if (order == null)
+ continue;
+ oms_wei_order_item_info orderItem = null;
+ Dispatcher.Invoke(new Action(() => { orderItem = order.orderItems.FirstOrDefault(oi => oi.order_id == tmpOrderItem.order_id && oi.sku_id == tmpOrderItem.sku_id); }));
+ if (orderItem == null)
+ continue;
+
+ string refundStatusStr = "";
+ string outOrderNo = "";
+ if (order.OrderBuyType == "云仓")
+ {
+ outOrderNo = (orderItem.ItemTransitOrderWithVoid?.out_order_no).ParseToString();
+ refundStatusStr = (orderItem?.TransitRefundStatusStr).ParseToString();
+ }
+ else if (order.OrderBuyType == "直发" || order.OrderBuyType == "云改直")
+ {
+ outOrderNo = (order.out_order_no).ParseToString();
+ refundStatusStr = (order.out_after_sale_status).ParseToString();
+ }
+ if (orderItem == null || string.IsNullOrEmpty(outOrderNo) || !orderItem.PddBuyerAfterSaleAddressStr.IsNullOrEmpty() ||
+ (!refundStatusStr.Contains("需手动申请售后") && !refundStatusStr.Contains("待用户发货")))
+ continue;
+
+ PddBuyerOrderLiteInfo pddBuyerOrderLiteInfo = new PddBuyerOrderLiteInfo();
+ pddBuyerOrderLiteInfo.ShopOrderIdStr = orderItem.order_id;
+ pddBuyerOrderLiteInfo.order_sn = pddOrderSn;
+
+ if (order.OrderBuyType == "云仓")
+ pddBuyerOrderLiteInfo.order_amount = orderItem.ItemTransitOrderWithVoid?.out_amount;
+ else if (order.OrderBuyType == "直发" || order.OrderBuyType == "云改直")
+ pddBuyerOrderLiteInfo.order_amount = order.out_amount;
+
+ order_pdd_buyer_after_sale pddBuyerAfterSale = new order_pdd_buyer_after_sale()
+ {
+ wx_order_id = orderItem.order_id,
+ wx_sku_id = orderItem.sku_id,
+ TransitCreateTime = orderItem.ItemTransitOrderWithVoid?.created_time == null ? DateTime.MinValue : orderItem.ItemTransitOrderWithVoid.created_time,
+ pre_allocated_order_no = orderItem.ItemTransitOrderWithVoid?.pre_allocated_order_no,
+ buyerId = buyer.buyer_id,
+ buyerName = buyer.buyer_name,
+ orderSn = pddOrderSn,
+ orderAmount = pddBuyerOrderLiteInfo.order_amount,
+ refundAmount = pddBuyerOrderLiteInfo.order_amount,
+ orderDate = pddOrderSn.ParseToString().Split('-').FirstOrDefault().ParseToInt(),
+ };
+ if (orderItem.PddBuyerAfterSale != null)
+ pddBuyerAfterSale = orderItem.PddBuyerAfterSale;
+
+ bool isSimPddAfterSaleSuccess = true;
+ if (refundStatusStr.Contains("需手动申请售后"))
+ {
+ isSimPddAfterSaleSuccess = false;
+ // pddBuyerAfterSale作为参数传入,获取退货退款金额
+ var rst = PDDBuyerOrderReadCtrl.SimPddAfterSaleWithReturnGoods(buyer, pddBuyerOrderLiteInfo, pddBuyerAfterSale);
+
+ var afterSalesStatus = BaseRegex.GetIntJson(ref rst, "after_sales_status");
+ var afterSalesId = BaseRegex.GetLongJson(ref rst, "after_sales_id");
+ pddBuyerAfterSale.afterSalesId = afterSalesId.ToString();
+ pddBuyerAfterSale.statusText = "待用户发货";
+
+ if (afterSalesStatus == 0)
+ {
+ var msg = BaseRegex.GetStringJsonByRegs(ref rst, rst, "msg", "err_msg", "error_msg", "errorMsg", "errMsg");
+ BaseMsgWindow.ShowAnimateMessage(msg, "Error", 3);
+ Thread.Sleep(5000);
+ }
+ else
+ {
+ if (order.OrderBuyType == "云仓")
+ {
+ var e57Rst = PDDBuyerOrderReadCtrl.SendTransitAfterSaleE57(pddBuyerOrderLiteInfo, "待用户发货");
+ if (e57Rst.Contains("0") || e57Rst.Contains("200"))
+ {
+ BaseMsgWindow.ShowAnimateMessage("买手退款信息更新成功", "Msg", 3);
+ isSimPddAfterSaleSuccess = true;
+ Thread.Sleep(Randomx.GetId(10000, 12001));
+ }
+ else
+ {
+ var msg = BaseRegex.GetStringXml(ref e57Rst, "msg");
+ BaseMsgWindow.ShowAnimateMessage("买手退款信息更新失败,服务端返回 " + msg, "Error", 3);
+ }
+ }
+ else if (order.OrderBuyType == "直发" || order.OrderBuyType == "云改直")
+ {
+ var e57Rst = PDDBuyerOrderReadCtrl.SendAfterSaleE57NeedManual(pddBuyerOrderLiteInfo, "待用户发货");
+ if (e57Rst.Contains("0") || e57Rst.Contains("200"))
+ {
+ BaseMsgWindow.ShowAnimateMessage("买手退款信息更新成功", "Msg", 3);
+ isSimPddAfterSaleSuccess = true;
+ Thread.Sleep(Randomx.GetId(10000, 12001));
+ }
+ else
+ {
+ var msg = BaseRegex.GetStringXml(ref e57Rst, "msg");
+ BaseMsgWindow.ShowAnimateMessage("买手退款信息更新失败,服务端返回 " + msg, "Error", 3);
+ }
+ }
+ }
+ }
+ if (isSimPddAfterSaleSuccess)
+ {
+ var addressRst = YkdBuyerOrder.GetAfterSaleAddress(buyer, pddOrderSn, pddBuyerAfterSale.afterSalesId.ParseToString());
+ var merchantReceiverInfo = BaseRegex.GetOneJsonObjStrJson(ref addressRst, "merchantReceiverInfo");
+ string address = "";
+ if (merchantReceiverInfo != null)
+ {
+ address = BaseRegex.GetStringJson(ref merchantReceiverInfo, "copyValue");
+ }
+
+ var url3 = BaseClass.Build29WxObjString("order/wx_add_mdy_buyer_after_sale");
+ var data3 = UserLogin.GetSignaturex();
+ data3 += "&wx_order_id=" + pddBuyerAfterSale.wx_order_id;
+ data3 += "&wx_sku_id=" + pddBuyerAfterSale.wx_sku_id;
+ if (pddBuyerAfterSale.TransitCreateTime != DateTime.MinValue)
+ data3 += "&TransitCreateTime=" + pddBuyerAfterSale.TransitCreateTime.ToString("yyyy-MM-dd HH:mm:ss");
+ data3 += "&pre_allocated_order_no=" + pddBuyerAfterSale.pre_allocated_order_no;
+ data3 += "&buyerId=" + pddBuyerAfterSale.buyerId;
+ data3 += "&buyerName=" + pddBuyerAfterSale.buyerName;
+ data3 += "&orderAmount=" + pddBuyerAfterSale.orderAmount;
+ data3 += "&orderSn=" + pddBuyerAfterSale.orderSn;
+ data3 += "&afterSalesId=" + pddBuyerAfterSale.afterSalesId;
+ data3 += "&orderDate=" + pddBuyerAfterSale.orderDate;
+ //data3 += "&TransitPickupTime=" + pddBuyerOrder.TransitPickupTime.ToString("yyyy-MM-dd HH:mm:ss");
+ data3 += "&refundAmount=" + pddBuyerAfterSale.refundAmount;
+ data3 += "&statusText=" + pddBuyerAfterSale.statusText;
+ if (!string.IsNullOrEmpty(address))
+ data3 += "&afterSaleAddress=" + address;
+ if (order.OrderBuyType == "直发" || order.OrderBuyType == "云改直") // 云仓 0 直发 1
+ data3 += "&wx_send_type=1";
+ //data3 += "&is_mdy=true";
+ var html3 = GetHtml.PostUtf8(url3, data3);
+ if (string.IsNullOrEmpty(html3) || !html3.Contains("\"code\":200"))
+ html3 = GetHtml.PostUtf8(url3, data3);
+ }
+ MainWindow.Instance.orderListCtrl.GetOrder(tmpOrderItem.order_id);
+ Dispatcher.Invoke(new Action(() => { txtMsg.Text = "正在处理买手退货,总计:" + tmpOrderItems.Count + ",已处理:" + index; }));
+ }
+
+ Dispatcher.Invoke(new Action(() => { txtMsg.Text = "买手退货处理完成,总计:" + tmpOrderItems.Count + ",已处理:" + index; }));
+ });
+ }
+
+
+ public static string WxSimAbnormalOrderSeach(ShopLoginInfo shop, int page = 1)
+ {
+ string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeorder/list/cgi/orderSearch?token=&lang=zh_CN";
+ string referer = "https://store.weixin.qq.com/shop/order/list";
+ string body = @"{""isSearch"":false,""pageSize"":100,""overTime"":0,""pengingShipOneDay"":0,""pengingShipSixHour"":0,""expediteDelivery"":0," +
+ @"""stockoutPunishAlert"":0,""appointmentInstall"":0,""waybillStatus"":3,""isUserBookingDelivery"":0,""pageNum"":" + page + @",""onAftersaleOrderExist"":0,""orderStatus"":30}";
+ var result = HttpResponseWXBLL.WeiXinPostResponse(shop, url, body, referer);
+ return result;
+ }
+
+ private void btnMultiRemark_Click(object sender, RoutedEventArgs e)
+ {
+ wpFilterRemarkSelect.Children.Clear();
+ List txts = txtFilterRemark.Text.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries).ToList();
+ var remarks = GlobalConfig.lstOrder.Select(o => o.shop_remark).Distinct().ToList();
+ remarks.AddRange(GlobalConfig.lstOrder.Select(o => o.soft_remark).Distinct().ToList());
+ remarks = remarks.Distinct().ToList();
+ foreach (var remark in remarks)
+ {
+ if (string.IsNullOrWhiteSpace(remark))
+ continue;
+ wpFilterRemarkSelect.Children.Add(new CheckBox() { Content = remark, IsChecked = txts.Contains(remark), Margin = new Thickness(2) });
+ }
+
+ Point position = txtFilterRemark.TranslatePoint(new Point(0, 0), gridOrderListCtrl);
+ borderFilterRemarkSelect.Margin = new Thickness(position.X - 2, position.Y + txtFilterRemark.ActualHeight + 3, 0, 0);
+
+ if (borderFilterRemarkSelect.Visibility == Visibility.Visible)
+ borderFilterRemarkSelect.Visibility = Visibility.Collapsed;
+ else
+ borderFilterRemarkSelect.Visibility = Visibility.Visible;
+ }
+
+ private void btnCancelFilterRemark_Click(object sender, RoutedEventArgs e)
+ {
+ borderFilterRemarkSelect.Visibility = Visibility.Collapsed;
+ }
+
+ private void btnApplyFilterRemark_Click(object sender, RoutedEventArgs e)
+ {
+ string txt = "";
+ foreach (UIElement element in wpFilterRemarkSelect.Children)
+ {
+ if (element is CheckBox box && box.IsChecked == true)
+ {
+ txt += box.Content.ParseToString() + ";";
+ }
+ }
+ txtFilterRemark.Text = txt.TrimEnd(';');
+ borderFilterRemarkSelect.Visibility = Visibility.Collapsed;
+ }
+
+ private void btnFilterRemarkSelectAll_Click(object sender, RoutedEventArgs e)
+ {
+ foreach (UIElement element in wpFilterRemarkSelect.Children)
+ {
+ if (element is CheckBox box)
+ {
+ box.IsChecked = true;
+ }
+ }
+ }
+
+ private void btnFilterRemarkUnSelectAll_Click(object sender, RoutedEventArgs e)
+ {
+ foreach (UIElement element in wpFilterRemarkSelect.Children)
+ {
+ if (element is CheckBox box)
+ {
+ box.IsChecked = false;
+ }
+ }
+ }
+
+ private void txtFilterRemark_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ lstFilterText = txtFilterRemark.Text.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList();
+ }
+
+ private void chkEmergencyReturnOrRefund_Click(object sender, RoutedEventArgs e)
+ {
+ if (sender is CheckBox chk)
+ {
+ var isCheck = !chk.IsChecked.ParseToBool();
+ chkEmergencyReturn.IsChecked = chkEmergencyRefund.IsChecked = false;
+ chk.IsChecked = !isCheck;
+ }
+ FilterOrders();
+ }
+
+ private void btn_ShowShopRevenueStatisticsView(object sender, RoutedEventArgs e)
+ {
+ new DialogWindow()
+ {
+ Title = "统计",
+ Content = new ShopRevenueStatisticsView(),
+
+ }.ShowDialog();
+
+ }
+ }
}
diff --git a/29WxOrderWpf/Ctrls/Statistics/Charts/Chart.xaml b/29WxOrderWpf/Ctrls/Statistics/Charts/Chart.xaml
new file mode 100644
index 0000000..dd17c18
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/Charts/Chart.xaml
@@ -0,0 +1,17 @@
+
+
+
\ No newline at end of file
diff --git a/29WxOrderWpf/Ctrls/Statistics/Charts/RevenueLineChart.xaml b/29WxOrderWpf/Ctrls/Statistics/Charts/RevenueLineChart.xaml
new file mode 100644
index 0000000..b4d7f4b
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/Charts/RevenueLineChart.xaml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/29WxOrderWpf/Ctrls/Statistics/Charts/RevenueLineChart.xaml.cs b/29WxOrderWpf/Ctrls/Statistics/Charts/RevenueLineChart.xaml.cs
new file mode 100644
index 0000000..a5b7a0b
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/Charts/RevenueLineChart.xaml.cs
@@ -0,0 +1,242 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Shapes;
+using _29WxOrderWpf.Ctrls.Statistics.Models;
+
+namespace _29WxOrderWpf.Ctrls.Statistics.Charts
+{
+ ///
+ /// 销售趋势折线图(轻量自绘,无第三方依赖)。
+ /// 绑定 (IList<RevenueTrendPoint>)即可,数据变化时自动重绘。
+ /// 鼠标悬停在数据点圆圈上时显示该点数据(日期 / 销售额 / 订单数)。
+ ///
+ public partial class RevenueLineChart : UserControl
+ {
+ public static readonly DependencyProperty PointsProperty =
+ DependencyProperty.Register("Points", typeof(IList), typeof(RevenueLineChart),
+ new PropertyMetadata(null, OnRenderPropertyChanged));
+
+ /// 趋势数据点
+ public IList Points
+ {
+ get { return (IList)GetValue(PointsProperty); }
+ set { SetValue(PointsProperty, value); }
+ }
+
+ public static readonly DependencyProperty LineBrushProperty =
+ DependencyProperty.Register("LineBrush", typeof(Brush), typeof(RevenueLineChart),
+ new PropertyMetadata(new SolidColorBrush(Color.FromRgb(22, 119, 255)), OnRenderPropertyChanged));
+
+ /// 折线颜色
+ public Brush LineBrush
+ {
+ get { return (Brush)GetValue(LineBrushProperty); }
+ set { SetValue(LineBrushProperty, value); }
+ }
+
+ public static readonly DependencyProperty LineThicknessProperty =
+ DependencyProperty.Register("LineThickness", typeof(double), typeof(RevenueLineChart),
+ new PropertyMetadata(2d, OnRenderPropertyChanged));
+
+ /// 折线粗细
+ public double LineThickness
+ {
+ get { return (double)GetValue(LineThicknessProperty); }
+ set { SetValue(LineThicknessProperty, value); }
+ }
+
+ public RevenueLineChart()
+ {
+ InitializeComponent();
+ Loaded += delegate { Render(); };
+ SizeChanged += delegate { Render(); };
+ }
+
+ private static void OnRenderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ ((RevenueLineChart)d).Render();
+ }
+
+ private void Render()
+ {
+ LayoutRoot.Children.Clear();
+ var points = Points;
+ if (points == null || points.Count == 0 || ActualWidth <= 20 || ActualHeight <= 20)
+ return;
+
+ const double marginLeft = 52;
+ const double marginRight = 16;
+ const double marginTop = 18;
+ const double marginBottom = 30;
+
+ double plotWidth = Math.Max(10, ActualWidth - marginLeft - marginRight);
+ double plotHeight = Math.Max(10, ActualHeight - marginTop - marginBottom);
+
+ var values = points.Select(p => (double)p.SalesAmount).ToList();
+ double maxValue = values.Max();
+ if (maxValue <= 0) maxValue = 1;
+ double yMax = maxValue * 1.15;
+
+ var lineBrush = LineBrush ?? new SolidColorBrush(Color.FromRgb(22, 119, 255));
+ Color lineColor = lineBrush is SolidColorBrush ? ((SolidColorBrush)lineBrush).Color : Color.FromRgb(22, 119, 255);
+
+ int count = points.Count;
+ double stepX = count <= 1 ? 0 : plotWidth / (count - 1);
+
+ Func getX = i => marginLeft + stepX * i;
+ Func getY = v => marginTop + plotHeight * (1 - v / yMax);
+
+ // 1. 横向网格线 + Y 轴刻度
+ for (int k = 0; k <= 4; k++)
+ {
+ double ratio = k / 4.0;
+ double y = marginTop + plotHeight * ratio;
+ double v = yMax * (1 - ratio);
+
+ LayoutRoot.Children.Add(new Line
+ {
+ X1 = marginLeft, Y1 = y, X2 = marginLeft + plotWidth, Y2 = y,
+ Stroke = new SolidColorBrush(Color.FromRgb(238, 238, 238)),
+ StrokeThickness = 1
+ });
+
+ var yLabel = new TextBlock
+ {
+ Text = FormatValue(v),
+ FontSize = 11,
+ Foreground = new SolidColorBrush(Color.FromRgb(153, 153, 153)),
+ Width = marginLeft - 6,
+ TextAlignment = TextAlignment.Right
+ };
+ LayoutRoot.Children.Add(yLabel);
+ Canvas.SetLeft(yLabel, 0);
+ Canvas.SetTop(yLabel, y - 8);
+ }
+
+ // 2. 面积填充
+ if (count > 1)
+ {
+ var figure = new PathFigure { StartPoint = new Point(getX(0), getY(values[0])) };
+ for (int i = 1; i < count; i++)
+ figure.Segments.Add(new LineSegment { Point = new Point(getX(i), getY(values[i])) });
+ figure.Segments.Add(new LineSegment { Point = new Point(getX(count - 1), marginTop + plotHeight) });
+ figure.Segments.Add(new LineSegment { Point = new Point(getX(0), marginTop + plotHeight) });
+ figure.IsClosed = true;
+
+ var gradient = new LinearGradientBrush
+ {
+ StartPoint = new Point(0, 0),
+ EndPoint = new Point(0, 1)
+ };
+ gradient.GradientStops.Add(new GradientStop(Color.FromArgb(64, lineColor.R, lineColor.G, lineColor.B), 0));
+ gradient.GradientStops.Add(new GradientStop(Color.FromArgb(8, lineColor.R, lineColor.G, lineColor.B), 1));
+
+ LayoutRoot.Children.Add(new Path
+ {
+ Data = new PathGeometry { Figures = { figure } },
+ Fill = gradient
+ });
+ }
+
+ // 3. 折线
+ var polylinePoints = new PointCollection();
+ for (int i = 0; i < count; i++)
+ polylinePoints.Add(new Point(getX(i), getY(values[i])));
+
+ LayoutRoot.Children.Add(new Polyline
+ {
+ Points = polylinePoints,
+ Stroke = lineBrush,
+ StrokeThickness = LineThickness,
+ StrokeLineJoin = PenLineJoin.Round
+ });
+
+ // 4. 数据点(点较多时省略;悬停显示该点数据)
+ if (count <= 31)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ var dot = new Ellipse
+ {
+ ToolTip = CreateTooltip(points[i])
+ };
+ dot. Style = (Style)FindResource("LineEllipse");
+ //// 悬停时高亮圆点
+ //dot.MouseEnter += (s, e) => dot.Fill = lineBrush;
+ //dot.MouseLeave += (s, e) => dot.Fill = Brushes.White;
+
+ LayoutRoot.Children.Add(dot);
+ Canvas.SetLeft(dot, getX(i) - 3.5);
+ Canvas.SetTop(dot, getY(values[i]) - 3.5);
+ }
+ }
+
+ // 5. X 轴日期刻度(最多显示 8 个)
+ int labelStep = Math.Max(1, (int)Math.Ceiling(count / 8.0));
+ for (int i = 0; i < count; i += labelStep)
+ {
+ var tb = new TextBlock
+ {
+ Text = points[i].DateText,
+ FontSize = 11,
+ Foreground = new SolidColorBrush(Color.FromRgb(153, 153, 153)),
+ TextAlignment = TextAlignment.Center,
+ Width = 60
+ };
+ LayoutRoot.Children.Add(tb);
+ double x = getX(i) - 30;
+ x = Math.Max(0, Math.Min(ActualWidth - 60, x));
+ Canvas.SetLeft(tb, x);
+ Canvas.SetTop(tb, marginTop + plotHeight + 6);
+ }
+ }
+
+ /// 生成数据点悬浮提示(日期 / 销售额 / 订单数)
+ private static object CreateTooltip(RevenueTrendPoint p)
+ {
+ var panel = new StackPanel();
+ var txtBrush = new SolidColorBrush(Color.FromRgb(51, 51, 51));
+ panel.Children.Add(new TextBlock
+ {
+ Text = p.Date.ToString("yyyy-MM-dd"),
+ FontSize = 11,
+ FontWeight = FontWeights.SemiBold,
+ Foreground = txtBrush
+ });
+ panel.Children.Add(new TextBlock
+ {
+ Text = "销售额:" + FormatValue((double)p.SalesAmount) + "元",
+ FontSize = 11,
+ Foreground = txtBrush
+ });
+ panel.Children.Add(new TextBlock
+ {
+ Text = "订单数:" + p.OrderCount + " 单",
+ FontSize = 11,
+ Foreground = txtBrush
+ });
+
+ return new Border
+ {
+ Background = Brushes.White,
+ CornerRadius = new CornerRadius(4),
+ Padding = new Thickness(8, 5, 8, 5),
+ Child = panel
+ };
+ }
+
+ private static string FormatValue(double value)
+ {
+ double abs = Math.Abs(value);
+ if (abs >= 100000000)
+ return (value / 100000000d).ToString("0.#") + "亿";
+ if (abs >= 10000)
+ return (value / 10000d).ToString("0.#") + "万";
+ return value.ToString("#,##0");
+ }
+ }
+}
\ No newline at end of file
diff --git a/29WxOrderWpf/Ctrls/Statistics/Charts/RevenuePieChart.xaml b/29WxOrderWpf/Ctrls/Statistics/Charts/RevenuePieChart.xaml
new file mode 100644
index 0000000..53d6213
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/Charts/RevenuePieChart.xaml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/29WxOrderWpf/Ctrls/Statistics/Charts/RevenuePieChart.xaml.cs b/29WxOrderWpf/Ctrls/Statistics/Charts/RevenuePieChart.xaml.cs
new file mode 100644
index 0000000..91f61b7
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/Charts/RevenuePieChart.xaml.cs
@@ -0,0 +1,425 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Shapes;
+using _29WxOrderWpf.Ctrls.Statistics.Models;
+
+namespace _29WxOrderWpf.Ctrls.Statistics.Charts
+{
+ ///
+ /// 店铺销售占比饼图(轻量自绘,无第三方依赖)。
+ /// 绑定 (IList<ShopSalesProportionItem>)即可,数据变化时自动重绘。
+ /// 设置 (>0)可只显示前 N 项,其余项合并为一个“”扇区(百分比为剩余总和,整体仍为 100%)。
+ /// 设置 可在环形图中央留白处显示标题( 可切换为顶部),不会遮挡扇形;
+ /// 图例通过 可放置到 4 个角,饼图区域由独立 panel 包裹,方便整体挪动和调整大小。
+ ///
+ public partial class RevenuePieChart : UserControl
+ {
+ /// 标题显示位置
+ public enum PieTitlePlacement
+ {
+ /// 居中显示在环形图中央留白处(默认,不遮挡扇形)
+ Center,
+
+ /// 显示在图表顶部
+ Top
+ }
+
+ /// 图例显示位置(4 个角)
+ public enum PieLegendPosition
+ {
+ /// 左上角
+ TopLeft,
+
+ /// 右上角(默认)
+ TopRight,
+
+ /// 左下角
+ BottomLeft,
+
+ /// 右下角
+ BottomRight
+ }
+
+ /// 待绘制扇区(含颜色)
+ private sealed class DisplaySlice
+ {
+ public ShopSalesProportionItem Item;
+ public Brush Brush;
+ }
+
+ /// ECharts 默认配色
+ private static readonly Color[] Palette =
+ {
+ Color.FromRgb(84, 112, 198),
+ Color.FromRgb(145, 204, 117),
+ Color.FromRgb(250, 200, 88),
+ Color.FromRgb(238, 102, 102),
+ Color.FromRgb(115, 192, 222),
+ Color.FromRgb(59, 162, 114),
+ Color.FromRgb(252, 132, 82),
+ Color.FromRgb(154, 96, 180),
+ Color.FromRgb(234, 124, 204)
+ };
+
+ /// “其他”合并项默认颜色(灰色)
+ private static readonly Color OtherColor = Color.FromRgb(192, 196, 204);
+
+ public static readonly DependencyProperty ItemsSourceProperty =
+ DependencyProperty.Register("ItemsSource", typeof(IList), typeof(RevenuePieChart),
+ new PropertyMetadata(null, OnRenderPropertyChanged));
+
+ /// 占比数据
+ public IList ItemsSource
+ {
+ get { return (IList)GetValue(ItemsSourceProperty); }
+ set { SetValue(ItemsSourceProperty, value); }
+ }
+
+ public static readonly DependencyProperty MaxItemsProperty =
+ DependencyProperty.Register("MaxItems", typeof(int), typeof(RevenuePieChart),
+ new PropertyMetadata(0, OnRenderPropertyChanged));
+
+ /// 最多显示的独立扇区数(>0 时其余项合并为“其他”;<=0 显示全部)
+ public int MaxItems
+ {
+ get { return (int)GetValue(MaxItemsProperty); }
+ set { SetValue(MaxItemsProperty, value); }
+ }
+
+ public static readonly DependencyProperty OtherLabelProperty =
+ DependencyProperty.Register("OtherLabel", typeof(string), typeof(RevenuePieChart),
+ new PropertyMetadata("其他", OnRenderPropertyChanged));
+
+ /// 合并项的显示名称(默认“其他”)
+ public string OtherLabel
+ {
+ get { return (string)GetValue(OtherLabelProperty); }
+ set { SetValue(OtherLabelProperty, value); }
+ }
+
+ public static readonly DependencyProperty OtherBrushProperty =
+ DependencyProperty.Register("OtherBrush", typeof(Brush), typeof(RevenuePieChart),
+ new PropertyMetadata(new SolidColorBrush(OtherColor), OnRenderPropertyChanged));
+
+ /// 合并项的颜色(默认灰色)
+ public Brush OtherBrush
+ {
+ get { return (Brush)GetValue(OtherBrushProperty); }
+ set { SetValue(OtherBrushProperty, value); }
+ }
+
+ public static readonly DependencyProperty TitleProperty =
+ DependencyProperty.Register("Title", typeof(string), typeof(RevenuePieChart),
+ new PropertyMetadata(null, OnRenderPropertyChanged));
+
+ /// 标题文本(空/Null 不显示)
+ public string Title
+ {
+ get { return (string)GetValue(TitleProperty); }
+ set { SetValue(TitleProperty, value); }
+ }
+
+ public static readonly DependencyProperty TitlePlacementProperty =
+ DependencyProperty.Register("TitlePlacement", typeof(PieTitlePlacement), typeof(RevenuePieChart),
+ new PropertyMetadata(PieTitlePlacement.Center, OnRenderPropertyChanged));
+
+ /// 标题显示位置(默认居中显示在环形图留白处,不遮挡扇形)
+ public PieTitlePlacement TitlePlacement
+ {
+ get { return (PieTitlePlacement)GetValue(TitlePlacementProperty); }
+ set { SetValue(TitlePlacementProperty, value); }
+ }
+
+ public static readonly DependencyProperty TitleFontSizeProperty =
+ DependencyProperty.Register("TitleFontSize", typeof(double), typeof(RevenuePieChart),
+ new PropertyMetadata(14d, OnRenderPropertyChanged));
+
+ /// 标题字号
+ public double TitleFontSize
+ {
+ get { return (double)GetValue(TitleFontSizeProperty); }
+ set { SetValue(TitleFontSizeProperty, value); }
+ }
+
+ public static readonly DependencyProperty TitleBrushProperty =
+ DependencyProperty.Register("TitleBrush", typeof(Brush), typeof(RevenuePieChart),
+ new PropertyMetadata(new SolidColorBrush(Color.FromRgb(51, 51, 51)), OnRenderPropertyChanged));
+
+ /// 标题颜色
+ public Brush TitleBrush
+ {
+ get { return (Brush)GetValue(TitleBrushProperty); }
+ set { SetValue(TitleBrushProperty, value); }
+ }
+
+ public static readonly DependencyProperty LegendPositionProperty =
+ DependencyProperty.Register("LegendPosition", typeof(PieLegendPosition), typeof(RevenuePieChart),
+ new PropertyMetadata(PieLegendPosition.TopRight, OnRenderPropertyChanged));
+
+ /// 图例显示位置(默认右上角,与饼图分列放置,不遮挡)
+ public PieLegendPosition LegendPosition
+ {
+ get { return (PieLegendPosition)GetValue(LegendPositionProperty); }
+ set { SetValue(LegendPositionProperty, value); }
+ }
+
+ public RevenuePieChart()
+ {
+ InitializeComponent();
+ Loaded += delegate { Render(); };
+ SizeChanged += delegate { Render(); };
+ }
+
+ private static void OnRenderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ ((RevenuePieChart)d).Render();
+ }
+
+ private void Render()
+ {
+ LayoutRoot.Children.Clear();
+ var items = ItemsSource;
+ if (items == null || items.Count == 0 || ActualWidth <= 20 || ActualHeight <= 20)
+ return;
+
+ double width = ActualWidth;
+ double height = ActualHeight;
+
+ // 图例列宽:图例占左/右一列,饼图占另一列,天然不会互相遮挡
+ double legendWidth = Math.Min(210, width * 0.38);
+ bool legendOnLeft = LegendPosition == PieLegendPosition.TopLeft
+ || LegendPosition == PieLegendPosition.BottomLeft;
+
+ double pieLeft = legendOnLeft ? legendWidth : 0;
+ double pieWidth = Math.Max(10, width - legendWidth);
+ double pieHeight = height;
+
+ // 顶部标题:先预留高度,饼图相应下移,避免遮挡
+ double topTitleHeight = 0;
+ if (TitlePlacement == PieTitlePlacement.Top && !string.IsNullOrEmpty(Title))
+ {
+ var probe = CreateTitleBlock(pieWidth);
+ probe.Measure(new Size(pieWidth, double.PositiveInfinity));
+ topTitleHeight = Math.Ceiling(probe.DesiredSize.Height) + 8;
+ }
+
+ // 饼图区域用独立 Canvas 包裹,方便整体挪动(SetLeft/SetTop)和修改大小(Width/Height)
+ var piePanel = new Canvas { Width = pieWidth, Height = pieHeight };
+ LayoutRoot.Children.Add(piePanel);
+ Canvas.SetLeft(piePanel, pieLeft);
+ Canvas.SetTop(piePanel, 0);
+
+ double cx = pieWidth / 2;
+ double cy = (topTitleHeight + pieHeight) / 2;
+ double radius = Math.Max(10, Math.Min(pieWidth, pieHeight - topTitleHeight) / 2 - 18);
+
+ // 0. 生成实际绘制的扇区列表(MaxItems > 0 时其余项合并为“其他”)
+ var slices = BuildSlices(items);
+
+ // 1. 绘制扇形
+ double startAngle = -90; // 从正上方开始,顺时针
+ foreach (var slice in slices)
+ {
+ double sweep = slice.Item.Percentage / 100d * 360d;
+ if (sweep < 0) sweep = 0;
+ var brush = slice.Brush;
+
+ if (sweep >= 359.9)
+ {
+ var circle = new Ellipse
+ {
+ Width = radius * 2,
+ Height = radius * 2,
+ Fill = brush
+ };
+ piePanel.Children.Add(circle);
+ Canvas.SetLeft(circle, cx - radius);
+ Canvas.SetTop(circle, cy - radius);
+ }
+ else if (sweep > 0.01)
+ {
+ piePanel.Children.Add(CreateSlice(cx, cy, radius, startAngle, sweep, brush));
+ }
+ startAngle += sweep;
+ }
+
+ // 2. 中间留白圆心
+ double holeRadius = radius * 0.55;
+ var hole = new Ellipse
+ {
+ Width = holeRadius * 2,
+ Height = holeRadius * 2,
+ Fill = Brushes.White
+ };
+ piePanel.Children.Add(hole);
+ Canvas.SetLeft(hole, cx - holeRadius);
+ Canvas.SetTop(hole, cy - holeRadius);
+
+ // 3. 标题(居中显示在环形图留白处,宽度限制在留白直径内,不遮挡扇形)
+ if (!string.IsNullOrEmpty(Title))
+ {
+ double maxW = TitlePlacement == PieTitlePlacement.Center
+ ? Math.Max(20, holeRadius * 2 - 8)
+ : pieWidth;
+ var titleBlock = CreateTitleBlock(maxW);
+ titleBlock.Measure(new Size(maxW, double.PositiveInfinity));
+ double w = Math.Min(titleBlock.DesiredSize.Width, maxW);
+ double h = titleBlock.DesiredSize.Height;
+
+ piePanel.Children.Add(titleBlock);
+ Canvas.SetLeft(titleBlock, cx - w / 2);
+ Canvas.SetTop(titleBlock, TitlePlacement == PieTitlePlacement.Center ? cy - h / 2 : 0);
+ }
+
+ // 4. 图例(4 个角可设置,与饼图分列,不遮挡)
+ var legendPanel = CreateLegendPanel(slices, legendWidth - 16);
+ legendPanel.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+ double legendW = legendPanel.DesiredSize.Width;
+ double legendH = legendPanel.DesiredSize.Height;
+
+ const double padding = 8;
+ double lx, ly;
+ if (LegendPosition == PieLegendPosition.TopLeft || LegendPosition == PieLegendPosition.TopRight)
+ ly = padding;
+ else
+ ly = Math.Max(padding, height - legendH - padding);
+ lx = legendOnLeft ? padding : width - legendW - padding;
+
+ LayoutRoot.Children.Add(legendPanel);
+ Canvas.SetLeft(legendPanel, lx);
+ Canvas.SetTop(legendPanel, ly);
+ }
+
+ ///
+ /// 根据 生成实际绘制的扇区列表:
+ /// 按占比从大到小取前 N 项单独显示,其余项合并为一个“其他”扇区(百分比为剩余总和,整体仍为 100%)。
+ ///
+ private List BuildSlices(IList items)
+ {
+ var result = new List();
+ if (items == null || items.Count == 0)
+ return result;
+
+ var ordered = items
+ .OrderByDescending(i => i.Percentage)
+ .ThenByDescending(i => i.SalesAmount)
+ .ToList();
+
+ int max = MaxItems > 0 ? MaxItems : ordered.Count;
+ if (max >= ordered.Count)
+ {
+ for (int i = 0; i < ordered.Count; i++)
+ result.Add(new DisplaySlice
+ {
+ Item = ordered[i],
+ Brush = new SolidColorBrush(Palette[i % Palette.Length])
+ });
+ return result;
+ }
+
+ for (int i = 0; i < max; i++)
+ result.Add(new DisplaySlice
+ {
+ Item = ordered[i],
+ Brush = new SolidColorBrush(Palette[i % Palette.Length])
+ });
+
+ var rest = ordered.Skip(max).ToList();
+ result.Add(new DisplaySlice
+ {
+ Item = new ShopSalesProportionItem
+ {
+ ShopName = string.IsNullOrEmpty(OtherLabel) ? "其他" : OtherLabel,
+ Percentage = rest.Sum(r => r.Percentage),
+ SalesAmount = rest.Sum(r => r.SalesAmount)
+ },
+ Brush = OtherBrush ?? new SolidColorBrush(OtherColor)
+ });
+ return result;
+ }
+
+ private TextBlock CreateTitleBlock(double maxWidth)
+ {
+ var brush = TitleBrush ?? new SolidColorBrush(Color.FromRgb(51, 51, 51));
+ return new TextBlock
+ {
+ Text = Title,
+ FontSize = TitleFontSize,
+ FontWeight = FontWeights.Bold,
+ Foreground = brush,
+ TextAlignment = TextAlignment.Center,
+ TextWrapping = TextWrapping.Wrap,
+ TextTrimming = TextTrimming.CharacterEllipsis,
+ MaxWidth = maxWidth
+ };
+ }
+
+ private static StackPanel CreateLegendPanel(IList slices, double maxWidth)
+ {
+ double maxLegendWidth = Math.Max(60, maxWidth);
+ var legendPanel = new StackPanel { MaxWidth = maxLegendWidth };
+ foreach (var slice in slices)
+ {
+ var legendRow = new StackPanel
+ {
+ Orientation = Orientation.Horizontal,
+ Margin = new Thickness(0, 4, 0, 4)
+ };
+ legendRow.Children.Add(new Rectangle
+ {
+ Width = 12,
+ Height = 12,
+ Fill = slice.Brush
+ });
+
+ var text = new TextBlock
+ {
+ Text = slice.Item.ShopName + " " + slice.Item.Percentage.ToString("0.0") + "%",
+ FontSize = 12,
+ Foreground = new SolidColorBrush(Color.FromRgb(102, 102, 102)),
+ Margin = new Thickness(6, 0, 0, 0),
+ VerticalAlignment = VerticalAlignment.Center,
+ MaxWidth = Math.Max(40, maxLegendWidth - 18),
+ TextTrimming = TextTrimming.CharacterEllipsis
+ };
+ legendRow.Children.Add(text);
+ legendPanel.Children.Add(legendRow);
+ }
+ return legendPanel;
+ }
+
+ private static Path CreateSlice(double cx, double cy, double radius, double startAngle, double sweep, Brush fill)
+ {
+ var start = PointOnCircle(cx, cy, radius, startAngle);
+ var end = PointOnCircle(cx, cy, radius, startAngle + sweep);
+
+ var figure = new PathFigure { StartPoint = new Point(cx, cy), IsClosed = true, IsFilled = true };
+ figure.Segments.Add(new LineSegment { Point = start });
+ figure.Segments.Add(new ArcSegment
+ {
+ Point = end,
+ Size = new Size(radius, radius),
+ IsLargeArc = sweep > 180,
+ SweepDirection = SweepDirection.Clockwise
+ });
+
+ return new Path
+ {
+ Data = new PathGeometry { Figures = { figure } },
+ Fill = fill,
+ Stroke = Brushes.White,
+ StrokeThickness = 1
+ };
+ }
+
+ private static Point PointOnCircle(double cx, double cy, double radius, double angle)
+ {
+ double rad = angle * Math.PI / 180d;
+ return new Point(cx + radius * Math.Cos(rad), cy + radius * Math.Sin(rad));
+ }
+ }
+}
\ No newline at end of file
diff --git a/29WxOrderWpf/Ctrls/Statistics/General.xaml b/29WxOrderWpf/Ctrls/Statistics/General.xaml
new file mode 100644
index 0000000..2ab7af3
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/General.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/29WxOrderWpf/Ctrls/Statistics/Models/ShopRevenueStatisticsModels.cs b/29WxOrderWpf/Ctrls/Statistics/Models/ShopRevenueStatisticsModels.cs
new file mode 100644
index 0000000..8eebad0
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/Models/ShopRevenueStatisticsModels.cs
@@ -0,0 +1,256 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+
+namespace _29WxOrderWpf.Ctrls.Statistics.Models
+{
+ ///
+ /// 店铺营收统计 - 查询参数
+ ///
+ public class ShopRevenueStatisticsQuery
+ {
+ /// 开始时间
+ public DateTime StartDate { get; set; }
+
+ /// 结束时间
+ public DateTime EndDate { get; set; }
+
+ /// 店铺 app_key(A.app_key),空/Null 表示全部店铺
+ public string ShopKey { get; set; }
+ }
+
+ ///
+ /// 店铺营收统计 - 接口返回的原始明细行。
+ /// 对应接口返回字段:
+ /// A.app_key, B.create_time, B.order_id, B.status,
+ /// B.product_price, B.order_price, B.purchase_price, B.freight,
+ /// B.predict_commission_fee, B.commission_amount, B.discounted_price, B.profit,
+ /// B.purchase_status, c.refund_status
+ /// 其中 A 为店铺表,B 为订单表,c 为售后/退款表。
+ /// 金额字段单位均为“分”,展示时需除以 100。
+ ///
+ public class ShopRevenueStatisticsRow
+ {
+ /// A.app_key 店铺 app_key
+ [JsonProperty("app_key")]
+ public string AppKey { get; set; }
+
+ /// B.create_time 订单创建时间(接口为秒级时间戳,由 UnixDateTimeConverter 转换为 DateTime)
+ [JsonProperty("create_time")]
+ [JsonConverter(typeof(UnixDateTimeConverter))]
+ public DateTime CreateTime { get; set; }
+
+ /// B.order_id 订单号
+ [JsonProperty("order_id")]
+ public string OrderId { get; set; }
+
+ /// B.status 订单状态:10-待付款;20-待发货;21-部分发货;30-待收货;100-完成;200-全部商品售后之后订单取消;250-未付款用户主动取消或超时未付款订单自动取消
+ public int Status { get; set; }
+
+ /// B.product_price 商品总价(分)
+ [JsonProperty("product_price")]
+ public int ProductPrice { get; set; }
+
+ /// B.order_price 订单金额(分),计算公式:order_price = original_order_price - discounted_price - deduction_price - change_down_price
+ [JsonProperty("order_price")]
+ public int OrderPrice { get; set; }
+
+ /// B.purchase_price 采购价(分)
+ [JsonProperty("purchase_price")]
+ public int PurchasePrice { get; set; }
+
+ /// B.freight 运费(分)
+ public int Freight { get; set; }
+
+ /// B.predict_commission_fee 平台服务费(微信小店:预计技术服务费)(分)
+ [JsonProperty("predict_commission_fee")]
+ public int PredictCommissionFee { get; set; }
+
+ /// B.commission_amount 达人佣金(微信小店:分账金额)(分)
+ [JsonProperty("commission_amount")]
+ public int CommissionAmount { get; set; }
+
+ /// B.discounted_price 优惠券优惠金额(分)
+ [JsonProperty("discounted_price")]
+ public int DiscountedPrice { get; set; }
+
+ /// B.profit 利润(分),计算公式:实付金额 - 采购价 - 平台服务费 - 达人佣金(采购价、达人佣金为空值则按 0)
+ public int Profit { get; set; }
+
+ /// B.purchase_status 采购状态:0-未采购;1-采购(默认值 0,推送仓库时修改为 1)
+ [JsonProperty("purchase_status")]
+ public int PurchaseStatus { get; set; }
+
+ /// c.refund_status 退款状态(4/11 视为已退款,与 RevenueStatisticsAggregator.IsRefunded 保持一致)
+ [JsonProperty("refund_status")]
+ public int RefundStatus { get; set; }
+
+ /// 店铺名称(由 app_key 关联店铺表得到,展示用,非接口原始字段)
+ [JsonProperty("shop_name")]
+ public string ShopName { get; set; }
+
+ }
+
+ ///
+ /// 顶部汇总卡片数据(金额单位:元)
+ ///
+ public class ShopRevenueSummary
+ {
+ /// 销售额(最终有效销售额)
+ public decimal SalesAmount { get; set; }
+
+ /// 有效订单数(已扣除退款订单)
+ public int ValidOrderCount { get; set; }
+
+ /// 利润(实际利润)
+ public decimal Profit { get; set; }
+
+ /// 退款金额(统计期间退款)
+ public decimal RefundAmount { get; set; }
+
+ /// 商品销量(有效销量)
+ public int ProductSalesVolume { get; set; }
+
+ /// 客户数(成交客户)
+ public int CustomerCount { get; set; }
+
+ /// 客单价(平均每单金额)
+ public decimal AvgOrderAmount { get; set; }
+
+ /// 退款率(退款订单占比,百分数,如 2.31 表示 2.31%)
+ public decimal RefundRate { get; set; }
+ }
+
+ ///
+ /// 销售趋势数据点(金额单位:元)
+ ///
+ public class RevenueTrendPoint
+ {
+ /// 日期
+ public DateTime Date { get; set; }
+
+ /// 日期文本(MM-dd)
+ public string DateText { get { return Date.ToString("MM-dd"); } }
+
+ /// 当日销售额(元)
+ public decimal SalesAmount { get; set; }
+
+ /// 当日有效订单数
+ public int OrderCount { get; set; }
+ }
+
+ ///
+ /// 店铺销售占比数据(金额单位:元)
+ ///
+ public class ShopSalesProportionItem
+ {
+ /// 店铺名称
+ public string ShopName { get; set; }
+
+ /// 销售额(元)
+ public decimal SalesAmount { get; set; }
+
+ /// 占比(0~100)
+ public double Percentage { get; set; }
+ }
+
+ ///
+ /// 店铺统计表格行(金额单位:元)
+ ///
+ public class ShopStatisticsItem
+ {
+ /// 店铺名称
+ public string ShopName { get; set; }
+
+ /// 订单数
+ public int OrderCount { get; set; }
+
+ /// 销售额(元)
+ public decimal SalesAmount { get; set; }
+
+ /// 利润(元)
+ public decimal Profit { get; set; }
+
+ /// 退款金额(元)
+ public decimal RefundAmount { get; set; }
+
+ /// 客户数
+ public int CustomerCount { get; set; }
+
+ /// 客单价(元)
+ public decimal AvgOrderAmount { get; set; }
+ }
+
+ ///
+ /// 店铺下拉选项
+ ///
+ public class ShopOption
+ {
+ /// 店铺 app_key(A.app_key)
+ public string AppKey { get; set; }
+
+ /// 店铺名称
+ public string ShopName { get; set; }
+ }
+
+ ///
+ /// 时间范围下拉选项
+ ///
+ public class TimeRangeOption
+ {
+ /// 显示文本(如:今天、昨天、本周、本月、最近10天、自定义)
+ public string Text { get; set; }
+
+ /// 值(today / yesterday / week / month / last10 / custom)
+ public string Value { get; set; }
+ }
+
+ class UnixDateTimeConverter : JsonConverter
+ {
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(DateTime);
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ // 读取数值(支持 long 和 int 类型)
+ if (reader.TokenType == JsonToken.Integer)
+ {
+ long milliseconds = (long)reader.Value;
+ // Unix 纪元:1970-01-01 UTC
+ DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ if (milliseconds.ToString().Length == 13)
+ {
+ return epoch.AddMilliseconds(milliseconds);
+ }
+ return epoch.AddSeconds(milliseconds);
+
+
+ }
+ // 如果传入的是字符串(如 "1700000000000"),也支持
+ else if (reader.TokenType == JsonToken.String)
+ {
+ if (long.TryParse((string)reader.Value, out long milliseconds))
+ {
+ DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ if (milliseconds.ToString().Length == 13)
+ {
+ return epoch.AddMilliseconds(milliseconds);
+ }
+ return epoch.AddSeconds(milliseconds);
+ }
+ }
+ throw new JsonSerializationException($"无法将 {reader.Value} 转换为 DateTime");
+ }
+
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ // 序列化时转回时间戳
+ DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ long milliseconds = (long)((DateTime)value - epoch).TotalMilliseconds;
+ writer.WriteValue(milliseconds);
+ }
+ }
+}
\ No newline at end of file
diff --git a/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs b/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs
new file mode 100644
index 0000000..acc57c9
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs
@@ -0,0 +1,443 @@
+using _29WxOrderWpf.Common;
+using _29WxOrderWpf.Ctrls.Statistics.Models;
+using AllBase;
+using AllBase.Helper;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Serialization;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Work;
+
+namespace _29WxOrderWpf.Ctrls.Statistics.Services
+{
+ ///
+ /// 店铺营收统计 - 数据服务调用接口。
+ /// 页面只依赖此接口,接入真实数据源时新建实现类(如对接 HTTP 接口 / SQL 查询),
+ /// 并通过 ShopRevenueStatisticsViewModel 构造函数注入即可,无需改动页面。
+ ///
+ public interface IShopRevenueStatisticsService
+ {
+ ///
+ /// 查询原始统计明细(接口返回的 A.* / B.* / c.* 原始字段)。
+ /// 真实实现通常通过 SQL / HTTP 一次性返回这些行,再由聚合器计算。
+ ///
+ Task> QueryRowsAsync(ShopRevenueStatisticsQuery query);
+
+ /// 获取顶部汇总卡片数据
+ Task GetSummaryAsync(ShopRevenueStatisticsQuery query);
+
+ /// 获取销售趋势(按天)
+ Task> GetSalesTrendAsync(ShopRevenueStatisticsQuery query);
+
+ /// 获取店铺销售占比(饼图)
+ Task> GetShopSalesProportionAsync(ShopRevenueStatisticsQuery query);
+
+ /// 获取店铺统计表格
+ Task> GetShopStatisticsAsync(ShopRevenueStatisticsQuery query);
+
+ /// 获取店铺下拉列表(用于查询条件)
+ Task> GetShopOptionsAsync();
+ }
+
+ ///
+ /// 统计聚合器:把接口返回的原始明细行聚合成页面所需的汇总/趋势/占比/表格数据。
+ /// 聚合口径说明(依据接口字段描述):
+ /// - 订单状态 status:10-待付款;20-待发货;21-部分发货;30-待收货;100-完成;
+ /// 200-全部商品售后之后订单取消;250-未付款用户主动取消或超时未付款订单自动取消。
+ /// - 有效订单:已付款(20/21/30/100)且未退款;10/250 未付款不计入销售额。
+ /// - 已退款:c.refund_status 为 4/11,或订单状态为 200(全部商品售后后取消)。
+ /// - 金额字段单位均为“分”,除以 100 转为元。
+ ///
+ public static class RevenueStatisticsAggregator
+ {
+ /// 订单状态 - 待付款
+ public const int StatusPendingPay = 10;
+
+ /// 订单状态 - 待发货
+ public const int StatusWaitSend = 20;
+
+ /// 订单状态 - 部分发货
+ public const int StatusPartSend = 21;
+
+ /// 订单状态 - 待收货
+ public const int StatusWaitReceive = 30;
+
+ /// 订单状态 - 完成
+ public const int StatusFinished = 100;
+
+ /// 订单状态 - 全部商品售后之后订单取消
+ public const int StatusCancelAfterAfterSale = 200;
+
+ /// 订单状态 - 未付款用户主动取消/超时未付款自动取消
+ public const int StatusCancelNotPay = 250;
+
+ /// 是否已付款的订单(20/21/30/100;10 待付款、250 未付款取消不计入)
+ public static bool IsPaidOrder(ShopRevenueStatisticsRow row)
+ {
+ if (row == null) return false;
+ return row.Status == StatusWaitSend
+ || row.Status == StatusPartSend
+ || row.Status == StatusWaitReceive
+ || row.Status == StatusFinished;
+ }
+
+ /// 是否已退款(c.refund_status 为 4/11,或订单状态为 200 全部商品售后后取消)
+ public static bool IsRefunded(ShopRevenueStatisticsRow row)
+ {
+ if (row == null) return false;
+ return row.RefundStatus == 4 || row.RefundStatus == 11 || row.Status == StatusCancelAfterAfterSale;
+ }
+
+ /// 是否有效订单(已付款且未退款)
+ public static bool IsValidOrder(ShopRevenueStatisticsRow row)
+ {
+ return IsPaidOrder(row) && !IsRefunded(row);
+ }
+
+ /// 汇总卡片
+ public static ShopRevenueSummary GetSummary(IEnumerable rows)
+ {
+ var list = (rows ?? new List()).ToList();
+ var valid = list.Where(IsValidOrder).ToList();
+ var refunded = list.Where(IsRefunded).ToList();
+
+ decimal salesAmount = valid.Sum(r => (decimal)r.OrderPrice) / 100m;
+ decimal profit = valid.Sum(r => (decimal)r.Profit) / 100m;
+ decimal refundAmount = refunded.Sum(r => (decimal)r.OrderPrice) / 100m;
+ int validOrderCount = valid.Select(r => r.OrderId).Distinct().Count();
+ // 总订单数(退款率分母)= 已付款订单 + 已退款订单(含售后取消 200),不含未付款的 10/250
+ int totalOrderCount = list.Where(r => IsPaidOrder(r) || IsRefunded(r)).Select(r => r.OrderId).Distinct().Count();
+ int refundOrderCount = refunded.Select(r => r.OrderId).Distinct().Count();
+
+ return new ShopRevenueSummary
+ {
+ SalesAmount = salesAmount,
+ ValidOrderCount = validOrderCount,
+ Profit = profit,
+ RefundAmount = refundAmount,
+ ProductSalesVolume = valid.Count,
+ CustomerCount = validOrderCount,
+ AvgOrderAmount = validOrderCount == 0 ? 0m : salesAmount / validOrderCount,
+ RefundRate = totalOrderCount == 0 ? 0m : (decimal)refundOrderCount * 100m / totalOrderCount
+ };
+ }
+
+ /// 销售趋势(按天,缺失日期补 0,仅统计有效订单)
+ public static List GetSalesTrend(IEnumerable rows, DateTime startDate, DateTime endDate)
+ {
+ var list = (rows ?? new List()).Where(IsValidOrder).ToList();
+ var map = list
+ .GroupBy(r => r.CreateTime.Date)
+ .ToDictionary(
+ g => g.Key,
+ g => new RevenueTrendPoint
+ {
+ Date = g.Key,
+ SalesAmount = g.Sum(r => (decimal)r.OrderPrice) / 100m,
+ OrderCount = g.Select(r => r.OrderId).Distinct().Count()
+ });
+
+ var result = new List();
+ for (var d = startDate.Date; d <= endDate.Date; d = d.AddDays(1))
+ {
+ if (map.TryGetValue(d, out var point))
+ result.Add(point);
+ else
+ result.Add(new RevenueTrendPoint { Date = d, SalesAmount = 0m, OrderCount = 0 });
+ }
+ return result;
+ }
+
+ /// 店铺销售占比(饼图,仅统计有效订单)
+ public static List GetShopSalesProportion(IEnumerable rows)
+ {
+ var list = (rows ?? new List()).Where(IsValidOrder).ToList();
+ decimal total = list.Sum(r => (decimal)r.OrderPrice) / 100m;
+
+ return list
+ .GroupBy(r => r.ShopName)
+ .Select(g => new ShopSalesProportionItem
+ {
+ ShopName = string.IsNullOrEmpty(g.Key) ? "未知店铺" : g.Key,
+ SalesAmount = g.Sum(r => (decimal)r.OrderPrice) / 100m,
+ Percentage = total == 0m ? 0d : (double)(g.Sum(r => (decimal)r.OrderPrice) / 100m / total * 100m)
+ })
+ .OrderByDescending(i => i.SalesAmount)
+ .ToList();
+ }
+
+ /// 店铺统计表格
+ public static List GetShopStatistics(IEnumerable rows)
+ {
+ var list = (rows ?? new List()).ToList();
+
+ return list
+ .GroupBy(r => r.ShopName)
+ .Select(g =>
+ {
+ var valid = g.Where(IsValidOrder).ToList();
+ var refunded = g.Where(IsRefunded).ToList();
+ decimal salesAmount = valid.Sum(r => (decimal)r.OrderPrice) / 100m;
+ int orderCount = valid.Select(r => r.OrderId).Distinct().Count();
+ return new ShopStatisticsItem
+ {
+ ShopName = string.IsNullOrEmpty(g.Key) ? "未知店铺" : g.Key,
+ OrderCount = orderCount,
+ SalesAmount = salesAmount,
+ Profit = valid.Sum(r => (decimal)r.Profit) / 100m,
+ RefundAmount = refunded.Sum(r => (decimal)r.OrderPrice) / 100m,
+ CustomerCount = orderCount,
+ AvgOrderAmount = orderCount == 0 ? 0m : salesAmount / orderCount
+ };
+ })
+ .OrderByDescending(i => i.SalesAmount)
+ .ToList();
+ }
+ }
+
+ ///
+ /// 默认实现:返回模拟数据,用于页面演示/联调。
+ /// 接入真实接口时,新建实现类并注入即可(见 IShopRevenueStatisticsService 注释)。
+ ///
+ public class ShopRevenueStatisticsService : IShopRevenueStatisticsService
+ {
+ ///
+ /// 明细数据缓存。
+ /// key = 店铺id|yyyyMMdd(店铺 × 天),value = 该店铺当天的明细行。
+ /// 查询按“店铺 × 日期”命中;完全未命中时所有店铺 + 整个时间范围一次请求,
+ /// 部分命中时只请求缺失的店铺/日期段。
+ ///
+ private readonly Dictionary> _rowCache =
+ new Dictionary>();
+ private readonly object _cacheLock = new object();
+
+ private sealed class DateRange
+ {
+ public DateTime Start;
+ public DateTime End;
+ }
+
+ private static string CacheKey(string shopId, DateTime day)
+ {
+ return shopId + "|" + day.ToString("yyyyMMdd");
+ }
+
+ public async Task> QueryRowsAsync(ShopRevenueStatisticsQuery query)
+ {
+ // 1. 展开本次查询涉及的店铺(ShopKey 为空 = 全部店铺)
+ List shopIds;
+ if (string.IsNullOrEmpty(query.ShopKey))
+ shopIds = (await GetShopOptionsAsync()).Select(a => a.AppKey).ToList();
+ else
+ shopIds = new List { query.ShopKey };
+ if (shopIds.Count == 0)
+ return new List();
+
+ var startDay = query.StartDate.Date;
+ var endDay = query.EndDate.Date;
+ int totalDays = (int)(endDay - startDay).Days + 1;
+
+ // 2. 命中检测:按 店铺 × 天 找出缺失项
+ var missingByShop = new Dictionary>();
+ int missingCount = 0;
+ lock (_cacheLock)
+ {
+ foreach (var shopId in shopIds)
+ {
+ var missingDays = new List();
+ for (var d = startDay; d <= endDay; d = d.AddDays(1))
+ {
+ if (!_rowCache.ContainsKey(CacheKey(shopId, d)))
+ missingDays.Add(d);
+ }
+ missingCount += missingDays.Count;
+ missingByShop[shopId] = missingDays;
+ }
+ }
+
+ // 3. 全部命中:直接从缓存拼装返回
+ if (missingCount == 0)
+ return GetCachedRows(shopIds, startDay, endDay);
+
+ // 4. 完全未命中:所有店铺 + 整个时间范围一次请求
+ if (missingCount == shopIds.Count * totalDays)
+ {
+ var allRows = await RequestRowsAsync(shopIds, startDay, endDay);
+ CacheResponse(shopIds, startDay, endDay, allRows, null);
+ var cached = GetCachedRows(shopIds, startDay, endDay);
+ // 若接口行内未返回 app_key 导致无法入库,则直接返回本次请求结果
+ return cached.Count > 0 ? cached : allRows;
+ }
+
+ // 5. 部分命中:只请求未命中的(店铺 × 连续缺失日期段)
+ foreach (var pair in missingByShop)
+ {
+ if (pair.Value.Count == 0)
+ continue;
+ foreach (var run in BuildRuns(pair.Value))
+ {
+ var rows = await RequestRowsAsync(new List { pair.Key }, run.Start, run.End);
+ CacheResponse(new List { pair.Key }, run.Start, run.End, rows, pair.Key);
+ }
+ }
+
+ return GetCachedRows(shopIds, startDay, endDay);
+ }
+
+ /// 按 店铺 × 日期 从缓存拼装结果
+ private List GetCachedRows(List shopIds, DateTime startDate, DateTime endDate)
+ {
+ var result = new List();
+ lock (_cacheLock)
+ {
+ for (var d = startDate.Date; d <= endDate.Date; d = d.AddDays(1))
+ {
+ foreach (var shopId in shopIds)
+ {
+ if (_rowCache.TryGetValue(CacheKey(shopId, d), out var list))
+ result.AddRange(list);
+ }
+ }
+ }
+ return result;
+ }
+
+ /// 请求接口一次(可传多个店铺),返回原始明细行
+ private async Task> RequestRowsAsync(List shopIds, DateTime startDate, DateTime endDate)
+ {
+ var url = BaseClass.Build29WxObjString("shop_revenue_statistics/get_shop_order_amount");
+ var sb = new StringBuilder();
+ sb.Append(UserLogin.GetSignaturex());
+ sb.Append("&shop_ids=").Append(string.Join(",", shopIds));
+ sb.Append("&start_time=").Append(BaseClass.ConvertDateTimeLong(startDate.Date));
+ sb.Append("&end_time=").Append(BaseClass.ConvertDateTimeLong(endDate.Date.AddDays(1).AddTicks(-1)));
+ var html = await GetHtml.PostUtf8Async(url, sb.ToString());
+
+ var ret = JsonConvert.DeserializeObject>>(html, new JsonSerializerSettings
+ {
+ ContractResolver = new CamelCasePropertyNamesContractResolver()
+ });
+ if (ret.Code != 200)
+ {
+ throw new Exception(ret.Msg);
+ }
+ return ret.Data ?? new List();
+ }
+
+ ///
+ /// 把一次请求的结果写入缓存(按 店铺id|日期 分桶)。
+ /// 除有数据的 店铺×天 外,会把本次请求覆盖但无数据的 店铺×天 也标记为已缓存(空列表),
+ /// 避免“该店铺当天无数据”被反复判定为未命中而重复请求数据库。
+ ///
+ private void CacheResponse(List shopIds, DateTime startDate, DateTime endDate, List rows, string fallbackShopId)
+ {
+ if (rows == null)
+ rows = new List();
+
+ // 能否按 店铺×天 归属:
+ // 单店铺请求一定可以(用请求的店铺兜底);多店铺请求要求行内带 app_key;
+ // 响应为空时也视为可归属(说明覆盖的 店铺×天 都无数据)。
+ bool canAttribute = shopIds.Count == 1
+ || rows.Count == 0
+ || rows.Any(r => !string.IsNullOrEmpty(r.AppKey));
+
+ lock (_cacheLock)
+ {
+ if (canAttribute)
+ {
+ // 覆盖的 店铺×天 全部落缓存键(无数据的天记为空的已缓存)
+ for (var d = startDate.Date; d <= endDate.Date; d = d.AddDays(1))
+ {
+ foreach (var shopId in shopIds)
+ {
+ var key = CacheKey(shopId, d);
+ if (!_rowCache.TryGetValue(key, out var list))
+ {
+ list = new List();
+ _rowCache[key] = list;
+ }
+ }
+ }
+ }
+
+ // 有数据的行按 店铺×天 追加
+ foreach (var row in rows)
+ {
+ // 行内未带 app_key 时,用本次请求的店铺兜底
+ var shopId = string.IsNullOrEmpty(row.AppKey) ? fallbackShopId : row.AppKey;
+ if (string.IsNullOrEmpty(shopId))
+ continue;
+ var key = CacheKey(shopId, row.CreateTime.Date);
+ if (!_rowCache.TryGetValue(key, out var list))
+ {
+ list = new List();
+ _rowCache[key] = list;
+ }
+ list.Add(row);
+ }
+ }
+ }
+
+ /// 把缺失日期合并为连续日期段(每段一次请求)
+ private static List BuildRuns(List missingDays)
+ {
+ var sorted = missingDays.OrderBy(d => d).ToList();
+ var runs = new List();
+ int i = 0;
+ while (i < sorted.Count)
+ {
+ var start = sorted[i];
+ var end = start;
+ i++;
+ while (i < sorted.Count && sorted[i] == end.AddDays(1))
+ {
+ end = sorted[i];
+ i++;
+ }
+ runs.Add(new DateRange { Start = start, End = end });
+ }
+ return runs;
+ }
+
+ public async Task GetSummaryAsync(ShopRevenueStatisticsQuery query)
+ {
+ var rows = await QueryRowsAsync(query);
+ return RevenueStatisticsAggregator.GetSummary(rows);
+ }
+
+ public async Task> GetSalesTrendAsync(ShopRevenueStatisticsQuery query)
+ {
+ var rows = await QueryRowsAsync(query);
+ return RevenueStatisticsAggregator.GetSalesTrend(rows, query.StartDate, query.EndDate);
+ }
+
+ public async Task> GetShopSalesProportionAsync(ShopRevenueStatisticsQuery query)
+ {
+ var rows = await QueryRowsAsync(query);
+ return RevenueStatisticsAggregator.GetShopSalesProportion(rows);
+ }
+
+ public async Task> GetShopStatisticsAsync(ShopRevenueStatisticsQuery query)
+ {
+ var rows = await QueryRowsAsync(query);
+ return RevenueStatisticsAggregator.GetShopStatistics(rows);
+ }
+
+ public Task> GetShopOptionsAsync()
+ {
+ var list = GlobalConfig.ShopLoginList.Select(a =>
+ new ShopOption()
+ {
+ AppKey = a.ShopId,
+ ShopName = a.ShopAccount
+ }).ToList();
+
+ return Task.FromResult(list);
+ }
+
+ }
+}
diff --git a/29WxOrderWpf/Ctrls/Statistics/ShopRevenueStatisticsView.xaml b/29WxOrderWpf/Ctrls/Statistics/ShopRevenueStatisticsView.xaml
new file mode 100644
index 0000000..a7cb480
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/ShopRevenueStatisticsView.xaml
@@ -0,0 +1,455 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/29WxOrderWpf/Ctrls/Statistics/ShopRevenueStatisticsView.xaml.cs b/29WxOrderWpf/Ctrls/Statistics/ShopRevenueStatisticsView.xaml.cs
new file mode 100644
index 0000000..421018b
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/ShopRevenueStatisticsView.xaml.cs
@@ -0,0 +1,25 @@
+using System.Windows.Controls;
+using _29WxOrderWpf.Ctrls.Statistics.ViewModels;
+
+namespace _29WxOrderWpf.Ctrls.Statistics
+{
+ ///
+ /// 店铺营收统计页面(MVVM)。
+ /// 页面不写业务逻辑,只负责绑定 ShopRevenueStatisticsViewModel;
+ /// 如需注入自定义数据服务,请使用
+ /// new ShopRevenueStatisticsView(new ShopRevenueStatisticsViewModel(你的 IShopRevenueStatisticsService 实现))。
+ ///
+ public partial class ShopRevenueStatisticsView : UserControl
+ {
+ public ShopRevenueStatisticsView()
+ : this(new ShopRevenueStatisticsViewModel())
+ {
+ }
+
+ public ShopRevenueStatisticsView(ShopRevenueStatisticsViewModel viewModel)
+ {
+ InitializeComponent();
+ DataContext = viewModel;
+ }
+ }
+}
\ No newline at end of file
diff --git a/29WxOrderWpf/Ctrls/Statistics/ViewModels/ShopRevenueStatisticsViewModel.cs b/29WxOrderWpf/Ctrls/Statistics/ViewModels/ShopRevenueStatisticsViewModel.cs
new file mode 100644
index 0000000..70307f0
--- /dev/null
+++ b/29WxOrderWpf/Ctrls/Statistics/ViewModels/ShopRevenueStatisticsViewModel.cs
@@ -0,0 +1,288 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Input;
+using AllBase.Model.MvvmBaseClasses;
+using _29WxOrderWpf.Ctrls.Statistics.Models;
+using _29WxOrderWpf.Ctrls.Statistics.Services;
+using CefSharp;
+using _29WxOrderWpf.Commands;
+
+namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels
+{
+ ///
+ /// 店铺营收统计 - 页面 ViewModel(MVVM)。
+ /// 通过 IShopRevenueStatisticsService 调用数据接口;
+ /// 接入真实接口时传入自定义实现:new ShopRevenueStatisticsViewModel(你的服务实现)。
+ ///
+ public class ShopRevenueStatisticsViewModel : PropertyNotifyObject
+ {
+ private readonly IShopRevenueStatisticsService _service;
+
+ private ShopRevenueSummary _summary;
+ private ObservableCollection _trendData;
+ private ObservableCollection _shopProportionData;
+ private ObservableCollection _shopStatistics;
+ private ShopOption _selectedShop;
+ private string _selectedPlatform;
+
+ public ShopRevenueStatisticsViewModel()
+ : this(new ShopRevenueStatisticsService())
+ {
+
+ }
+
+ public ShopRevenueStatisticsViewModel(IShopRevenueStatisticsService service)
+ {
+ _service = service ?? new ShopRevenueStatisticsService();
+
+ TimeRangeOptions = new ObservableCollection
+ {
+ new TimeRangeOption { Text = "昨天", Value = "yesterday" },
+ new TimeRangeOption { Text = "本周", Value = "week" },
+ new TimeRangeOption { Text = "本月", Value = "month" },
+ new TimeRangeOption { Text = "最近10天", Value = "last10" },
+ new TimeRangeOption { Text = "自定义", Value = "custom" }
+ };
+
+ ShopOptions = new ObservableCollection();
+
+ QueryCommand = new DelegateCommand(async () => await LoadAsync());
+ ResetCommand = new DelegateCommand(Reset);
+
+ InitializeAsync();
+ }
+
+ #region 查询条件
+
+ /// 时间范围选项
+ public ObservableCollection TimeRangeOptions { get; }
+
+ /// 选中的时间范围
+ public TimeRangeOption SelectedTimeRange
+ {
+ get { return this.GetValue(x => x.SelectedTimeRange); }
+ set
+ {
+ this.SetValue(x => x.SelectedTimeRange, value);
+ ApplyTimeRange();
+ OnPropertyChanged(nameof(IsCustomDateRange));
+ }
+ }
+
+ /// 是否为自定义时间范围
+ public bool IsCustomDateRange
+ {
+ get { return SelectedTimeRange != null && SelectedTimeRange.Value == "custom"; }
+ }
+
+ /// 开始日期
+ public DateTime StartDate
+ {
+ get { return this.GetValue(x => x.StartDate); }
+ set { this.SetValue(x => x.StartDate, value); }
+ }
+
+ /// 结束日期
+ public DateTime EndDate
+ {
+ get { return this.GetValue(x => x.EndDate); }
+ set { this.SetValue(x => x.EndDate, value); }
+ }
+
+ /// 店铺选项(含“全部店铺”)
+ public ObservableCollection ShopOptions { get; }
+
+ /// 选中的店铺
+ public ShopOption SelectedShop
+ {
+ get { return _selectedShop; }
+ set
+ {
+ _selectedShop = value;
+ OnPropertyChanged(nameof(SelectedShop));
+ }
+ }
+
+ #endregion
+
+ #region 统计结果
+
+ /// 汇总卡片数据
+ public ShopRevenueSummary Summary
+ {
+ get { return _summary; }
+ private set
+ {
+ _summary = value;
+ OnPropertyChanged(nameof(Summary));
+ }
+ }
+
+ /// 销售趋势数据
+ public ObservableCollection TrendData
+ {
+ get { return _trendData; }
+ private set
+ {
+ _trendData = value;
+ OnPropertyChanged(nameof(TrendData));
+ }
+ }
+
+ /// 店铺销售占比数据
+ public ObservableCollection ShopProportionData
+ {
+ get { return _shopProportionData; }
+ private set
+ {
+ _shopProportionData = value;
+ OnPropertyChanged(nameof(ShopProportionData));
+ }
+ }
+
+ /// 店铺统计表格数据
+ public ObservableCollection ShopStatistics
+ {
+ get { return _shopStatistics; }
+ private set
+ {
+ _shopStatistics = value;
+ OnPropertyChanged(nameof(ShopStatistics));
+ }
+ }
+
+ /// 是否正在加载
+ public bool IsLoading
+ {
+ get { return this.GetValue(x => x.IsLoading); }
+ set { this.SetValue(x => x.IsLoading, value); }
+ }
+
+ #endregion
+
+ #region 命令
+
+ /// 查询命令
+ public ICommand QueryCommand { get; }
+
+ /// 重置命令
+ public ICommand ResetCommand { get; }
+
+ #endregion
+
+ #region 初始化
+
+ private async void InitializeAsync()
+ {
+ try
+ {
+ // 店铺选项
+ ShopOptions.Add(new ShopOption { AppKey = string.Empty, ShopName = "全部店铺" });
+ var shops = await _service.GetShopOptionsAsync();
+ foreach (var shop in shops)
+ ShopOptions.Add(shop);
+ SelectedShop = ShopOptions.FirstOrDefault();
+
+ // 默认时间范围:本月
+ SelectedTimeRange = TimeRangeOptions.FirstOrDefault(t => t.Value == "month");
+ ApplyTimeRange();
+
+ await LoadAsync();
+ }
+ catch (Exception)
+ {
+ // 初始化失败(如接口不可用),页面保持可查询状态;可在此接入日志/提示
+ }
+ }
+
+ #endregion
+
+ #region 业务逻辑
+
+ /// 根据时间范围选项计算起止日期
+ private void ApplyTimeRange()
+ {
+ var now = DateTime.Now;
+ var today = now.Date;
+ var selected = SelectedTimeRange == null ? string.Empty : SelectedTimeRange.Value;
+ switch (selected)
+ {
+ case "yesterday":
+ StartDate = today.AddDays(-1);
+ EndDate = today.AddDays(-1).AddHours(23).AddMinutes(59).AddSeconds(59);
+ break;
+ case "week":
+ int diff = today.DayOfWeek == DayOfWeek.Sunday ? 6 : (int)today.DayOfWeek - 1;
+ StartDate = today.AddDays(-diff);
+ EndDate = now;
+ break;
+ case "month":
+ StartDate = new DateTime(today.Year, today.Month, 1);
+ EndDate = now;
+ break;
+ case "last10":
+ StartDate = today.AddDays(-9);
+ EndDate = now;
+ break;
+ default:
+ // 自定义:保持用户选择的日期不变
+ break;
+ }
+ }
+
+ /// 执行查询,刷新页面所有统计数据
+ private async Task LoadAsync()
+ {
+ if (StartDate > EndDate)
+ {
+ var temp = StartDate;
+ StartDate = EndDate;
+ EndDate = temp;
+ }
+
+ IsLoading = true;
+ try
+ {
+ var query = new ShopRevenueStatisticsQuery
+ {
+ StartDate = StartDate,
+ EndDate = EndDate,
+ ShopKey = SelectedShop == null ? string.Empty : SelectedShop.AppKey,
+ };
+
+ Summary = await _service.GetSummaryAsync(query);
+
+ var trend = await _service.GetSalesTrendAsync(query);
+ TrendData = new ObservableCollection(trend);
+
+ var proportion = await _service.GetShopSalesProportionAsync(query);
+ ShopProportionData = new ObservableCollection(proportion);
+
+ var table = await _service.GetShopStatisticsAsync(query);
+ ShopStatistics = new ObservableCollection(table);
+ }
+ catch (Exception)
+ {
+ // 查询异常:保留上一次数据,可在此接入日志/错误提示
+ }
+ finally
+ {
+ IsLoading = false;
+ }
+ }
+
+ /// 重置查询条件并重新加载
+ private async void Reset()
+ {
+ SelectedShop = ShopOptions.FirstOrDefault();
+ SelectedTimeRange = TimeRangeOptions.FirstOrDefault(t => t.Value == "month");
+ ApplyTimeRange();
+ await LoadAsync();
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/AllBase/BaseClass.cs b/AllBase/BaseClass.cs
index fce2d68..ed06626 100644
--- a/AllBase/BaseClass.cs
+++ b/AllBase/BaseClass.cs
@@ -631,7 +631,7 @@ namespace AllBase
///
public static long ConvertDateTimeLong(DateTime time)
{
- TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
+ TimeSpan ts = time - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalMilliseconds);
}
diff --git a/AllBase/GetHtml.cs b/AllBase/GetHtml.cs
index 1323ad9..6ae44dc 100644
--- a/AllBase/GetHtml.cs
+++ b/AllBase/GetHtml.cs
@@ -19,1113 +19,1114 @@ using System.Security.Policy;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
+using System.Threading.Tasks;
using System.Web;
namespace AllBase
{
- public class GetHtml
- {
- ///
- /// 加载远程图片
- ///
- ///
- ///
- public static Image LoadImage(string url)
- {
- try
- {
- System.Net.WebRequest webreq = System.Net.WebRequest.Create(url);
- System.Net.WebResponse webres = webreq.GetResponse();
- System.IO.Stream stream = webres.GetResponseStream();
- return Image.FromStream(stream);
- }
- catch
- {
- return null;
- }
+ public class GetHtml
+ {
+ ///
+ /// 加载远程图片
+ ///
+ ///
+ ///
+ public static Image LoadImage(string url)
+ {
+ try
+ {
+ System.Net.WebRequest webreq = System.Net.WebRequest.Create(url);
+ System.Net.WebResponse webres = webreq.GetResponse();
+ System.IO.Stream stream = webres.GetResponseStream();
+ return Image.FromStream(stream);
+ }
+ catch
+ {
+ return null;
+ }
- }
+ }
- ///
- /// 读取网络图片转为Img以在DataGridView中显示,用于HttpWebRequest直接读取可能403的情况
- ///
- ///
- ///
- ///
- public static Image GetUrlImg(string imgUrl, out string rst)
- {
- rst = "";
- //return LoadImage(imgUrl);
- Image image = null;
- HttpWebResponse response = null;
- try
- {
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(imgUrl);
+ ///
+ /// 读取网络图片转为Img以在DataGridView中显示,用于HttpWebRequest直接读取可能403的情况
+ ///
+ ///
+ ///
+ ///
+ public static Image GetUrlImg(string imgUrl, out string rst)
+ {
+ rst = "";
+ //return LoadImage(imgUrl);
+ Image image = null;
+ HttpWebResponse response = null;
+ try
+ {
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(imgUrl);
- request.KeepAlive = true;
- request.Headers.Set(HttpRequestHeader.CacheControl, "max-age=0");
- request.Headers.Add("Upgrade-Insecure-Requests", @"1");
- request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.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.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
- request.Headers.Set(HttpRequestHeader.AcceptLanguage, "zh-CN,zh;q=0.9");
- //request.IfModifiedSince = DateTime.Parse("Fri, 18 Jul 2025 06:00:49 GMT"); // 没改动不更新,CS程序无缓存不使用
+ request.KeepAlive = true;
+ request.Headers.Set(HttpRequestHeader.CacheControl, "max-age=0");
+ request.Headers.Add("Upgrade-Insecure-Requests", @"1");
+ request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.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.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
+ request.Headers.Set(HttpRequestHeader.AcceptLanguage, "zh-CN,zh;q=0.9");
+ //request.IfModifiedSince = DateTime.Parse("Fri, 18 Jul 2025 06:00:49 GMT"); // 没改动不更新,CS程序无缓存不使用
- response = (HttpWebResponse)request.GetResponse();
+ response = (HttpWebResponse)request.GetResponse();
- using (Stream stream = response.GetResponseStream())
- {
- image = Image.FromStream(stream);
- }
- }
- catch (WebException ex)
- {
- if (ex.Status == WebExceptionStatus.ProtocolError)
- {
- response = (HttpWebResponse)ex.Response;
- rst = ReadResponse(response);
- }
- if (string.IsNullOrEmpty(rst))
- rst = ex.Message;
- }
- catch (Exception e)
- {
- rst = e.Message;
- }
- if (response != null)
- {
- response.Close();
- response.Dispose();
- }
- return image;
+ using (Stream stream = response.GetResponseStream())
+ {
+ image = Image.FromStream(stream);
+ }
+ }
+ catch (WebException ex)
+ {
+ if (ex.Status == WebExceptionStatus.ProtocolError)
+ {
+ response = (HttpWebResponse)ex.Response;
+ rst = ReadResponse(response);
+ }
+ if (string.IsNullOrEmpty(rst))
+ rst = ex.Message;
+ }
+ catch (Exception e)
+ {
+ rst = e.Message;
+ }
+ if (response != null)
+ {
+ response.Close();
+ response.Dispose();
+ }
+ return image;
- //try
- //{
- // if (!string.IsNullOrEmpty(prodSelect?.main_img))
- // {
- // using (Stream stream = WebRequest.Create(prodSelect.main_img.Replace("https", "http")).GetResponse().GetResponseStream())
- // {
- // image = Image.FromStream(stream);
- // }
- // }
- //}
- //catch (Exception ex)
- //{
- //}
- }
+ //try
+ //{
+ // if (!string.IsNullOrEmpty(prodSelect?.main_img))
+ // {
+ // using (Stream stream = WebRequest.Create(prodSelect.main_img.Replace("https", "http")).GetResponse().GetResponseStream())
+ // {
+ // image = Image.FromStream(stream);
+ // }
+ // }
+ //}
+ //catch (Exception ex)
+ //{
+ //}
+ }
- 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();
- }
- }
- }
+ 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();
+ }
+ }
+ }
- ///
- /// 代理抓取
- ///
- ///
- ///
- public static string ByProxy(string url)
- {
- string html = "", newurl = GetProxyUrlx(url);
- Random ro = new Random();
- int i = 0;
- MultiThreadClient mc = new MultiThreadClient();
- ReTry:
- html = mc.GetHtml(newurl);
- if (IsError(ref html))
- {
- Thread.Sleep(ro.Next(2000, 6000));
- if (i < 4)
- {
- i++;
- goto ReTry;
- }
- newurl = GetProxyUrlx(url);
- html = mc.GetHtml(newurl);
- if (IsError(ref html))
- return mc.GetHtml(url);
- return html;
- }
- Thread.Sleep(100 + BaseClass.WaitTime / 2 + ro.Next(BaseClass.WaitTime));
- Clear(ref html);
- return html;
- }
- ///
- /// 清理、处理代码
- ///
- ///
- private static void Clear(ref string html)
- {
- html = UrlDecode(html);
- html = html.Replace("\\", "");
- }
- ///
- /// 是否错误
- ///
- ///
- ///
- public static bool IsError(ref string html)
- {
- return string.IsNullOrEmpty(html) || html.Length < 100 || html.Contains("您的访问出错了") ||
- html.Contains("访问异常出错");
- }
- ///
- /// 获取代理地址
- ///
- ///
- ///
- public static string GetProxyUrlx(string url)
- {
- if (string.IsNullOrEmpty(url))
- return null;
- if (BaseClass.ProxyOut.Count == 0)
- {
- BaseClass.ViewCode += "代理异常";
- return url;
- }
- Random ra = new Random();
- string p = BaseClass.ProxyOut[ra.Next(BaseClass.ProxyOut.Count)];
- return "http://" + p + "/url=" + url.Replace(".google.", ".goo00gle.")
- .Replace("?", "%3f").Replace("=", "%3d").Replace("&", "%26");
- }
- ///
- /// ascii码转译为汉字
- ///
- /// 带ASCII码的字符串
- /// 还原字符串
- public static void AsciiToString(ref string temp)
- {
- if (string.IsNullOrEmpty(temp))
- return;
- //return;
- try
- {
- if (temp.Contains(""))
- {
- Regex reUnicode = new Regex(@"[x]([0-9A-Fa-f]{4,5});", RegexOptions.Compiled);
- temp = reUnicode.Replace(temp, m =>
- {
- short c;
- if (short.TryParse(m.Groups[1].Value, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out c))
- return "" + (char)c;
- return m.Value;
- });
- }
- if (temp.Contains("\\u"))
- {
- Regex reUnicode = new Regex(@"\\u([0-9a-fA-F]{4,5})", RegexOptions.Compiled);
- temp = reUnicode.Replace(temp, m =>
- {
- short c;
- if (short.TryParse(m.Groups[1].Value, System.Globalization.NumberStyles.HexNumber,
- CultureInfo.InvariantCulture, out c))
- return "" + (char)c;
- return m.Value;
- });
- }
- }
- catch
- {
- }
- //string html = "´,´©,©>,>µ,µ®,®°,°¡,¡, »,»" +
- // "¦,¦÷,÷¿,¿¬,¬§,§•,•½,½«,«¶,¶¨,¨" +
- // "¸,¸¼,¼<,<±,±×,×¢,¢¾,¾¯,¯“,"" +
- // "™,™€,€£,£¥,¥„,„…,…·,·›,›ª,ª" +
- // "ˆ,ˆ“,“—,—’,’º,º†,†‹,‹–,–" +
- // "‚,‚”,”‡,‡‘,‘‰,‰,˜,˜≈,≈" +
- // "⁄,⁄←,←∂,∂♠,♠∩,∩≥,≥≤,≤″,″∑,∑♣,♣" +
- // "↔,↔◊,◊′,′↑,↑↓,↓♥,♥−,−∏,∏,♦,♦" +
- // "∞,∞≠,≠√,√,≡,≡∫,∫‾,‾→,→α,αη,η" +
- // "μ,μπ,πθ,θβ,βγ,γν,νψ,ψυ,υχ,χι,ι" +
- // "ω,ωρ,ρξ,ξδ,δκ,κο,οσ,σζ,ζε,ε" +
- // "λ,λφ,φτ,τΑ,ΑΗ,ΗΜ,ΜΠ,ΠΘ,ΘΒ,ΒΓ,Γ" +
- // "Ν,ΝΨ,ΨΥ,ΥΧ,ΧΙ,ΙΩ,ΩΡ,ΡΞ,ΞΔ,ΔΚ,Κ" +
- // "Ο,ΟΣ,ΣΖ,ΖΕ,ΕΛ,ΛΦ,ΦΤ,Τς,ς&,&";
- //string[] h = html.Split(';');
- //string s1;
- //string s2;
- //foreach (string s in h)
- //{
- // s2 = s.Substring(2, s.Length - 2) + ";";
- // if (!temp.Contains(s2))
- // continue;
- // s1 = s.Substring(0, 1);
- // temp = temp.Replace(s2, s1);
- //}
- //return temp;
- }
- ///
- /// html解码,\u解码
- ///
- ///
- ///
- public static string UrlDecode(string html)
- {
- string temp = HttpUtility.UrlDecode(html);
- Regex reUnicode = new Regex(@"\\u([0-9a-fA-F]{4})", RegexOptions.Compiled);
- return reUnicode.Replace(temp, m =>
- {
- short c;
- if (short.TryParse(m.Groups[1].Value, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out c))
- return "" + (char)c;
- return m.Value;
- });
- }
+ ///
+ /// 代理抓取
+ ///
+ ///
+ ///
+ public static string ByProxy(string url)
+ {
+ string html = "", newurl = GetProxyUrlx(url);
+ Random ro = new Random();
+ int i = 0;
+ MultiThreadClient mc = new MultiThreadClient();
+ ReTry:
+ html = mc.GetHtml(newurl);
+ if (IsError(ref html))
+ {
+ Thread.Sleep(ro.Next(2000, 6000));
+ if (i < 4)
+ {
+ i++;
+ goto ReTry;
+ }
+ newurl = GetProxyUrlx(url);
+ html = mc.GetHtml(newurl);
+ if (IsError(ref html))
+ return mc.GetHtml(url);
+ return html;
+ }
+ Thread.Sleep(100 + BaseClass.WaitTime / 2 + ro.Next(BaseClass.WaitTime));
+ Clear(ref html);
+ return html;
+ }
+ ///
+ /// 清理、处理代码
+ ///
+ ///
+ private static void Clear(ref string html)
+ {
+ html = UrlDecode(html);
+ html = html.Replace("\\", "");
+ }
+ ///
+ /// 是否错误
+ ///
+ ///
+ ///
+ public static bool IsError(ref string html)
+ {
+ return string.IsNullOrEmpty(html) || html.Length < 100 || html.Contains("您的访问出错了") ||
+ html.Contains("访问异常出错");
+ }
+ ///
+ /// 获取代理地址
+ ///
+ ///
+ ///
+ public static string GetProxyUrlx(string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ return null;
+ if (BaseClass.ProxyOut.Count == 0)
+ {
+ BaseClass.ViewCode += "代理异常";
+ return url;
+ }
+ Random ra = new Random();
+ string p = BaseClass.ProxyOut[ra.Next(BaseClass.ProxyOut.Count)];
+ return "http://" + p + "/url=" + url.Replace(".google.", ".goo00gle.")
+ .Replace("?", "%3f").Replace("=", "%3d").Replace("&", "%26");
+ }
+ ///
+ /// ascii码转译为汉字
+ ///
+ /// 带ASCII码的字符串
+ /// 还原字符串
+ public static void AsciiToString(ref string temp)
+ {
+ if (string.IsNullOrEmpty(temp))
+ return;
+ //return;
+ try
+ {
+ if (temp.Contains(""))
+ {
+ Regex reUnicode = new Regex(@"[x]([0-9A-Fa-f]{4,5});", RegexOptions.Compiled);
+ temp = reUnicode.Replace(temp, m =>
+ {
+ short c;
+ if (short.TryParse(m.Groups[1].Value, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out c))
+ return "" + (char)c;
+ return m.Value;
+ });
+ }
+ if (temp.Contains("\\u"))
+ {
+ Regex reUnicode = new Regex(@"\\u([0-9a-fA-F]{4,5})", RegexOptions.Compiled);
+ temp = reUnicode.Replace(temp, m =>
+ {
+ short c;
+ if (short.TryParse(m.Groups[1].Value, System.Globalization.NumberStyles.HexNumber,
+ CultureInfo.InvariantCulture, out c))
+ return "" + (char)c;
+ return m.Value;
+ });
+ }
+ }
+ catch
+ {
+ }
+ //string html = "´,´©,©>,>µ,µ®,®°,°¡,¡, »,»" +
+ // "¦,¦÷,÷¿,¿¬,¬§,§•,•½,½«,«¶,¶¨,¨" +
+ // "¸,¸¼,¼<,<±,±×,×¢,¢¾,¾¯,¯“,"" +
+ // "™,™€,€£,£¥,¥„,„…,…·,·›,›ª,ª" +
+ // "ˆ,ˆ“,“—,—’,’º,º†,†‹,‹–,–" +
+ // "‚,‚”,”‡,‡‘,‘‰,‰,˜,˜≈,≈" +
+ // "⁄,⁄←,←∂,∂♠,♠∩,∩≥,≥≤,≤″,″∑,∑♣,♣" +
+ // "↔,↔◊,◊′,′↑,↑↓,↓♥,♥−,−∏,∏,♦,♦" +
+ // "∞,∞≠,≠√,√,≡,≡∫,∫‾,‾→,→α,αη,η" +
+ // "μ,μπ,πθ,θβ,βγ,γν,νψ,ψυ,υχ,χι,ι" +
+ // "ω,ωρ,ρξ,ξδ,δκ,κο,οσ,σζ,ζε,ε" +
+ // "λ,λφ,φτ,τΑ,ΑΗ,ΗΜ,ΜΠ,ΠΘ,ΘΒ,ΒΓ,Γ" +
+ // "Ν,ΝΨ,ΨΥ,ΥΧ,ΧΙ,ΙΩ,ΩΡ,ΡΞ,ΞΔ,ΔΚ,Κ" +
+ // "Ο,ΟΣ,ΣΖ,ΖΕ,ΕΛ,ΛΦ,ΦΤ,Τς,ς&,&";
+ //string[] h = html.Split(';');
+ //string s1;
+ //string s2;
+ //foreach (string s in h)
+ //{
+ // s2 = s.Substring(2, s.Length - 2) + ";";
+ // if (!temp.Contains(s2))
+ // continue;
+ // s1 = s.Substring(0, 1);
+ // temp = temp.Replace(s2, s1);
+ //}
+ //return temp;
+ }
+ ///
+ /// html解码,\u解码
+ ///
+ ///
+ ///
+ public static string UrlDecode(string html)
+ {
+ string temp = HttpUtility.UrlDecode(html);
+ Regex reUnicode = new Regex(@"\\u([0-9a-fA-F]{4})", RegexOptions.Compiled);
+ return reUnicode.Replace(temp, m =>
+ {
+ short c;
+ if (short.TryParse(m.Groups[1].Value, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out c))
+ return "" + (char)c;
+ return m.Value;
+ });
+ }
- ///
- /// 本地+国内+美国
- ///
- ///
- ///
- ///
- public static string GetByMyself(string url, out bool isError, bool isServer)
- {
- MultiThreadClient mu = new MultiThreadClient();
- mu.TimeOut = isServer ? 40 : 20;
- string Html = mu.GetHtml(url);
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(ProxyIpInUrl(url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(ProxyIpOutUrl(url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- {
- isError = true;
- return null;
- }
- isError = false;
- return Html;
- }
- ///
- /// 国内+本地+美国
- ///
- ///
- ///
- ///
- public static string GetByIn(string url, out bool isError, bool isServer)
- {
- MultiThreadClient mu = new MultiThreadClient();
- mu.TimeOut = isServer ? 40 : 20; ;
- string Html = mu.GetHtml(ProxyIpInUrl(url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(url);
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- {
- mu.TimeOut = 30;
- Html = mu.GetHtml(ProxyIpOutUrl(url));
- }
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- {
- isError = true;
- return null;
- }
- isError = false;
- return Html;
- }
- ///
- /// 国内+本地+美国
- ///
- ///
- ///
- ///
- public static string PostByIn(string url, out bool isError, bool isServer, string data)
- {
- MultiThreadClient mu = new MultiThreadClient();
- mu.TimeOut = isServer ? 40 : 20; ;
- string Html = mu.GetHtml(ProxyIpInUrl(url), Encoding.UTF8.GetBytes(data));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(url, Encoding.UTF8.GetBytes(data));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(ProxyIpOutUrl(url), Encoding.UTF8.GetBytes(data));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- {
- isError = true;
- return null;
- }
- isError = false;
- return Html;
- }
- ///
- /// 美国+国内+本地
- ///
- ///
- ///
- ///
- public static string GetByOut(string url, out bool isError, bool isServer)
- {
- MultiThreadClient mu = new MultiThreadClient();
- mu.TimeOut = isServer ? 60 : 30; ;
- string Html = mu.GetHtml(ProxyIpOutUrl(url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(ProxyIpInUrl(url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(url);
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- {
- isError = true;
- return null;
- }
- isError = false;
- return Html;
- }
- ///
- /// 美国服务器出口
- ///
- ///
- ///
- public static string ByUsa(string url)
- {
- bool isError;
- return ByUsa(url, out isError, false, false, false, false);
- }
- ///
- /// 美国服务器出口
- ///
- ///
- ///
- public static string ByUsa(string url, bool mobile)
- {
- bool isError;
- return ByUsa(url, out isError, mobile, false, false, false);
- }
- ///
- /// 美国服务器出口
- ///
- ///
- ///
- public static string ByUsa(bool isUtf8, string url)
- {
- bool isError;
- return ByUsa(url, out isError, false, false, isUtf8, false);
- }
- ///
- /// 美国服务器出口
- ///
- ///
- ///
- public static string ByUsa(string url, bool mobile, bool isGbk)
- {
- bool isError;
- return ByUsa(url, out isError, mobile, isGbk, false, false);
- }
- ///
- /// 美国服务器出口
- ///
- ///
- ///
- public static string ByUsaWhoies(string domain)
- {
- bool isError;
- return ByUsa(domain, out isError, false, false, false, true);
- }
+ ///
+ /// 本地+国内+美国
+ ///
+ ///
+ ///
+ ///
+ public static string GetByMyself(string url, out bool isError, bool isServer)
+ {
+ MultiThreadClient mu = new MultiThreadClient();
+ mu.TimeOut = isServer ? 40 : 20;
+ string Html = mu.GetHtml(url);
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(ProxyIpInUrl(url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(ProxyIpOutUrl(url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ {
+ isError = true;
+ return null;
+ }
+ isError = false;
+ return Html;
+ }
+ ///
+ /// 国内+本地+美国
+ ///
+ ///
+ ///
+ ///
+ public static string GetByIn(string url, out bool isError, bool isServer)
+ {
+ MultiThreadClient mu = new MultiThreadClient();
+ mu.TimeOut = isServer ? 40 : 20; ;
+ string Html = mu.GetHtml(ProxyIpInUrl(url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(url);
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ {
+ mu.TimeOut = 30;
+ Html = mu.GetHtml(ProxyIpOutUrl(url));
+ }
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ {
+ isError = true;
+ return null;
+ }
+ isError = false;
+ return Html;
+ }
+ ///
+ /// 国内+本地+美国
+ ///
+ ///
+ ///
+ ///
+ public static string PostByIn(string url, out bool isError, bool isServer, string data)
+ {
+ MultiThreadClient mu = new MultiThreadClient();
+ mu.TimeOut = isServer ? 40 : 20; ;
+ string Html = mu.GetHtml(ProxyIpInUrl(url), Encoding.UTF8.GetBytes(data));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(url, Encoding.UTF8.GetBytes(data));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(ProxyIpOutUrl(url), Encoding.UTF8.GetBytes(data));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ {
+ isError = true;
+ return null;
+ }
+ isError = false;
+ return Html;
+ }
+ ///
+ /// 美国+国内+本地
+ ///
+ ///
+ ///
+ ///
+ public static string GetByOut(string url, out bool isError, bool isServer)
+ {
+ MultiThreadClient mu = new MultiThreadClient();
+ mu.TimeOut = isServer ? 60 : 30; ;
+ string Html = mu.GetHtml(ProxyIpOutUrl(url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(ProxyIpInUrl(url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(url);
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ {
+ isError = true;
+ return null;
+ }
+ isError = false;
+ return Html;
+ }
+ ///
+ /// 美国服务器出口
+ ///
+ ///
+ ///
+ public static string ByUsa(string url)
+ {
+ bool isError;
+ return ByUsa(url, out isError, false, false, false, false);
+ }
+ ///
+ /// 美国服务器出口
+ ///
+ ///
+ ///
+ public static string ByUsa(string url, bool mobile)
+ {
+ bool isError;
+ return ByUsa(url, out isError, mobile, false, false, false);
+ }
+ ///
+ /// 美国服务器出口
+ ///
+ ///
+ ///
+ public static string ByUsa(bool isUtf8, string url)
+ {
+ bool isError;
+ return ByUsa(url, out isError, false, false, isUtf8, false);
+ }
+ ///
+ /// 美国服务器出口
+ ///
+ ///
+ ///
+ public static string ByUsa(string url, bool mobile, bool isGbk)
+ {
+ bool isError;
+ return ByUsa(url, out isError, mobile, isGbk, false, false);
+ }
+ ///
+ /// 美国服务器出口
+ ///
+ ///
+ ///
+ public static string ByUsaWhoies(string domain)
+ {
+ bool isError;
+ return ByUsa(domain, out isError, false, false, false, true);
+ }
- ///
- /// 美国服务器出口
- ///
- ///
- ///
- ///
- public static string ByUsa(string url, out bool isError, bool mobile, bool isGbk, bool isUtf8, bool isWhois)
- {
- MultiThreadClient mu = new MultiThreadClient();
- mu.TimeOut = 30;
- mu.IsGbk = isGbk;
- mu.IsUtf8 = isUtf8;
- if (mobile)
- mu.AddCookies = "Moblie";
- mu.IsWhoies = isWhois;
- string Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyOut, url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyOut, url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyOut, url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- {
- isError = true;
- return null;
- }
- isError = false;
- return Html;
- }
+ ///
+ /// 美国服务器出口
+ ///
+ ///
+ ///
+ ///
+ public static string ByUsa(string url, out bool isError, bool mobile, bool isGbk, bool isUtf8, bool isWhois)
+ {
+ MultiThreadClient mu = new MultiThreadClient();
+ mu.TimeOut = 30;
+ mu.IsGbk = isGbk;
+ mu.IsUtf8 = isUtf8;
+ if (mobile)
+ mu.AddCookies = "Moblie";
+ mu.IsWhoies = isWhois;
+ string Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyOut, url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyOut, url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyOut, url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ {
+ isError = true;
+ return null;
+ }
+ isError = false;
+ return Html;
+ }
- ///
- /// 局域网出口
- ///
- ///
- ///
- ///
- public static string ByLocation(string url)
- {
- MultiThreadClient mu = new MultiThreadClient();
- mu.TimeOut = 30;
- string Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyIn, url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyIn, url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyIn, url));
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- {
- return null;
- }
- return Html;
- }
+ ///
+ /// 局域网出口
+ ///
+ ///
+ ///
+ ///
+ public static string ByLocation(string url)
+ {
+ MultiThreadClient mu = new MultiThreadClient();
+ mu.TimeOut = 30;
+ string Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyIn, url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyIn, url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ Html = mu.GetHtml(GetProxyUrl(BaseClass.ProxyIn, url));
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ {
+ return null;
+ }
+ return Html;
+ }
- ///
- /// 远程下载文件
- ///
- ///
- ///
- ///
- public static bool ByUsaDownload(string url, string path)
- {
- string newUrl = GetProxyUrl(BaseClass.ProxyOut, url);
- bool ok = DownloadFile(newUrl, path);
- if (!ok)
- DownloadFile(GetProxyUrl(BaseClass.ProxyOut, url), path);
- if (!ok)
- DownloadFile(GetProxyUrl(BaseClass.ProxyOut, url), path);
- return ok;
- }
+ ///
+ /// 远程下载文件
+ ///
+ ///
+ ///
+ ///
+ public static bool ByUsaDownload(string url, string path)
+ {
+ string newUrl = GetProxyUrl(BaseClass.ProxyOut, url);
+ bool ok = DownloadFile(newUrl, path);
+ if (!ok)
+ DownloadFile(GetProxyUrl(BaseClass.ProxyOut, url), path);
+ if (!ok)
+ DownloadFile(GetProxyUrl(BaseClass.ProxyOut, url), path);
+ return ok;
+ }
- ///
- /// HTTPS专用出口
- ///
- ///
- ///
- public static string ByHttps(string url)
- {
- bool isError;
- return ByHttps(url, out isError, false);
- }
- ///
- /// HTTPS专用出口
- ///
- ///
- ///
- public static string ByHttps(string url, bool mobile)
- {
- bool isError;
- return ByHttps(url, out isError, mobile);
- }
- ///
- /// HTTPS专用出口
- ///
- ///
- ///
- ///
- public static string ByHttps(string url, out bool isError, bool mobile)
- {
- MultiThreadClient mu = new MultiThreadClient();
- mu.TimeOut = 60;
- if (mobile)
- mu.IsMoblie = true;
- string urlx = GetProxyUrl(BaseClass.ProxyHttps, url);
- string Html = mu.GetHtml(urlx);
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- {
- urlx = GetProxyUrl(BaseClass.ProxyHttps, url);
- Html = mu.GetHtml(urlx);
- }
- if (string.IsNullOrEmpty(Html) || mu.IsError)
- {
- isError = true;
- return null;
- }
- isError = false;
- return Html;
- }
- ///
- /// 转换URL
- ///
- ///
- ///
- ///
- public static string GetProxyUrl(List ips, string url)
- {
- if (ips.Count == 0)
- return url;
- Random ra = new Random(Guid.NewGuid().GetHashCode());
- string ip = ips[ra.Next(ips.Count)];
+ ///
+ /// HTTPS专用出口
+ ///
+ ///
+ ///
+ public static string ByHttps(string url)
+ {
+ bool isError;
+ return ByHttps(url, out isError, false);
+ }
+ ///
+ /// HTTPS专用出口
+ ///
+ ///
+ ///
+ public static string ByHttps(string url, bool mobile)
+ {
+ bool isError;
+ return ByHttps(url, out isError, mobile);
+ }
+ ///
+ /// HTTPS专用出口
+ ///
+ ///
+ ///
+ ///
+ public static string ByHttps(string url, out bool isError, bool mobile)
+ {
+ MultiThreadClient mu = new MultiThreadClient();
+ mu.TimeOut = 60;
+ if (mobile)
+ mu.IsMoblie = true;
+ string urlx = GetProxyUrl(BaseClass.ProxyHttps, url);
+ string Html = mu.GetHtml(urlx);
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ {
+ urlx = GetProxyUrl(BaseClass.ProxyHttps, url);
+ Html = mu.GetHtml(urlx);
+ }
+ if (string.IsNullOrEmpty(Html) || mu.IsError)
+ {
+ isError = true;
+ return null;
+ }
+ isError = false;
+ return Html;
+ }
+ ///
+ /// 转换URL
+ ///
+ ///
+ ///
+ ///
+ public static string GetProxyUrl(List ips, string url)
+ {
+ if (ips.Count == 0)
+ return url;
+ Random ra = new Random(Guid.NewGuid().GetHashCode());
+ string ip = ips[ra.Next(ips.Count)];
- return "http://" + (ip.Contains(":") ? ip : ip + ":6000") + "/url=" + ReplaceUrl(url);
- }
+ return "http://" + (ip.Contains(":") ? ip : ip + ":6000") + "/url=" + ReplaceUrl(url);
+ }
- ///
- /// utf8 下载页面
- ///
- ///
- ///
- public static string Utf8(string url)
- {
- if (string.IsNullOrEmpty(url))
- return "";
- try
- {
- WebClientx web = new WebClientx();
- web.Timeout = 60;
- web.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
- web.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
- web.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)");
- web.Proxy = null;
- byte[] b = web.DownloadData(url);
- return Encoding.UTF8.GetString(b);
- }
- catch
- {
- return "";
- }
- }
- ///
- /// Whois 查询
- ///
- ///
- ///
- public static string Whois(string url)
- {
- if (string.IsNullOrEmpty(url))
- return "";
- try
- {
- WebClientx web = new WebClientx();
- web.Timeout = 30;
- web.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
- web.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
- web.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)");
- web.Headers.Add("Add-Cookies", "whois");
- web.Proxy = null;
- byte[] b = web.DownloadData(url);
- return Encoding.UTF8.GetString(b);
- }
- catch
- {
- return "";
- }
- }
+ ///
+ /// utf8 下载页面
+ ///
+ ///
+ ///
+ public static string Utf8(string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ return "";
+ try
+ {
+ WebClientx web = new WebClientx();
+ web.Timeout = 60;
+ web.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+ web.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
+ web.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)");
+ web.Proxy = null;
+ byte[] b = web.DownloadData(url);
+ return Encoding.UTF8.GetString(b);
+ }
+ catch
+ {
+ return "";
+ }
+ }
+ ///
+ /// Whois 查询
+ ///
+ ///
+ ///
+ public static string Whois(string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ return "";
+ try
+ {
+ WebClientx web = new WebClientx();
+ web.Timeout = 30;
+ web.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+ web.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
+ web.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)");
+ web.Headers.Add("Add-Cookies", "whois");
+ web.Proxy = null;
+ byte[] b = web.DownloadData(url);
+ return Encoding.UTF8.GetString(b);
+ }
+ catch
+ {
+ return "";
+ }
+ }
- ///
- /// 模拟百度抓取
- ///
- ///
- ///
- public static string ByBaidu(string url)
- {
- string userAgent = "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)";
- return ByBaidu(url, userAgent);
- }
- ///
- /// 模拟百度蜘蛛下载页面
- ///
- ///
- ///
- public static string ByBaidu(string url, bool redirect)
- {
- if (string.IsNullOrEmpty(url))
- return "";
- try
- {
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
- request.Method = "GET";
- request.Accept = "*/*";
- request.Headers.Add("Accept-Language", "zh-CN");
- request.Headers.Add("Accept-Encoding", "gzip,deflate");
- request.UserAgent =
- "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1";
- request.AllowAutoRedirect = redirect;
- request.Timeout = 20000;
- request.ReadWriteTimeout = 20000;
+ ///
+ /// 模拟百度抓取
+ ///
+ ///
+ ///
+ public static string ByBaidu(string url)
+ {
+ string userAgent = "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)";
+ return ByBaidu(url, userAgent);
+ }
+ ///
+ /// 模拟百度蜘蛛下载页面
+ ///
+ ///
+ ///
+ public static string ByBaidu(string url, bool redirect)
+ {
+ if (string.IsNullOrEmpty(url))
+ return "";
+ try
+ {
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
+ request.Method = "GET";
+ request.Accept = "*/*";
+ request.Headers.Add("Accept-Language", "zh-CN");
+ request.Headers.Add("Accept-Encoding", "gzip,deflate");
+ request.UserAgent =
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1";
+ request.AllowAutoRedirect = redirect;
+ request.Timeout = 20000;
+ request.ReadWriteTimeout = 20000;
- request.Proxy = null;
- HttpWebResponse response = (HttpWebResponse)request.GetResponse();
- Stream receiveStream = response.GetResponseStream();
- MemoryStream ms = new MemoryStream();
- int num = 0;
- byte[] buffer = new byte[10240];
- do
- {
- num = receiveStream.Read(buffer, 0, buffer.Length);
- if (num > 0)
- ms.Write(buffer, 0, num);
- } while (num > 0);
- byte[] b = ms.ToArray();
- ms.Close();
- b = ZipHelper.Decompress(b);
- string contentType = response.Headers["Content-Type"];
- string newurl = response.Headers["Location"];
- if (!string.IsNullOrEmpty(newurl))
- return "重定向:" + newurl;
- string html = "";
- if (!string.IsNullOrEmpty(contentType))
- {
- string c = GetRegexString(contentType, "charset\\s*=\\s*(\\S+)").Trim();
- if (!string.IsNullOrEmpty(c))
- html = Encoding.GetEncoding(c).GetString(b);
- }
- if (string.IsNullOrEmpty(html))
- {
- html = Encoding.GetEncoding("UTF-8").GetString(b);
- string r = @"]*?charset=[""']*([\w-]+)[""']*";
- string c = GetRegexString(html.ToLower(), r);
- if (c.IndexOf("'") > -1)
- c = c.Substring(0, c.IndexOf("'"));
- if (c.IndexOf("\"") > -1)
- c = c.Substring(0, c.IndexOf("\""));
- if (c.IndexOf(" ") > -1)
- c = c.Substring(0, c.IndexOf(" "));
- if (c.IndexOf(">") > -1)
- c = c.Substring(0, c.IndexOf(">"));
- if (c.ToLower() != "utf-8" && !string.IsNullOrEmpty(c))
- html = Encoding.GetEncoding(c).GetString(b);
- else if (string.IsNullOrEmpty(c))
- html = Encoding.GetEncoding("gbk").GetString(b);
- }
- if (!string.IsNullOrEmpty(html))
- {
- if (html.Substring(0, 1) == "锘")
- html = Encoding.GetEncoding("UTF-8").GetString(b);
- //if (html.Contains("�") && (html.Length - html.Replace("�", "").Length > 3))
- // html = Encoding.GetEncoding("gbk").GetString(b);
- }
- if (string.IsNullOrEmpty(html) && !string.IsNullOrEmpty(newurl))
- html = "重定向:" + newurl;
- return html;
- }
- catch (Exception e)
- {
- return e.Message;
- }
- }
+ request.Proxy = null;
+ HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+ Stream receiveStream = response.GetResponseStream();
+ MemoryStream ms = new MemoryStream();
+ int num = 0;
+ byte[] buffer = new byte[10240];
+ do
+ {
+ num = receiveStream.Read(buffer, 0, buffer.Length);
+ if (num > 0)
+ ms.Write(buffer, 0, num);
+ } while (num > 0);
+ byte[] b = ms.ToArray();
+ ms.Close();
+ b = ZipHelper.Decompress(b);
+ string contentType = response.Headers["Content-Type"];
+ string newurl = response.Headers["Location"];
+ if (!string.IsNullOrEmpty(newurl))
+ return "重定向:" + newurl;
+ string html = "";
+ if (!string.IsNullOrEmpty(contentType))
+ {
+ string c = GetRegexString(contentType, "charset\\s*=\\s*(\\S+)").Trim();
+ if (!string.IsNullOrEmpty(c))
+ html = Encoding.GetEncoding(c).GetString(b);
+ }
+ if (string.IsNullOrEmpty(html))
+ {
+ html = Encoding.GetEncoding("UTF-8").GetString(b);
+ string r = @"]*?charset=[""']*([\w-]+)[""']*";
+ string c = GetRegexString(html.ToLower(), r);
+ if (c.IndexOf("'") > -1)
+ c = c.Substring(0, c.IndexOf("'"));
+ if (c.IndexOf("\"") > -1)
+ c = c.Substring(0, c.IndexOf("\""));
+ if (c.IndexOf(" ") > -1)
+ c = c.Substring(0, c.IndexOf(" "));
+ if (c.IndexOf(">") > -1)
+ c = c.Substring(0, c.IndexOf(">"));
+ if (c.ToLower() != "utf-8" && !string.IsNullOrEmpty(c))
+ html = Encoding.GetEncoding(c).GetString(b);
+ else if (string.IsNullOrEmpty(c))
+ html = Encoding.GetEncoding("gbk").GetString(b);
+ }
+ if (!string.IsNullOrEmpty(html))
+ {
+ if (html.Substring(0, 1) == "锘")
+ html = Encoding.GetEncoding("UTF-8").GetString(b);
+ //if (html.Contains("�") && (html.Length - html.Replace("�", "").Length > 3))
+ // html = Encoding.GetEncoding("gbk").GetString(b);
+ }
+ if (string.IsNullOrEmpty(html) && !string.IsNullOrEmpty(newurl))
+ html = "重定向:" + newurl;
+ return html;
+ }
+ catch (Exception e)
+ {
+ return e.Message;
+ }
+ }
- ///
- /// 自动识别代码模拟浏览器
- ///
- ///
- ///
- public static string GetUrl(string getUrl, ref string cookies, ref string codeType)
- {
- if (string.IsNullOrEmpty(getUrl))
- return "";
- try
- {
- int retryTimes = 0;
- GotoAgen:
- if (string.IsNullOrEmpty(cookies))
- cookies = null;
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(getUrl);
- request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0";
- request.Method = "GET";
- request.Accept = "*/*";
- request.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip,deflate");
- request.Headers.Add("Cookie", cookies);
+ ///
+ /// 自动识别代码模拟浏览器
+ ///
+ ///
+ ///
+ public static string GetUrl(string getUrl, ref string cookies, ref string codeType)
+ {
+ if (string.IsNullOrEmpty(getUrl))
+ return "";
+ try
+ {
+ int retryTimes = 0;
+ GotoAgen:
+ if (string.IsNullOrEmpty(cookies))
+ cookies = null;
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(getUrl);
+ request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0";
+ request.Method = "GET";
+ request.Accept = "*/*";
+ request.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
+ request.Headers.Add("Accept-Encoding", "gzip,deflate");
+ request.Headers.Add("Cookie", cookies);
- request.Proxy = null;
- request.AllowAutoRedirect = false;
- request.Timeout = 10000;
- HttpWebResponse response = (HttpWebResponse)request.GetResponse();
- Stream receiveStream = response.GetResponseStream();
- MemoryStream ms = new MemoryStream();
- int num = 0;
- byte[] buffer = new byte[20480];
- do
- {
- try
- {
- num = receiveStream.Read(buffer, 0, buffer.Length);
- if (num > 0)
- ms.Write(buffer, 0, num);
- }
- catch
- {
- num = 0;
- }
- }
- while (num > 0);
- byte[] b = ms.ToArray();
- ms.Close();
+ request.Proxy = null;
+ request.AllowAutoRedirect = false;
+ request.Timeout = 10000;
+ HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+ Stream receiveStream = response.GetResponseStream();
+ MemoryStream ms = new MemoryStream();
+ int num = 0;
+ byte[] buffer = new byte[20480];
+ do
+ {
+ try
+ {
+ num = receiveStream.Read(buffer, 0, buffer.Length);
+ if (num > 0)
+ ms.Write(buffer, 0, num);
+ }
+ catch
+ {
+ num = 0;
+ }
+ }
+ while (num > 0);
+ byte[] b = ms.ToArray();
+ ms.Close();
- b = ZipHelper.Decompress(b);
- string cookies1 = response.Headers.Get("Set-Cookie");
- string location = response.Headers.Get("Location"); //跳转地址
- if (!string.IsNullOrEmpty(cookies1))
- cookies = UpCookies(cookies, cookies1);
- string contentType = response.Headers["Content-Type"];
- string html = "";
- if (string.IsNullOrEmpty(location)) //不是跳转
- {
- if (!string.IsNullOrEmpty(contentType))
- {
- codeType = GetRegexString(contentType, "charset\\s*=\\s*(\\S+)").Trim();
- if (!string.IsNullOrEmpty(codeType))
- html = Encoding.GetEncoding(codeType).GetString(b);
- }
- if (string.IsNullOrEmpty(html))
- {
- codeType = "UTF-8";
- html = Encoding.GetEncoding(codeType).GetString(b);
- string r = @"<\s*meta.+charset\s*=\s*[""']*(\S+)[""'\s>]*";
- string c = GetRegexString(html, r).Trim();
- if (c.IndexOf("'") > -1)
- c = c.Substring(0, c.IndexOf("'"));
- if (c.IndexOf("\"") > -1)
- c = c.Substring(0, c.IndexOf("\""));
- if (c.IndexOf(" ") > -1)
- c = c.Substring(0, c.IndexOf(" "));
- if (c.IndexOf(">") > -1)
- c = c.Substring(0, c.IndexOf(">"));
- if (!string.IsNullOrEmpty(c) && c.ToLower() != "utf-8")
- {
- html = Encoding.GetEncoding(c).GetString(b);
- codeType = c;
- }
- }
- }
- if (retryTimes < 4 && (!string.IsNullOrEmpty(location) || string.IsNullOrEmpty(html)))
- {
- //下面是支持301和302跳转部分
- if (location.Length > 8 && (location.Substring(0, 7) == "http://" || location.Substring(0, 8) == "https://" || location.Substring(0, 6) == "ftp://"))
- {
- getUrl = location;
- }
- else
- {
- if (location.Substring(0, 1) == "/")
- {
- string[] l = getUrl.Split('/');
- if (l.Length > 3)
- {
- getUrl = "";
- for (int i = 0; i < 3; i++)
- getUrl += l[i] + "/";
- getUrl += location.Substring(1, location.Length - 1);
- }
- }
- else
- {
- if (getUrl.Substring(getUrl.Length - 1, 1) == "/")
- getUrl += location;
- else
- getUrl += "/" + location;
- }
- }
- retryTimes++;
- goto GotoAgen;
- }
- return html;
- }
- catch
- {
- return "";
- }
- }
- ///
- /// 更新cookies
- ///
- ///
- ///
- ///
- private static string UpCookies(string old, string newc)
- {
- if (string.IsNullOrEmpty(old))
- {
- return newc;
- }
- if (string.IsNullOrEmpty(newc))
- {
- return old;
- }
- int io = 0;
- old = old.Trim();
- newc = newc.Trim();
- string[] o = old.Split(';');
- string[] n = newc.Split(';');
- List c = new List();
- for (int i = 0; i < o.Length; i++)
- {
- CoockiesValue cv = new CoockiesValue();
- io = o[i].IndexOf("=");
- if (io > -1)
- {
- cv.Title = o[i].Substring(0, io).Trim();
- cv.Value = o[i].Substring(io + 1, o[i].Length - io - 1).Trim();
- }
- else
- {
- if (!string.IsNullOrEmpty(o[i]))
- cv.Title = o[i].Trim();
- }
- if (!string.IsNullOrEmpty(cv.Title))
- c.Add(cv);
- }
- for (int i = 0; i < n.Length; i++)
- {
- CoockiesValue cv = new CoockiesValue();
- io = o[i].IndexOf("=");
- if (io > -1)
- {
- cv.Title = o[i].Substring(0, io).Trim();
- cv.Value = o[i].Substring(io + 1, o[i].Length - io - 1).Trim();
- }
- else
- {
- if (!string.IsNullOrEmpty(o[i]))
- cv.Title = o[i].Trim();
- }
- if (!string.IsNullOrEmpty(cv.Title))
- {
- bool isHad = false;
- for (int j = 0; j < c.Count; j++)
- {
- if (cv.Title == c[j].Title)
- {
- c[j].Value = cv.Value;
- isHad = true;
- break;
- }
- }
- if (!isHad)
- c.Add(cv);
- }
- }
- string temp = "";
- for (int i = 0; i < c.Count; i++)
- {
- if (string.IsNullOrEmpty(c[i].Value))
- temp += c[i].Title + "; ";
- else
- temp += c[i].Title + "=" + c[i].Value + "; ";
- }
- return temp;
- }
- ///
- /// cookies值
- ///
- public class CoockiesValue
- {
- ///
- /// 名称
- ///
- public string Title { get; set; }
- ///
- /// 值
- ///
- public string Value { get; set; }
- }
- ///
- /// 模拟百度蜘蛛下载页面
- ///
- ///
- ///
- public static string ByBaidu(string url, string userAgent)
- {
- if (string.IsNullOrEmpty(url))
- {
- return "";
- }
- try
- {
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
- request.Method = "GET";
- request.Accept = "*/*";
- request.Headers.Add("Accept-Language", "zh-CN");
- request.Headers.Add("Accept-Encoding", "gzip,deflate");
- request.UserAgent = userAgent;
- request.AllowAutoRedirect = false;
- request.Timeout = 10000;
- request.ReadWriteTimeout = 10000;
+ b = ZipHelper.Decompress(b);
+ string cookies1 = response.Headers.Get("Set-Cookie");
+ string location = response.Headers.Get("Location"); //跳转地址
+ if (!string.IsNullOrEmpty(cookies1))
+ cookies = UpCookies(cookies, cookies1);
+ string contentType = response.Headers["Content-Type"];
+ string html = "";
+ if (string.IsNullOrEmpty(location)) //不是跳转
+ {
+ if (!string.IsNullOrEmpty(contentType))
+ {
+ codeType = GetRegexString(contentType, "charset\\s*=\\s*(\\S+)").Trim();
+ if (!string.IsNullOrEmpty(codeType))
+ html = Encoding.GetEncoding(codeType).GetString(b);
+ }
+ if (string.IsNullOrEmpty(html))
+ {
+ codeType = "UTF-8";
+ html = Encoding.GetEncoding(codeType).GetString(b);
+ string r = @"<\s*meta.+charset\s*=\s*[""']*(\S+)[""'\s>]*";
+ string c = GetRegexString(html, r).Trim();
+ if (c.IndexOf("'") > -1)
+ c = c.Substring(0, c.IndexOf("'"));
+ if (c.IndexOf("\"") > -1)
+ c = c.Substring(0, c.IndexOf("\""));
+ if (c.IndexOf(" ") > -1)
+ c = c.Substring(0, c.IndexOf(" "));
+ if (c.IndexOf(">") > -1)
+ c = c.Substring(0, c.IndexOf(">"));
+ if (!string.IsNullOrEmpty(c) && c.ToLower() != "utf-8")
+ {
+ html = Encoding.GetEncoding(c).GetString(b);
+ codeType = c;
+ }
+ }
+ }
+ if (retryTimes < 4 && (!string.IsNullOrEmpty(location) || string.IsNullOrEmpty(html)))
+ {
+ //下面是支持301和302跳转部分
+ if (location.Length > 8 && (location.Substring(0, 7) == "http://" || location.Substring(0, 8) == "https://" || location.Substring(0, 6) == "ftp://"))
+ {
+ getUrl = location;
+ }
+ else
+ {
+ if (location.Substring(0, 1) == "/")
+ {
+ string[] l = getUrl.Split('/');
+ if (l.Length > 3)
+ {
+ getUrl = "";
+ for (int i = 0; i < 3; i++)
+ getUrl += l[i] + "/";
+ getUrl += location.Substring(1, location.Length - 1);
+ }
+ }
+ else
+ {
+ if (getUrl.Substring(getUrl.Length - 1, 1) == "/")
+ getUrl += location;
+ else
+ getUrl += "/" + location;
+ }
+ }
+ retryTimes++;
+ goto GotoAgen;
+ }
+ return html;
+ }
+ catch
+ {
+ return "";
+ }
+ }
+ ///
+ /// 更新cookies
+ ///
+ ///
+ ///
+ ///
+ private static string UpCookies(string old, string newc)
+ {
+ if (string.IsNullOrEmpty(old))
+ {
+ return newc;
+ }
+ if (string.IsNullOrEmpty(newc))
+ {
+ return old;
+ }
+ int io = 0;
+ old = old.Trim();
+ newc = newc.Trim();
+ string[] o = old.Split(';');
+ string[] n = newc.Split(';');
+ List c = new List();
+ for (int i = 0; i < o.Length; i++)
+ {
+ CoockiesValue cv = new CoockiesValue();
+ io = o[i].IndexOf("=");
+ if (io > -1)
+ {
+ cv.Title = o[i].Substring(0, io).Trim();
+ cv.Value = o[i].Substring(io + 1, o[i].Length - io - 1).Trim();
+ }
+ else
+ {
+ if (!string.IsNullOrEmpty(o[i]))
+ cv.Title = o[i].Trim();
+ }
+ if (!string.IsNullOrEmpty(cv.Title))
+ c.Add(cv);
+ }
+ for (int i = 0; i < n.Length; i++)
+ {
+ CoockiesValue cv = new CoockiesValue();
+ io = o[i].IndexOf("=");
+ if (io > -1)
+ {
+ cv.Title = o[i].Substring(0, io).Trim();
+ cv.Value = o[i].Substring(io + 1, o[i].Length - io - 1).Trim();
+ }
+ else
+ {
+ if (!string.IsNullOrEmpty(o[i]))
+ cv.Title = o[i].Trim();
+ }
+ if (!string.IsNullOrEmpty(cv.Title))
+ {
+ bool isHad = false;
+ for (int j = 0; j < c.Count; j++)
+ {
+ if (cv.Title == c[j].Title)
+ {
+ c[j].Value = cv.Value;
+ isHad = true;
+ break;
+ }
+ }
+ if (!isHad)
+ c.Add(cv);
+ }
+ }
+ string temp = "";
+ for (int i = 0; i < c.Count; i++)
+ {
+ if (string.IsNullOrEmpty(c[i].Value))
+ temp += c[i].Title + "; ";
+ else
+ temp += c[i].Title + "=" + c[i].Value + "; ";
+ }
+ return temp;
+ }
+ ///
+ /// cookies值
+ ///
+ public class CoockiesValue
+ {
+ ///
+ /// 名称
+ ///
+ public string Title { get; set; }
+ ///
+ /// 值
+ ///
+ public string Value { get; set; }
+ }
+ ///
+ /// 模拟百度蜘蛛下载页面
+ ///
+ ///
+ ///
+ public static string ByBaidu(string url, string userAgent)
+ {
+ if (string.IsNullOrEmpty(url))
+ {
+ return "";
+ }
+ try
+ {
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
+ request.Method = "GET";
+ request.Accept = "*/*";
+ request.Headers.Add("Accept-Language", "zh-CN");
+ request.Headers.Add("Accept-Encoding", "gzip,deflate");
+ request.UserAgent = userAgent;
+ request.AllowAutoRedirect = false;
+ request.Timeout = 10000;
+ request.ReadWriteTimeout = 10000;
- request.Proxy = null;
- HttpWebResponse response = (HttpWebResponse)request.GetResponse();
- Stream receiveStream = response.GetResponseStream();
- MemoryStream ms = new MemoryStream();
- int num = 0;
- byte[] buffer = new byte[0x400];
- do
- {
- num = receiveStream.Read(buffer, 0, buffer.Length);
- if (num > 0)
- ms.Write(buffer, 0, num);
- }
- while (num > 0);
- byte[] b = ms.ToArray();
- ms.Close();
+ request.Proxy = null;
+ HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+ Stream receiveStream = response.GetResponseStream();
+ MemoryStream ms = new MemoryStream();
+ int num = 0;
+ byte[] buffer = new byte[0x400];
+ do
+ {
+ num = receiveStream.Read(buffer, 0, buffer.Length);
+ if (num > 0)
+ ms.Write(buffer, 0, num);
+ }
+ while (num > 0);
+ byte[] b = ms.ToArray();
+ ms.Close();
- b = ZipHelper.Decompress(b);
- string contentType = response.Headers["Content-Type"];
- string html = "";
- if (!string.IsNullOrEmpty(contentType))
- {
- string c = GetRegexString(contentType, "charset\\s*=\\s*(\\S+)").Trim();
- if (!string.IsNullOrEmpty(c))
- html = Encoding.GetEncoding(c).GetString(b);
- }
- if (string.IsNullOrEmpty(html))
- {
- html = Encoding.GetEncoding("UTF-8").GetString(b);
- string r = @"]*?charset=[""']*([\w-]+)[""']*";
- string c = GetRegexString(html.ToLower(), r);
- if (c.IndexOf("'") > -1)
- c = c.Substring(0, c.IndexOf("'"));
- if (c.IndexOf("\"") > -1)
- c = c.Substring(0, c.IndexOf("\""));
- if (c.IndexOf(" ") > -1)
- c = c.Substring(0, c.IndexOf(" "));
- if (c.IndexOf(">") > -1)
- c = c.Substring(0, c.IndexOf(">"));
- if (c.ToLower() != "utf-8" && !string.IsNullOrEmpty(c))
- html = Encoding.GetEncoding(c).GetString(b);
- else if (string.IsNullOrEmpty(c))
- html = Encoding.GetEncoding("gbk").GetString(b);
- }
- if (!string.IsNullOrEmpty(html))
- {
- if (html.Substring(0, 1) == "锘")
- html = Encoding.GetEncoding("UTF-8").GetString(b);
- //if (html.Contains("�") && (html.Length - html.Replace("�", "").Length > 3))
- // html = Encoding.GetEncoding("gbk").GetString(b);
- }
- return html;
- }
- catch (Exception e)
- {
- return e.Message;
- }
- }
- ///
- /// 返回单个正则分析结果
- ///
- ///
- ///
- ///
- public static string GetRegexString(string HtmlString, string RegexString)
- {
- MatchCollection mc = Regex.Matches(HtmlString, RegexString, RegexOptions.IgnoreCase);
- if (mc.Count > 0)
- return mc[0].Groups[1].ToString();
- return "";
- }
+ b = ZipHelper.Decompress(b);
+ string contentType = response.Headers["Content-Type"];
+ string html = "";
+ if (!string.IsNullOrEmpty(contentType))
+ {
+ string c = GetRegexString(contentType, "charset\\s*=\\s*(\\S+)").Trim();
+ if (!string.IsNullOrEmpty(c))
+ html = Encoding.GetEncoding(c).GetString(b);
+ }
+ if (string.IsNullOrEmpty(html))
+ {
+ html = Encoding.GetEncoding("UTF-8").GetString(b);
+ string r = @"]*?charset=[""']*([\w-]+)[""']*";
+ string c = GetRegexString(html.ToLower(), r);
+ if (c.IndexOf("'") > -1)
+ c = c.Substring(0, c.IndexOf("'"));
+ if (c.IndexOf("\"") > -1)
+ c = c.Substring(0, c.IndexOf("\""));
+ if (c.IndexOf(" ") > -1)
+ c = c.Substring(0, c.IndexOf(" "));
+ if (c.IndexOf(">") > -1)
+ c = c.Substring(0, c.IndexOf(">"));
+ if (c.ToLower() != "utf-8" && !string.IsNullOrEmpty(c))
+ html = Encoding.GetEncoding(c).GetString(b);
+ else if (string.IsNullOrEmpty(c))
+ html = Encoding.GetEncoding("gbk").GetString(b);
+ }
+ if (!string.IsNullOrEmpty(html))
+ {
+ if (html.Substring(0, 1) == "锘")
+ html = Encoding.GetEncoding("UTF-8").GetString(b);
+ //if (html.Contains("�") && (html.Length - html.Replace("�", "").Length > 3))
+ // html = Encoding.GetEncoding("gbk").GetString(b);
+ }
+ return html;
+ }
+ catch (Exception e)
+ {
+ return e.Message;
+ }
+ }
+ ///
+ /// 返回单个正则分析结果
+ ///
+ ///
+ ///
+ ///
+ public static string GetRegexString(string HtmlString, string RegexString)
+ {
+ MatchCollection mc = Regex.Matches(HtmlString, RegexString, RegexOptions.IgnoreCase);
+ if (mc.Count > 0)
+ return mc[0].Groups[1].ToString();
+ return "";
+ }
- ///
- /// Gbk 下载页面
- ///
- ///
- ///
- public static string Gbk(string url)
- {
- if (string.IsNullOrEmpty(url))
- return "";
- try
- {
- WebClientx web = new WebClientx();
- web.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
- web.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
- web.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)");
- web.Proxy = null;
- byte[] b = web.DownloadData(url);
- return Encoding.GetEncoding("gbk").GetString(b);
- }
- catch
- {
- return "";
- }
- }
- ///
- /// post 数据
- ///
- ///
- ///
- ///
- public static string PostUtf8(string url, StringBuilder postData)
- {
- try
- {
- WebClientx wc = new WebClientx();
- byte[] sendData = Encoding.GetEncoding("utf-8").GetBytes(postData.ToString());
- wc.Headers.Add("ContentLength", sendData.Length.ToString());
- wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
- wc.Proxy = null;
- return Encoding.UTF8.GetString(wc.UploadData(url, "POST", sendData));
- }
- catch
- {
- return "";
- }
- }
- ///
- /// post 数据
- ///
- ///
- ///
- ///
- public static string PostUtf8(string url, byte[] byteData, int time)
- {
- WebClientx webClient = new WebClientx();
- try
- {
- webClient.Timeout = time;
- webClient.Headers.Add("Accept-Encoding", "gzip,deflate");
- webClient.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
- webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)");
- webClient.Proxy = null;
- byte[] b = webClient.UploadData(url, byteData);
- string contentType = webClient.ResponseHeaders["Content-Type"];
- webClient.Dispose();
- webClient = null;
- string html = "";
- if (!string.IsNullOrEmpty(contentType))
- {
- string c = BaseRegex.GetMatchRegexString(contentType, "charset\\s*=\\s*(\\S+)");
- if (!string.IsNullOrEmpty(c))
- {
- c = c.Trim();
- html = Encoding.GetEncoding(c).GetString(b);
- }
- }
- if (string.IsNullOrEmpty(html))
- {
- html = Encoding.GetEncoding("UTF-8").GetString(b);
- string r = @"<\s*meta.+charset\s*=\s*[""']*(\S+)[""'\s>]*";
- string temp = BaseRegex.GetMatchRegexString(html.ToLower(), r);
- if (string.IsNullOrEmpty(temp))
- return html;
- string c = temp.Trim();
- if (c.IndexOf("'") > -1)
- c = c.Substring(0, c.IndexOf("'"));
- if (c.IndexOf("\"") > -1)
- c = c.Substring(0, c.IndexOf("\""));
- if (c.IndexOf(" ") > -1)
- c = c.Substring(0, c.IndexOf(" "));
- if (c.IndexOf(">") > -1)
- c = c.Substring(0, c.IndexOf(">"));
- if (!string.IsNullOrEmpty(c) && c.ToLower() != "utf-8")
- html = Encoding.GetEncoding(c).GetString(b);
- }
- return html;
- }
- catch
- {
- return "";
- }
- }
- ///
- /// 浏览器标识
- ///
- public static string UserAgent = @"Mozilla/5.0+(Windows+NT+10.0;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/57.0.2987.133+Safari/537.36
+ ///
+ /// Gbk 下载页面
+ ///
+ ///
+ ///
+ public static string Gbk(string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ return "";
+ try
+ {
+ WebClientx web = new WebClientx();
+ web.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+ web.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
+ web.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)");
+ web.Proxy = null;
+ byte[] b = web.DownloadData(url);
+ return Encoding.GetEncoding("gbk").GetString(b);
+ }
+ catch
+ {
+ return "";
+ }
+ }
+ ///
+ /// post 数据
+ ///
+ ///
+ ///
+ ///
+ public static string PostUtf8(string url, StringBuilder postData)
+ {
+ try
+ {
+ WebClientx wc = new WebClientx();
+ byte[] sendData = Encoding.GetEncoding("utf-8").GetBytes(postData.ToString());
+ wc.Headers.Add("ContentLength", sendData.Length.ToString());
+ wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
+ wc.Proxy = null;
+ return Encoding.UTF8.GetString(wc.UploadData(url, "POST", sendData));
+ }
+ catch
+ {
+ return "";
+ }
+ }
+ ///
+ /// post 数据
+ ///
+ ///
+ ///
+ ///
+ public static string PostUtf8(string url, byte[] byteData, int time)
+ {
+ WebClientx webClient = new WebClientx();
+ try
+ {
+ webClient.Timeout = time;
+ webClient.Headers.Add("Accept-Encoding", "gzip,deflate");
+ webClient.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
+ webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)");
+ webClient.Proxy = null;
+ byte[] b = webClient.UploadData(url, byteData);
+ string contentType = webClient.ResponseHeaders["Content-Type"];
+ webClient.Dispose();
+ webClient = null;
+ string html = "";
+ if (!string.IsNullOrEmpty(contentType))
+ {
+ string c = BaseRegex.GetMatchRegexString(contentType, "charset\\s*=\\s*(\\S+)");
+ if (!string.IsNullOrEmpty(c))
+ {
+ c = c.Trim();
+ html = Encoding.GetEncoding(c).GetString(b);
+ }
+ }
+ if (string.IsNullOrEmpty(html))
+ {
+ html = Encoding.GetEncoding("UTF-8").GetString(b);
+ string r = @"<\s*meta.+charset\s*=\s*[""']*(\S+)[""'\s>]*";
+ string temp = BaseRegex.GetMatchRegexString(html.ToLower(), r);
+ if (string.IsNullOrEmpty(temp))
+ return html;
+ string c = temp.Trim();
+ if (c.IndexOf("'") > -1)
+ c = c.Substring(0, c.IndexOf("'"));
+ if (c.IndexOf("\"") > -1)
+ c = c.Substring(0, c.IndexOf("\""));
+ if (c.IndexOf(" ") > -1)
+ c = c.Substring(0, c.IndexOf(" "));
+ if (c.IndexOf(">") > -1)
+ c = c.Substring(0, c.IndexOf(">"));
+ if (!string.IsNullOrEmpty(c) && c.ToLower() != "utf-8")
+ html = Encoding.GetEncoding(c).GetString(b);
+ }
+ return html;
+ }
+ catch
+ {
+ return "";
+ }
+ }
+ ///
+ /// 浏览器标识
+ ///
+ public static string UserAgent = @"Mozilla/5.0+(Windows+NT+10.0;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/57.0.2987.133+Safari/537.36
Mozilla/5.0+(Windows+NT+6.1)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/57.0.2987.133+Safari/537.36
Mozilla/5.0+(Windows+NT+10.0;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/54.0.2840.99+Safari/537.36
Mozilla/5.0+(Windows+NT+5.1)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/31.0.1650.63+Safari/537.36
@@ -1140,983 +1141,1039 @@ Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.1+(KHTML,+like+Gecko)+Chrome
Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.2372.400 QQBrowser/9.5.10548.400";
- ///
- /// post 数据
- ///
- ///
- ///
- ///
- public static string PostUtf8(string url, string postData, string contentType = "", int timeOut = -1)
- {
- HttpWebResponse response = null;
- string result;
- try
- {
- HttpWebRequest request;
- request = (HttpWebRequest)WebRequest.Create(url);
+ ///
+ /// post 数据
+ ///
+ ///
+ ///
+ ///
+ public static string PostUtf8(string url, string postData, string contentType = "", 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.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.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.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
- request.Headers.Set(HttpRequestHeader.AcceptLanguage, "zh-CN,zh;q=0.9");
+ request.KeepAlive = true;
+ request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
+ 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.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.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
+ request.Headers.Set(HttpRequestHeader.AcceptLanguage, "zh-CN,zh;q=0.9");
- request.Method = "POST";
- request.ServicePoint.Expect100Continue = false;
+ 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();
+ 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)request.GetResponse();
- }
- 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;
+ response = (HttpWebResponse)request.GetResponse();
+ }
+ 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;
- ////return PostUtf8(url, Encoding.UTF8.GetBytes(postData));
- ////bool isError = false;
- //string[] l = UserAgent.Split('\n');
- //try
- //{
- // string codeType = "utf-8";
- // HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
- // request.UserAgent = l[new Random(Guid.NewGuid().GetHashCode()).Next(l.Length)].Trim();
- // byte[] byteData = Encoding.GetEncoding(codeType).GetBytes(postData);
- // request.Method = "POST";
- // request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
- // if (timeOut == -1)
- // {
- // request.Timeout = BaseClass.TimeOut * 1000;
- // request.ReadWriteTimeout = BaseClass.TimeOut * 1000;
- // }
- // else
- // {
- // request.Timeout = timeOut * 1000;
- // request.ReadWriteTimeout = timeOut * 1000;
- // }
- // request.Proxy = null;
+ ////return PostUtf8(url, Encoding.UTF8.GetBytes(postData));
+ ////bool isError = false;
+ //string[] l = UserAgent.Split('\n');
+ //try
+ //{
+ // string codeType = "utf-8";
+ // HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
+ // request.UserAgent = l[new Random(Guid.NewGuid().GetHashCode()).Next(l.Length)].Trim();
+ // byte[] byteData = Encoding.GetEncoding(codeType).GetBytes(postData);
+ // request.Method = "POST";
+ // request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
+ // if (timeOut == -1)
+ // {
+ // request.Timeout = BaseClass.TimeOut * 1000;
+ // request.ReadWriteTimeout = BaseClass.TimeOut * 1000;
+ // }
+ // else
+ // {
+ // request.Timeout = timeOut * 1000;
+ // request.ReadWriteTimeout = timeOut * 1000;
+ // }
+ // request.Proxy = null;
- // request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
+ // request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
- // request.ContentType = "application/x-www-form-urlencoded; charset=" + codeType;
- // if (!string.IsNullOrEmpty(contentType))
- // {
- // request.ContentType = contentType;
- // }
- // request.ContentLength = byteData.Length;
- // request.Referer = url;
- // request.CookieContainer = new CookieContainer();
- // request.AllowAutoRedirect = false;
- // using (Stream requestStream = request.GetRequestStream())
- // {
- // requestStream.Write(byteData, 0, byteData.Length);
- // }
- // HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+ // request.ContentType = "application/x-www-form-urlencoded; charset=" + codeType;
+ // if (!string.IsNullOrEmpty(contentType))
+ // {
+ // request.ContentType = contentType;
+ // }
+ // request.ContentLength = byteData.Length;
+ // request.Referer = url;
+ // request.CookieContainer = new CookieContainer();
+ // request.AllowAutoRedirect = false;
+ // using (Stream requestStream = request.GetRequestStream())
+ // {
+ // requestStream.Write(byteData, 0, byteData.Length);
+ // }
+ // HttpWebResponse response = (HttpWebResponse)request.GetResponse();
- // Stream receiveStream = response.GetResponseStream();
- // StreamReader readStream = new StreamReader(receiveStream, Encoding.GetEncoding(codeType));
- // //string data = readStream.ReadToEnd().Trim();
- // //if (string.IsNullOrEmpty(data))
- // //{
- // // return "{\"code\": 400,\"data\": []}";
- // //}
- // //return data;
- // return ReadResponse(response);
- //}
- //catch (Exception e)
- //{
- // //LogSave.Add(url + "---------" + e.ToString());
- // //if (!isError)
- // //{
- // // isError = true;
- // // goto reTry;
- // //}
- // return "{\"code\": 400,\"msg\":\"" + e.Message + "\"}";
- //}
- }
- ///
- /// post 数据
- ///
- ///
- ///
- ///
- public static string PostUtf8(string url, byte[] byteData)
- {
- WebClientx webClient = new WebClientx();
- try
- {
- webClient.Timeout = 70;
- webClient.Headers.Add("Accept-Encoding", "gzip,deflate");
- webClient.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
- webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)");
- webClient.Proxy = null;
- byte[] b = webClient.UploadData(url, byteData);
- string contentType = webClient.ResponseHeaders["Content-Type"];
- webClient.Dispose();
- webClient = null;
- string html = "";
- if (!string.IsNullOrEmpty(contentType))
- {
- string c = BaseRegex.GetMatchRegexString(contentType, "charset\\s*=\\s*(\\S+)");
- if (!string.IsNullOrEmpty(c))
- {
- c = c.Trim();
- html = Encoding.GetEncoding(c).GetString(b);
- }
- }
- if (string.IsNullOrEmpty(html))
- {
- html = Encoding.GetEncoding("UTF-8").GetString(b);
- string r = @"<\s*meta.+charset\s*=\s*[""']*(\S+)[""'\s>]*";
- string temp = BaseRegex.GetMatchRegexString(html.ToLower(), r);
- if (string.IsNullOrEmpty(temp))
- return html;
- string c = temp.Trim();
- if (c.IndexOf("'") > -1)
- c = c.Substring(0, c.IndexOf("'"));
- if (c.IndexOf("\"") > -1)
- c = c.Substring(0, c.IndexOf("\""));
- if (c.IndexOf(" ") > -1)
- c = c.Substring(0, c.IndexOf(" "));
- if (c.IndexOf(">") > -1)
- c = c.Substring(0, c.IndexOf(">"));
- if (!string.IsNullOrEmpty(c) && c.ToLower() != "utf-8")
- html = Encoding.GetEncoding(c).GetString(b);
- }
- return html;
- }
- catch
- {
- return "";
- }
- }
+ // Stream receiveStream = response.GetResponseStream();
+ // StreamReader readStream = new StreamReader(receiveStream, Encoding.GetEncoding(codeType));
+ // //string data = readStream.ReadToEnd().Trim();
+ // //if (string.IsNullOrEmpty(data))
+ // //{
+ // // return "{\"code\": 400,\"data\": []}";
+ // //}
+ // //return data;
+ // return ReadResponse(response);
+ //}
+ //catch (Exception e)
+ //{
+ // //LogSave.Add(url + "---------" + e.ToString());
+ // //if (!isError)
+ // //{
+ // // isError = true;
+ // // goto reTry;
+ // //}
+ // return "{\"code\": 400,\"msg\":\"" + e.Message + "\"}";
+ //}
+ }
- ///
- /// post 数据
- ///
- ///
- ///
- ///
- public static string PostUtf8ForOplb(string url, string postData, string verifyAuthToken)
- {
- //return PostUtf8(url, Encoding.UTF8.GetBytes(postData));
+ public static async Task PostUtf8Async(string url, string postData, string contentType = "", int timeOut = -1)
+ {
+ HttpWebResponse response = null;
+ string result;
+ try
+ {
+ HttpWebRequest request;
+ request = (HttpWebRequest)WebRequest.Create(url);
- bool isError = false;
- string[] l = UserAgent.Split('\n');
- reTry:
- try
- {
- string codeType = "utf-8";
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
- request.UserAgent = l[new Random(Guid.NewGuid().GetHashCode()).Next(l.Length)].Trim();
- byte[] byteData = Encoding.GetEncoding(codeType).GetBytes(postData);
- request.Method = "POST";
- request.Headers.Add("X-PDD-VerifyAuthToken", verifyAuthToken);
- request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
- request.Timeout = BaseClass.TimeOut * 1000;
- request.ReadWriteTimeout = BaseClass.TimeOut * 1000;
- request.Proxy = null;
- request.ContentType = "application/x-www-form-urlencoded; charset=" + codeType;
- request.ContentLength = byteData.Length;
- request.Referer = url;
- request.CookieContainer = new CookieContainer();
- request.AllowAutoRedirect = false;
- using (Stream requestStream = request.GetRequestStream())
- {
- requestStream.Write(byteData, 0, byteData.Length);
- }
- HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+ request.KeepAlive = true;
+ request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
+ 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.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.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
+ request.Headers.Set(HttpRequestHeader.AcceptLanguage, "zh-CN,zh;q=0.9");
- Stream receiveStream = response.GetResponseStream();
- StreamReader readStream = new StreamReader(receiveStream, Encoding.GetEncoding(codeType));
- return readStream.ReadToEnd().Trim();
- }
- catch (Exception e)
- {
- if (!isError)
- {
- isError = true;
- goto reTry;
- }
- return "";
- }
+ 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();
- ///
- /// POST读取详细
- ///
- /// 提交地址
- /// 提交数据
- /// 代码
- ///
- public static string PostData(string strUrl, string data, string codeType)
- {
- try
- {
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strUrl);
- request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)";
- byte[] byteData = Encoding.GetEncoding(codeType).GetBytes(data);
- request.Method = "POST";
- request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
- request.Timeout = 10000;
- request.ReadWriteTimeout = 10000;
- request.ContentType = "application/x-www-form-urlencoded; charset=" + codeType;
- request.ContentLength = byteData.Length;
- request.Referer = strUrl;
- request.Proxy = null;
- request.CookieContainer = new CookieContainer();
- request.AllowAutoRedirect = false;
- using (Stream requestStream = request.GetRequestStream())
- {
- requestStream.Write(byteData, 0, byteData.Length);
- }
- HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+ 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;
- Stream receiveStream = response.GetResponseStream();
- StreamReader readStream = new StreamReader(receiveStream, Encoding.GetEncoding(codeType));
- return readStream.ReadToEnd();
- }
- catch
- {
- return "";
- }
- }
+ }
+ ///
+ /// post 数据
+ ///
+ ///
+ ///
+ ///
+ public static string PostUtf8(string url, byte[] byteData)
+ {
+ WebClientx webClient = new WebClientx();
+ try
+ {
+ webClient.Timeout = 70;
+ webClient.Headers.Add("Accept-Encoding", "gzip,deflate");
+ webClient.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
+ webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)");
+ webClient.Proxy = null;
+ byte[] b = webClient.UploadData(url, byteData);
+ string contentType = webClient.ResponseHeaders["Content-Type"];
+ webClient.Dispose();
+ webClient = null;
+ string html = "";
+ if (!string.IsNullOrEmpty(contentType))
+ {
+ string c = BaseRegex.GetMatchRegexString(contentType, "charset\\s*=\\s*(\\S+)");
+ if (!string.IsNullOrEmpty(c))
+ {
+ c = c.Trim();
+ html = Encoding.GetEncoding(c).GetString(b);
+ }
+ }
+ if (string.IsNullOrEmpty(html))
+ {
+ html = Encoding.GetEncoding("UTF-8").GetString(b);
+ string r = @"<\s*meta.+charset\s*=\s*[""']*(\S+)[""'\s>]*";
+ string temp = BaseRegex.GetMatchRegexString(html.ToLower(), r);
+ if (string.IsNullOrEmpty(temp))
+ return html;
+ string c = temp.Trim();
+ if (c.IndexOf("'") > -1)
+ c = c.Substring(0, c.IndexOf("'"));
+ if (c.IndexOf("\"") > -1)
+ c = c.Substring(0, c.IndexOf("\""));
+ if (c.IndexOf(" ") > -1)
+ c = c.Substring(0, c.IndexOf(" "));
+ if (c.IndexOf(">") > -1)
+ c = c.Substring(0, c.IndexOf(">"));
+ if (!string.IsNullOrEmpty(c) && c.ToLower() != "utf-8")
+ html = Encoding.GetEncoding(c).GetString(b);
+ }
+ return html;
+ }
+ catch
+ {
+ return "";
+ }
+ }
- ///
- /// POST读取详细
- ///
- /// 提交地址
- /// 提交数据
- /// 浏览器头
- ///
- public static string GetUtf8(string strUrl, string userAgen)
- {
- try
- {
- WebClientx web = new WebClientx();
- web.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
- web.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
- web.Headers.Add("User-Agent", userAgen);
- web.Proxy = null;
- byte[] b = web.DownloadData(strUrl);
- return Encoding.UTF8.GetString(b);
- }
- catch
- {
- return "";
- }
- }
+ ///
+ /// post 数据
+ ///
+ ///
+ ///
+ ///
+ public static string PostUtf8ForOplb(string url, string postData, string verifyAuthToken)
+ {
+ //return PostUtf8(url, Encoding.UTF8.GetBytes(postData));
- ///
- /// URL GB2312转码
- ///
- ///
- ///
- public static string UrlEncodeGb2312(string IndexKey)
- {
- if (string.IsNullOrEmpty(IndexKey))
- return "";
- return HttpUtility.UrlEncode(IndexKey, Encoding.GetEncoding("GB2312"));
+ bool isError = false;
+ string[] l = UserAgent.Split('\n');
+ reTry:
+ try
+ {
+ string codeType = "utf-8";
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
+ request.UserAgent = l[new Random(Guid.NewGuid().GetHashCode()).Next(l.Length)].Trim();
+ byte[] byteData = Encoding.GetEncoding(codeType).GetBytes(postData);
+ request.Method = "POST";
+ request.Headers.Add("X-PDD-VerifyAuthToken", verifyAuthToken);
+ request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
+ request.Timeout = BaseClass.TimeOut * 1000;
+ request.ReadWriteTimeout = BaseClass.TimeOut * 1000;
+ request.Proxy = null;
+ request.ContentType = "application/x-www-form-urlencoded; charset=" + codeType;
+ request.ContentLength = byteData.Length;
+ request.Referer = url;
+ request.CookieContainer = new CookieContainer();
+ request.AllowAutoRedirect = false;
+ using (Stream requestStream = request.GetRequestStream())
+ {
+ requestStream.Write(byteData, 0, byteData.Length);
+ }
+ HttpWebResponse response = (HttpWebResponse)request.GetResponse();
- byte[] sarr = Encoding.GetEncoding("gb2312").GetBytes(IndexKey);
- IndexKey = "";
- for (int i = 0; i < sarr.Length; i++)
- {
- IndexKey += "%";
- IndexKey += sarr[i].ToString("X2");
- }
- return IndexKey;
- }
- ///
- /// URL UTF-8转码
- ///
- ///
- ///
- public static string UrlEncodeUtf8(string IndexKey)
- {
- if (string.IsNullOrEmpty(IndexKey))
- return "";
- return HttpUtility.UrlEncode(IndexKey, Encoding.UTF8);
- byte[] sarr = System.Text.Encoding.UTF8.GetBytes(IndexKey);
- IndexKey = "";
- for (int i = 0; i < sarr.Length; i++)
- {
- IndexKey += "%";
- IndexKey += sarr[i].ToString("X2");
- }
- return IndexKey;
- }
- ///
- /// 用IE打开网址
- ///
- ///
- public static void OpenUrl(string url)
- {
- try
- {
- //if (url.Contains("http"))
- // Process.Start("iexplore.exe", url);
- //else
- Process.Start(url);
- }
- catch
- {
- }
- }
+ Stream receiveStream = response.GetResponseStream();
+ StreamReader readStream = new StreamReader(receiveStream, Encoding.GetEncoding(codeType));
+ return readStream.ReadToEnd().Trim();
+ }
+ catch (Exception e)
+ {
+ if (!isError)
+ {
+ isError = true;
+ goto reTry;
+ }
+ return "";
+ }
- ///
- /// 下载文件
- ///
- /// 下载地址
- /// 保存目录
- ///
- public static bool DownloadFile(string Urlstring, string FilePath)
- {
- try
- {
- WebClientx mywebclient = new WebClientx();
- mywebclient.Proxy = null;
- if (File.Exists(FilePath))
- File.Delete(FilePath);
- mywebclient.DownloadFile(Urlstring, FilePath);
- return true;
- }
- catch
- {
- return false;
- }
- }
- ///
- /// 下载文件
- ///
- /// 下载地址
- /// 保存目录
- ///
- public static bool DownloadFile(string Urlstring, out byte[] b)
- {
- b = new byte[0];
- int times = 0;
- Next:
- try
- {
- WebClientx mywebclient = new WebClientx();
- b = mywebclient.DownloadData(Urlstring);
- return true;
- }
- catch
- {
- if (times < 4)
- {
- times++;
- Thread.Sleep(3000);
- goto Next;
- }
- return false;
- }
- }
+ }
+
+ ///
+ /// POST读取详细
+ ///
+ /// 提交地址
+ /// 提交数据
+ /// 代码
+ ///
+ public static string PostData(string strUrl, string data, string codeType)
+ {
+ try
+ {
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strUrl);
+ request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)";
+ byte[] byteData = Encoding.GetEncoding(codeType).GetBytes(data);
+ request.Method = "POST";
+ request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
+ request.Timeout = 10000;
+ request.ReadWriteTimeout = 10000;
+ request.ContentType = "application/x-www-form-urlencoded; charset=" + codeType;
+ request.ContentLength = byteData.Length;
+ request.Referer = strUrl;
+ request.Proxy = null;
+ request.CookieContainer = new CookieContainer();
+ request.AllowAutoRedirect = false;
+ using (Stream requestStream = request.GetRequestStream())
+ {
+ requestStream.Write(byteData, 0, byteData.Length);
+ }
+ HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+
+ Stream receiveStream = response.GetResponseStream();
+ StreamReader readStream = new StreamReader(receiveStream, Encoding.GetEncoding(codeType));
+ return readStream.ReadToEnd();
+ }
+ catch
+ {
+ return "";
+ }
+ }
+
+ ///
+ /// POST读取详细
+ ///
+ /// 提交地址
+ /// 提交数据
+ /// 浏览器头
+ ///
+ public static string GetUtf8(string strUrl, string userAgen)
+ {
+ try
+ {
+ WebClientx web = new WebClientx();
+ web.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+ web.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
+ web.Headers.Add("User-Agent", userAgen);
+ web.Proxy = null;
+ byte[] b = web.DownloadData(strUrl);
+ return Encoding.UTF8.GetString(b);
+ }
+ catch
+ {
+ return "";
+ }
+ }
+
+ ///
+ /// URL GB2312转码
+ ///
+ ///
+ ///
+ public static string UrlEncodeGb2312(string IndexKey)
+ {
+ if (string.IsNullOrEmpty(IndexKey))
+ return "";
+ return HttpUtility.UrlEncode(IndexKey, Encoding.GetEncoding("GB2312"));
+
+ byte[] sarr = Encoding.GetEncoding("gb2312").GetBytes(IndexKey);
+ IndexKey = "";
+ for (int i = 0; i < sarr.Length; i++)
+ {
+ IndexKey += "%";
+ IndexKey += sarr[i].ToString("X2");
+ }
+ return IndexKey;
+ }
+ ///
+ /// URL UTF-8转码
+ ///
+ ///
+ ///
+ public static string UrlEncodeUtf8(string IndexKey)
+ {
+ if (string.IsNullOrEmpty(IndexKey))
+ return "";
+ return HttpUtility.UrlEncode(IndexKey, Encoding.UTF8);
+ byte[] sarr = System.Text.Encoding.UTF8.GetBytes(IndexKey);
+ IndexKey = "";
+ for (int i = 0; i < sarr.Length; i++)
+ {
+ IndexKey += "%";
+ IndexKey += sarr[i].ToString("X2");
+ }
+ return IndexKey;
+ }
+ ///
+ /// 用IE打开网址
+ ///
+ ///
+ public static void OpenUrl(string url)
+ {
+ try
+ {
+ //if (url.Contains("http"))
+ // Process.Start("iexplore.exe", url);
+ //else
+ Process.Start(url);
+ }
+ catch
+ {
+ }
+ }
+
+ ///
+ /// 下载文件
+ ///
+ /// 下载地址
+ /// 保存目录
+ ///
+ public static bool DownloadFile(string Urlstring, string FilePath)
+ {
+ try
+ {
+ WebClientx mywebclient = new WebClientx();
+ mywebclient.Proxy = null;
+ if (File.Exists(FilePath))
+ File.Delete(FilePath);
+ mywebclient.DownloadFile(Urlstring, FilePath);
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ ///
+ /// 下载文件
+ ///
+ /// 下载地址
+ /// 保存目录
+ ///
+ public static bool DownloadFile(string Urlstring, out byte[] b)
+ {
+ b = new byte[0];
+ int times = 0;
+ Next:
+ try
+ {
+ WebClientx mywebclient = new WebClientx();
+ b = mywebclient.DownloadData(Urlstring);
+ return true;
+ }
+ catch
+ {
+ if (times < 4)
+ {
+ times++;
+ Thread.Sleep(3000);
+ goto Next;
+ }
+ return false;
+ }
+ }
- ///
- /// 读取网址,兼容https,兼容任意编码
- ///
- ///
- ///
- public static string GetUrl(string url)
- {
- WebClientx webClient = new WebClientx();
- try
- {
- webClient.Timeout = 30;
- webClient.Headers.Add("Accept-Encoding", "gzip,deflate");
- webClient.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
- webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)");
- webClient.Proxy = null;
- byte[] b = webClient.DownloadData(url);
- b = ZipHelper.Decompress(b);
- string contentType = webClient.ResponseHeaders["Content-Type"];
- webClient.Dispose();
- webClient = null;
- string html = "";
- if (!string.IsNullOrEmpty(contentType))
- {
- string c = BaseRegex.GetMatchRegexString(contentType, "charset\\s*=\\s*(\\S+)");
- if (!string.IsNullOrEmpty(c))
- {
- c = c.Trim();
- html = Encoding.GetEncoding(c).GetString(b);
- }
- }
- if (string.IsNullOrEmpty(html))
- {
- html = Encoding.GetEncoding("UTF-8").GetString(b);
- string r = @"<\s*meta.+charset\s*=\s*[""']*(\S+)[""'\s>]*";
- string c = BaseRegex.GetMatchRegexString(html.ToLower(), r).Trim();
- if (c.IndexOf("'") > -1)
- c = c.Substring(0, c.IndexOf("'"));
- if (c.IndexOf("\"") > -1)
- c = c.Substring(0, c.IndexOf("\""));
- if (c.IndexOf(" ") > -1)
- c = c.Substring(0, c.IndexOf(" "));
- if (c.IndexOf(">") > -1)
- c = c.Substring(0, c.IndexOf(">"));
- if (!string.IsNullOrEmpty(c) && c.ToLower() != "utf-8")
- html = Encoding.GetEncoding(c).GetString(b);
- }
- return html;
- }
- catch (Exception e)
- {
- LogSave.AddView(url + " 错误:" + e.Message.Replace("\r\n", " "));
- return null;
- }
- finally
- {
- try
- {
- webClient.Dispose();
- webClient = null;
- }
- catch
- {
- }
- }
- }
+ ///
+ /// 读取网址,兼容https,兼容任意编码
+ ///
+ ///
+ ///
+ public static string GetUrl(string url)
+ {
+ WebClientx webClient = new WebClientx();
+ try
+ {
+ webClient.Timeout = 30;
+ webClient.Headers.Add("Accept-Encoding", "gzip,deflate");
+ webClient.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
+ webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)");
+ webClient.Proxy = null;
+ byte[] b = webClient.DownloadData(url);
+ b = ZipHelper.Decompress(b);
+ string contentType = webClient.ResponseHeaders["Content-Type"];
+ webClient.Dispose();
+ webClient = null;
+ string html = "";
+ if (!string.IsNullOrEmpty(contentType))
+ {
+ string c = BaseRegex.GetMatchRegexString(contentType, "charset\\s*=\\s*(\\S+)");
+ if (!string.IsNullOrEmpty(c))
+ {
+ c = c.Trim();
+ html = Encoding.GetEncoding(c).GetString(b);
+ }
+ }
+ if (string.IsNullOrEmpty(html))
+ {
+ html = Encoding.GetEncoding("UTF-8").GetString(b);
+ string r = @"<\s*meta.+charset\s*=\s*[""']*(\S+)[""'\s>]*";
+ string c = BaseRegex.GetMatchRegexString(html.ToLower(), r).Trim();
+ if (c.IndexOf("'") > -1)
+ c = c.Substring(0, c.IndexOf("'"));
+ if (c.IndexOf("\"") > -1)
+ c = c.Substring(0, c.IndexOf("\""));
+ if (c.IndexOf(" ") > -1)
+ c = c.Substring(0, c.IndexOf(" "));
+ if (c.IndexOf(">") > -1)
+ c = c.Substring(0, c.IndexOf(">"));
+ if (!string.IsNullOrEmpty(c) && c.ToLower() != "utf-8")
+ html = Encoding.GetEncoding(c).GetString(b);
+ }
+ return html;
+ }
+ catch (Exception e)
+ {
+ LogSave.AddView(url + " 错误:" + e.Message.Replace("\r\n", " "));
+ return null;
+ }
+ finally
+ {
+ try
+ {
+ webClient.Dispose();
+ webClient = null;
+ }
+ catch
+ {
+ }
+ }
+ }
- ///
- /// 获取域名
- ///
- ///
- ///
- public static string GetDomain(string url)
- {
- try
- {
- url = url.ToLower();
- string temp = BaseRegex.GetMatchRegexString(url, @"([a-z0-9-\.]+\.[a-z]{2,8})");
- if (!string.IsNullOrEmpty(temp) && temp.Length > 1 && (temp.Substring(0, 1) == "." || temp.Substring(0, 1) == "-"))
- return null;
- if (!string.IsNullOrEmpty(temp))
- return temp;
- if (url.Contains("//") && url.IndexOf("//") + 2 < url.Length)
- url = url.Substring(url.IndexOf("//") + 2, url.Length - url.IndexOf("//") - 2);
- if (url.Contains("/") && url.IndexOf("/") > 0)
- url = url.Substring(0, url.IndexOf("/"));
- return url;
- }
- catch
- {
- return null;
- }
- }
+ ///
+ /// 获取域名
+ ///
+ ///
+ ///
+ public static string GetDomain(string url)
+ {
+ try
+ {
+ url = url.ToLower();
+ string temp = BaseRegex.GetMatchRegexString(url, @"([a-z0-9-\.]+\.[a-z]{2,8})");
+ if (!string.IsNullOrEmpty(temp) && temp.Length > 1 && (temp.Substring(0, 1) == "." || temp.Substring(0, 1) == "-"))
+ return null;
+ if (!string.IsNullOrEmpty(temp))
+ return temp;
+ if (url.Contains("//") && url.IndexOf("//") + 2 < url.Length)
+ url = url.Substring(url.IndexOf("//") + 2, url.Length - url.IndexOf("//") - 2);
+ if (url.Contains("/") && url.IndexOf("/") > 0)
+ url = url.Substring(0, url.IndexOf("/"));
+ return url;
+ }
+ catch
+ {
+ return null;
+ }
+ }
- ///
- /// 获取域名&ip
- ///
- ///
- ///
- public static string GetDomainIp(string url)
- {
- if (string.IsNullOrEmpty(url))
- return null;
- url = url.ToLower();
- string temp = BaseRegex.GetMatchRegexString(url, @"http[s]{0,1}://([a-z0-9-\.]+\.[a-z]{2,8}|[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3})");
- if (!string.IsNullOrEmpty(temp) && temp.Length > 1 && (temp.Substring(0, 1) == "." || temp.Substring(0, 1) == "-"))
- return null;
- if (!string.IsNullOrEmpty(temp))
- return temp;
- return null;
- }
+ ///
+ /// 获取域名&ip
+ ///
+ ///
+ ///
+ public static string GetDomainIp(string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ return null;
+ url = url.ToLower();
+ string temp = BaseRegex.GetMatchRegexString(url, @"http[s]{0,1}://([a-z0-9-\.]+\.[a-z]{2,8}|[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3})");
+ if (!string.IsNullOrEmpty(temp) && temp.Length > 1 && (temp.Substring(0, 1) == "." || temp.Substring(0, 1) == "-"))
+ return null;
+ if (!string.IsNullOrEmpty(temp))
+ return temp;
+ return null;
+ }
- ///
- /// 解析域名ip
- ///
- ///
- ///
- public static string GetIp(string domain)
- {
- try
- {
- for (int i = 0; i < 2; i++)
- {
- IPAddress[] aryIP = Dns.GetHostEntry(domain).AddressList;
- if (aryIP.Length > 0)
- return aryIP[0].ToString();
- Thread.Sleep(1000); //重试,防止DNS缓存
- }
- return null;
- }
- catch
- {
- //SocketServer.ViewCode += "域名:" + domain + "无法解析\r\n";
- return null;
- }
- }
- ///
- /// 是否是域名
- ///
- ///
- ///
- public static bool IsDomain(string domain)
- {
- string temp = BaseRegex.GetMatchRegexString(domain, @"([a-z0-9-\.]+\.[a-z]{2,8})");
- if (!string.IsNullOrEmpty(temp) && temp.Length > 1 && (temp.Substring(0, 1) == "." || temp.Substring(0, 1) == "-"))
- return false;
- if (temp == domain)
- return true;
- return false;
- }
+ ///
+ /// 解析域名ip
+ ///
+ ///
+ ///
+ public static string GetIp(string domain)
+ {
+ try
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ IPAddress[] aryIP = Dns.GetHostEntry(domain).AddressList;
+ if (aryIP.Length > 0)
+ return aryIP[0].ToString();
+ Thread.Sleep(1000); //重试,防止DNS缓存
+ }
+ return null;
+ }
+ catch
+ {
+ //SocketServer.ViewCode += "域名:" + domain + "无法解析\r\n";
+ return null;
+ }
+ }
+ ///
+ /// 是否是域名
+ ///
+ ///
+ ///
+ public static bool IsDomain(string domain)
+ {
+ string temp = BaseRegex.GetMatchRegexString(domain, @"([a-z0-9-\.]+\.[a-z]{2,8})");
+ if (!string.IsNullOrEmpty(temp) && temp.Length > 1 && (temp.Substring(0, 1) == "." || temp.Substring(0, 1) == "-"))
+ return false;
+ if (temp == domain)
+ return true;
+ return false;
+ }
- ///
- /// 获取顶级域名
- ///
- ///
- ///
- public static string GetMainDomain(string domain)
- {
- if (string.IsNullOrEmpty(domain))
- return "";
- domain = domain.ToLower();
- if (!domain.Contains(".") || domain.Length < 4)
- return "";
- string[] d = domain.Split('.');
- string main = d[d.Length - 2] + "." + d[d.Length - 1]; //原始域名
- if (d.Length > 2 &&
- (d[d.Length - 2] == "com" || d[d.Length - 2] == "net" || d[d.Length - 2] == "org" ||
- d[d.Length - 2] == "gov" || d[d.Length - 2] == "edu" || d[d.Length - 2] == "co"))
- main = d[d.Length - 3] + "." + main;
- return main;
- }
- ///
- /// 解密Jsion
- ///
- ///
- ///
- public static string Decode(string s)
- {
- s = WebUtility.HtmlDecode(s);
+ ///
+ /// 获取顶级域名
+ ///
+ ///
+ ///
+ public static string GetMainDomain(string domain)
+ {
+ if (string.IsNullOrEmpty(domain))
+ return "";
+ domain = domain.ToLower();
+ if (!domain.Contains(".") || domain.Length < 4)
+ return "";
+ string[] d = domain.Split('.');
+ string main = d[d.Length - 2] + "." + d[d.Length - 1]; //原始域名
+ if (d.Length > 2 &&
+ (d[d.Length - 2] == "com" || d[d.Length - 2] == "net" || d[d.Length - 2] == "org" ||
+ d[d.Length - 2] == "gov" || d[d.Length - 2] == "edu" || d[d.Length - 2] == "co"))
+ main = d[d.Length - 3] + "." + main;
+ return main;
+ }
+ ///
+ /// 解密Jsion
+ ///
+ ///
+ ///
+ public static string Decode(string s)
+ {
+ s = WebUtility.HtmlDecode(s);
- Regex reUnicode = new Regex(@"\\u([0-9a-fA-F]{4})", RegexOptions.Compiled);
- return reUnicode.Replace(s, m =>
- {
- short c;
- if (short.TryParse(m.Groups[1].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out c))
- {
- return "" + (char)c;
- }
- return m.Value;
- });
- }
+ Regex reUnicode = new Regex(@"\\u([0-9a-fA-F]{4})", RegexOptions.Compiled);
+ return reUnicode.Replace(s, m =>
+ {
+ short c;
+ if (short.TryParse(m.Groups[1].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out c))
+ {
+ return "" + (char)c;
+ }
+ return m.Value;
+ });
+ }
- #region 解码
- ///
- /// 解码
- ///
- ///
- ///
- public static string DecodeString(string code)
- {
- try
- {
- string code1 =
- code.Trim().Replace("_1/", "c")
- .Replace("_2/", "Y")
- .Replace("_3/", "A")
- .Replace("_4/", "Z")
- .Replace("_5/", "h")
- .Replace("_6/", "n")
- .Replace("_7/", "I")
- .Replace("_8/", "l")
- .Replace("_9/", "t")
- .Replace("_10/", "e")
- .Replace("_11/", "K")
- .Replace("_12/", "r")
- .Replace("_13/", "o")
- .Replace("_14/", "q")
- .Replace("_15/", "W")
- .Replace("_16/", "+")
- .Replace("_17/", "H")
- .Replace("_18/", "m")
- .Replace("_19/", "F")
- .Replace("_20/", "x")
- .Replace("_21/", "v")
- .Replace("_22/", "B")
- .Replace("_23/", "=")
- .Replace("\0_0/", "_");
- byte[] inArray = Convert.FromBase64String(code1);
- string html = Encoding.UTF8.GetString(inArray);
- //html =
- // html.Replace("_1_", "=")
- // .Replace("_2_", "?")
- // .Replace("_3_", "/")
- // .Replace("_4_", ".")
- // .Replace("_5_", "&")
- // .Replace("_6_", "<")
- // .Replace("_7_", ">")
- // .Replace("_8_", "'")
- // .Replace("_9_", "\"")
- // .Replace("0_0", "_");
- //html = html.Replace("_9=4_00", "\"1.00").Replace("_9?4_00", "\"1.00").Replace("_9/4_00", "\"1.00");
- return html;
- }
- catch (Exception e)
- {
- //LogSave.Add("解码数据错误:" + code);
- return "解码数据错误:" + e.Message;
- }
- }
- #endregion
+ #region 解码
+ ///
+ /// 解码
+ ///
+ ///
+ ///
+ public static string DecodeString(string code)
+ {
+ try
+ {
+ string code1 =
+ code.Trim().Replace("_1/", "c")
+ .Replace("_2/", "Y")
+ .Replace("_3/", "A")
+ .Replace("_4/", "Z")
+ .Replace("_5/", "h")
+ .Replace("_6/", "n")
+ .Replace("_7/", "I")
+ .Replace("_8/", "l")
+ .Replace("_9/", "t")
+ .Replace("_10/", "e")
+ .Replace("_11/", "K")
+ .Replace("_12/", "r")
+ .Replace("_13/", "o")
+ .Replace("_14/", "q")
+ .Replace("_15/", "W")
+ .Replace("_16/", "+")
+ .Replace("_17/", "H")
+ .Replace("_18/", "m")
+ .Replace("_19/", "F")
+ .Replace("_20/", "x")
+ .Replace("_21/", "v")
+ .Replace("_22/", "B")
+ .Replace("_23/", "=")
+ .Replace("\0_0/", "_");
+ byte[] inArray = Convert.FromBase64String(code1);
+ string html = Encoding.UTF8.GetString(inArray);
+ //html =
+ // html.Replace("_1_", "=")
+ // .Replace("_2_", "?")
+ // .Replace("_3_", "/")
+ // .Replace("_4_", ".")
+ // .Replace("_5_", "&")
+ // .Replace("_6_", "<")
+ // .Replace("_7_", ">")
+ // .Replace("_8_", "'")
+ // .Replace("_9_", "\"")
+ // .Replace("0_0", "_");
+ //html = html.Replace("_9=4_00", "\"1.00").Replace("_9?4_00", "\"1.00").Replace("_9/4_00", "\"1.00");
+ return html;
+ }
+ catch (Exception e)
+ {
+ //LogSave.Add("解码数据错误:" + code);
+ return "解码数据错误:" + e.Message;
+ }
+ }
+ #endregion
- ///
- /// 获取国内IP
- ///
- ///
- public static string ProxyIpIn()
- {
- if (BaseClass.ProxyIn.Count == 0)
- return "";
- Random ra = new Random(Guid.NewGuid().GetHashCode());
- return BaseClass.ProxyIn[ra.Next(BaseClass.ProxyIn.Count)];
- }
- ///
- /// 获取美国IP
- ///
- ///
- public static string ProxyIpOut()
- {
- if (BaseClass.ProxyOut.Count == 0)
- return "";
- Random ra = new Random(Guid.NewGuid().GetHashCode());
- return BaseClass.ProxyOut[ra.Next(BaseClass.ProxyOut.Count)];
- }
- ///
- /// 获取国内IP代理URL地址
- ///
- ///
- public static string ProxyIpInUrl(string url)
- {
- if (BaseClass.ProxyIn.Count == 0)
- return url;
- Random ra = new Random(Guid.NewGuid().GetHashCode());
- string ip = BaseClass.ProxyIn[ra.Next(BaseClass.ProxyIn.Count)];
- return "http://" + ip + ":6000/url=" + ReplaceUrl(url);
- }
- ///
- /// 获取美国IP代理URL地址
- ///
- ///
- public static string ProxyIpOutUrl(string url)
- {
- if (BaseClass.ProxyOut.Count == 0)
- return url;
- Random ra = new Random(Guid.NewGuid().GetHashCode());
- string ip = BaseClass.ProxyOut[ra.Next(BaseClass.ProxyOut.Count)];
- return "http://" + ip + ":6000/url=" + ReplaceUrl(url);
- }
- ///
- /// 替换链接,防止防火墙
- ///
- ///
- ///
- public static string ReplaceUrl(string url)
- {
- if (string.IsNullOrEmpty(url))
- return "";
- string newurl = "";
- string[] l = url.Split('.');
- for (int i = 0; i < l.Length; i++)
- {
- if (l[i].Length > 2)
- newurl += l[i].Substring(0, l[i].Length - 2) + "***ooo***" + l[i].Substring(l[i].Length - 2, 2);
- else
- newurl += l[i];
- if (i < l.Length - 1)
- newurl += ".";
- }
- return newurl.Replace(".google.", ".goo00gle.").Replace("?", "%3f").Replace("=", "%3d").Replace("&", "%26");
- }
- ///
- /// 还原链接
- ///
- ///
- ///
- public static string ReplaceUrlBak(string url)
- {
- if (string.IsNullOrEmpty(url))
- return "";
- string newurl = url.Replace("***ooo***", "");
- if (string.IsNullOrEmpty(newurl))
- return "";
- return newurl.Replace(".goo00gle.", ".google.").Replace("%3f", "?").Replace("%3d", "=").Replace("%26", "&");
- }
- ///
- /// 生成URL绝对地址
- ///
- /// 新URL
- /// 源地址
- ///
- public static string BuildUrl(string url, string oldurl)
- {
- if (string.IsNullOrEmpty(url))
- return oldurl;
- if (url.Contains("tencent:/"))
- return url;
- if (url.Length > 8 && url.Substring(0, 8).Contains("://"))
- {
- if (url.Length - url.Replace("/", "").Length == 2)
- url += "/";
- return url;
- }
+ ///
+ /// 获取国内IP
+ ///
+ ///
+ public static string ProxyIpIn()
+ {
+ if (BaseClass.ProxyIn.Count == 0)
+ return "";
+ Random ra = new Random(Guid.NewGuid().GetHashCode());
+ return BaseClass.ProxyIn[ra.Next(BaseClass.ProxyIn.Count)];
+ }
+ ///
+ /// 获取美国IP
+ ///
+ ///
+ public static string ProxyIpOut()
+ {
+ if (BaseClass.ProxyOut.Count == 0)
+ return "";
+ Random ra = new Random(Guid.NewGuid().GetHashCode());
+ return BaseClass.ProxyOut[ra.Next(BaseClass.ProxyOut.Count)];
+ }
+ ///
+ /// 获取国内IP代理URL地址
+ ///
+ ///
+ public static string ProxyIpInUrl(string url)
+ {
+ if (BaseClass.ProxyIn.Count == 0)
+ return url;
+ Random ra = new Random(Guid.NewGuid().GetHashCode());
+ string ip = BaseClass.ProxyIn[ra.Next(BaseClass.ProxyIn.Count)];
+ return "http://" + ip + ":6000/url=" + ReplaceUrl(url);
+ }
+ ///
+ /// 获取美国IP代理URL地址
+ ///
+ ///
+ public static string ProxyIpOutUrl(string url)
+ {
+ if (BaseClass.ProxyOut.Count == 0)
+ return url;
+ Random ra = new Random(Guid.NewGuid().GetHashCode());
+ string ip = BaseClass.ProxyOut[ra.Next(BaseClass.ProxyOut.Count)];
+ return "http://" + ip + ":6000/url=" + ReplaceUrl(url);
+ }
+ ///
+ /// 替换链接,防止防火墙
+ ///
+ ///
+ ///
+ public static string ReplaceUrl(string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ return "";
+ string newurl = "";
+ string[] l = url.Split('.');
+ for (int i = 0; i < l.Length; i++)
+ {
+ if (l[i].Length > 2)
+ newurl += l[i].Substring(0, l[i].Length - 2) + "***ooo***" + l[i].Substring(l[i].Length - 2, 2);
+ else
+ newurl += l[i];
+ if (i < l.Length - 1)
+ newurl += ".";
+ }
+ return newurl.Replace(".google.", ".goo00gle.").Replace("?", "%3f").Replace("=", "%3d").Replace("&", "%26");
+ }
+ ///
+ /// 还原链接
+ ///
+ ///
+ ///
+ public static string ReplaceUrlBak(string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ return "";
+ string newurl = url.Replace("***ooo***", "");
+ if (string.IsNullOrEmpty(newurl))
+ return "";
+ return newurl.Replace(".goo00gle.", ".google.").Replace("%3f", "?").Replace("%3d", "=").Replace("%26", "&");
+ }
+ ///
+ /// 生成URL绝对地址
+ ///
+ /// 新URL
+ /// 源地址
+ ///
+ public static string BuildUrl(string url, string oldurl)
+ {
+ if (string.IsNullOrEmpty(url))
+ return oldurl;
+ if (url.Contains("tencent:/"))
+ return url;
+ if (url.Length > 8 && url.Substring(0, 8).Contains("://"))
+ {
+ if (url.Length - url.Replace("/", "").Length == 2)
+ url += "/";
+ return url;
+ }
- string homeurl = BaseRegex.GetMatchRegexString(oldurl.ToLower(), "(http://[^/]*?)/");
- if (string.IsNullOrEmpty(homeurl))
- {
- homeurl = BaseRegex.GetMatchRegexString(oldurl.ToLower(), "(http://[^/]+)") + "/";
- if (string.IsNullOrEmpty(homeurl))
- {
- //BaseClass.ViewCode += "网址:" + oldurl + "识别失败\r\n";
- return url;
- }
- }
- if (url.Substring(0, 1) == "/")
- {
- string newurlx = homeurl + url;
- newurlx = newurlx.Replace("//", "/").Replace("http:/", "http://");
- return newurlx;
- }
- string[] l = oldurl.Split('/');
- int cute = l.Length;
- if (l.Length > 3)
- cute--;
- while (url.Contains("../"))
- {
- int s = url.IndexOf("../");
- if (s == 0)
- url = url.Substring(3);
- else
- url = url.Substring(0, s) + url.Substring(s + 3);
- cute--;
- if (cute < 3)
- cute = 3;
- }
- string newurl = "";
- for (int i = 0; i < cute; i++)
- newurl += l[i] + "/";
- newurl = newurl + url;
- return newurl.Replace("//", "/").Replace("http:/", "http://").Replace("/./", "/");
- }
- ///
- /// 获取代理地址
- ///
- ///
- ///
- public static string GetProxyUrl(string url)
- {
- if (string.IsNullOrEmpty(url))
- return null;
- if (BaseClass.Proxy.Count == 0)
- {
- BaseClass.ViewCode += "代理异常";
- return url;
- }
- Random ra = new Random();
- string p = BaseClass.Proxy[ra.Next(BaseClass.Proxy.Count)];
- return "http://" + p + "/url=" + url.Replace(".google.", ".goo00gle.")
- .Replace("?", "%3f").Replace("=", "%3d").Replace("&", "%26");
- }
+ string homeurl = BaseRegex.GetMatchRegexString(oldurl.ToLower(), "(http://[^/]*?)/");
+ if (string.IsNullOrEmpty(homeurl))
+ {
+ homeurl = BaseRegex.GetMatchRegexString(oldurl.ToLower(), "(http://[^/]+)") + "/";
+ if (string.IsNullOrEmpty(homeurl))
+ {
+ //BaseClass.ViewCode += "网址:" + oldurl + "识别失败\r\n";
+ return url;
+ }
+ }
+ if (url.Substring(0, 1) == "/")
+ {
+ string newurlx = homeurl + url;
+ newurlx = newurlx.Replace("//", "/").Replace("http:/", "http://");
+ return newurlx;
+ }
+ string[] l = oldurl.Split('/');
+ int cute = l.Length;
+ if (l.Length > 3)
+ cute--;
+ while (url.Contains("../"))
+ {
+ int s = url.IndexOf("../");
+ if (s == 0)
+ url = url.Substring(3);
+ else
+ url = url.Substring(0, s) + url.Substring(s + 3);
+ cute--;
+ if (cute < 3)
+ cute = 3;
+ }
+ string newurl = "";
+ for (int i = 0; i < cute; i++)
+ newurl += l[i] + "/";
+ newurl = newurl + url;
+ return newurl.Replace("//", "/").Replace("http:/", "http://").Replace("/./", "/");
+ }
+ ///
+ /// 获取代理地址
+ ///
+ ///
+ ///
+ public static string GetProxyUrl(string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ return null;
+ if (BaseClass.Proxy.Count == 0)
+ {
+ BaseClass.ViewCode += "代理异常";
+ return url;
+ }
+ Random ra = new Random();
+ string p = BaseClass.Proxy[ra.Next(BaseClass.Proxy.Count)];
+ return "http://" + p + "/url=" + url.Replace(".google.", ".goo00gle.")
+ .Replace("?", "%3f").Replace("=", "%3d").Replace("&", "%26");
+ }
- public static string GetUrlCodex(string url)
- {
- WebClientx webClient = new WebClientx();
- try
- {
- webClient.Timeout = 30;
- webClient.Headers.Add("Accept-Encoding", "gzip,deflate");
- webClient.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
- webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)");
- webClient.Proxy = null;
- byte[] b = webClient.DownloadData(url);
- b = ZipHelper.Decompress(b);
- string contentType = webClient.ResponseHeaders["Content-Type"];
- //webClient.Dispose();
- //webClient = null;
- string html = "";
- if (!String.IsNullOrEmpty(contentType))
- {
- string c = BaseRegex.GetMatchRegexString(contentType, "charset\\s*=\\s*(\\S+)");
- if (!String.IsNullOrEmpty(c))
- {
- c = c.Trim();
- html = Encoding.GetEncoding(c).GetString(b);
- }
- }
- if (String.IsNullOrEmpty(html))
- {
- html = Encoding.GetEncoding("UTF-8").GetString(b);
- //string r = @"<\s*meta.+charset\s*=\s*[""']*(\S+)[""'\s>]*";
- //string c = BaseRegex.GetMatchRegexString(html.ToLower(), r).Trim();
- //if (c.IndexOf("'") > -1)
- // c = c.Substring(0, c.IndexOf("'"));
- //if (c.IndexOf("\"") > -1)
- // c = c.Substring(0, c.IndexOf("\""));
- //if (c.IndexOf(" ") > -1)
- // c = c.Substring(0, c.IndexOf(" "));
- //if (c.IndexOf(">") > -1)
- // c = c.Substring(0, c.IndexOf(">"));
- //if (!String.IsNullOrEmpty(c) && c.ToLower() != "utf-8")
- // html = Encoding.GetEncoding(c).GetString(b);
- }
- return html;
- }
- catch (Exception e)
- {
- LogSave.AddView(url + " 错误:" + e.Message.Replace("\r\n", " "));
- return null;
- }
- finally
- {
- try
- {
- webClient.Dispose();
- webClient = null;
- }
- catch
- {
- }
- }
- }
+ public static string GetUrlCodex(string url)
+ {
+ WebClientx webClient = new WebClientx();
+ try
+ {
+ webClient.Timeout = 30;
+ webClient.Headers.Add("Accept-Encoding", "gzip,deflate");
+ webClient.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
+ webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)");
+ webClient.Proxy = null;
+ byte[] b = webClient.DownloadData(url);
+ b = ZipHelper.Decompress(b);
+ string contentType = webClient.ResponseHeaders["Content-Type"];
+ //webClient.Dispose();
+ //webClient = null;
+ string html = "";
+ if (!String.IsNullOrEmpty(contentType))
+ {
+ string c = BaseRegex.GetMatchRegexString(contentType, "charset\\s*=\\s*(\\S+)");
+ if (!String.IsNullOrEmpty(c))
+ {
+ c = c.Trim();
+ html = Encoding.GetEncoding(c).GetString(b);
+ }
+ }
+ if (String.IsNullOrEmpty(html))
+ {
+ html = Encoding.GetEncoding("UTF-8").GetString(b);
+ //string r = @"<\s*meta.+charset\s*=\s*[""']*(\S+)[""'\s>]*";
+ //string c = BaseRegex.GetMatchRegexString(html.ToLower(), r).Trim();
+ //if (c.IndexOf("'") > -1)
+ // c = c.Substring(0, c.IndexOf("'"));
+ //if (c.IndexOf("\"") > -1)
+ // c = c.Substring(0, c.IndexOf("\""));
+ //if (c.IndexOf(" ") > -1)
+ // c = c.Substring(0, c.IndexOf(" "));
+ //if (c.IndexOf(">") > -1)
+ // c = c.Substring(0, c.IndexOf(">"));
+ //if (!String.IsNullOrEmpty(c) && c.ToLower() != "utf-8")
+ // html = Encoding.GetEncoding(c).GetString(b);
+ }
+ return html;
+ }
+ catch (Exception e)
+ {
+ LogSave.AddView(url + " 错误:" + e.Message.Replace("\r\n", " "));
+ return null;
+ }
+ finally
+ {
+ try
+ {
+ webClient.Dispose();
+ webClient = null;
+ }
+ catch
+ {
+ }
+ }
+ }
- #region DES加密 | 解密
- //加解密密钥
- private static string skey = "AFZ94w3a";
+ #region DES加密 | 解密
+ //加解密密钥
+ private static string skey = "AFZ94w3a";
- #region DESEnCode DES加密
- public static string DESEnCode(string pToEncrypt)
- {
- try
- {
+ #region DESEnCode DES加密
+ public static string DESEnCode(string pToEncrypt)
+ {
+ try
+ {
- //pToEncrypt = HttpContext.Current.Server.UrlEncode(pToEncrypt);
- DESCryptoServiceProvider des = new DESCryptoServiceProvider();
- byte[] inputByteArray = Encoding.GetEncoding("UTF-8").GetBytes(pToEncrypt);
+ //pToEncrypt = HttpContext.Current.Server.UrlEncode(pToEncrypt);
+ DESCryptoServiceProvider des = new DESCryptoServiceProvider();
+ byte[] inputByteArray = Encoding.GetEncoding("UTF-8").GetBytes(pToEncrypt);
- des.Key = ASCIIEncoding.ASCII.GetBytes(skey);
- des.IV = ASCIIEncoding.ASCII.GetBytes(skey);
- MemoryStream ms = new MemoryStream();
- CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
+ des.Key = ASCIIEncoding.ASCII.GetBytes(skey);
+ des.IV = ASCIIEncoding.ASCII.GetBytes(skey);
+ MemoryStream ms = new MemoryStream();
+ CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
- cs.Write(inputByteArray, 0, inputByteArray.Length);
- cs.FlushFinalBlock();
+ cs.Write(inputByteArray, 0, inputByteArray.Length);
+ cs.FlushFinalBlock();
- StringBuilder ret = new StringBuilder();
- foreach (byte b in ms.ToArray())
- {
- ret.AppendFormat("{0:X2}", b);
- }
- ret.ToString();
- return ret.ToString();
+ StringBuilder ret = new StringBuilder();
+ foreach (byte b in ms.ToArray())
+ {
+ ret.AppendFormat("{0:X2}", b);
+ }
+ ret.ToString();
+ return ret.ToString();
- }
- catch (Exception e)
- {
+ }
+ catch (Exception e)
+ {
- //throw;
- }
- return "";
- }
- #endregion
+ //throw;
+ }
+ return "";
+ }
+ #endregion
- #region DESDeCode DES解密
- public static string DESDeCode(string pToDecrypt)
- {
- try
- {
- DESCryptoServiceProvider des = new DESCryptoServiceProvider();
- byte[] inputByteArray = new byte[pToDecrypt.Length / 2];
- for (int x = 0; x < pToDecrypt.Length / 2; x++)
- {
- int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));
- inputByteArray[x] = (byte)i;
- }
+ #region DESDeCode DES解密
+ public static string DESDeCode(string pToDecrypt)
+ {
+ try
+ {
+ DESCryptoServiceProvider des = new DESCryptoServiceProvider();
+ byte[] inputByteArray = new byte[pToDecrypt.Length / 2];
+ for (int x = 0; x < pToDecrypt.Length / 2; x++)
+ {
+ int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));
+ inputByteArray[x] = (byte)i;
+ }
- des.Key = ASCIIEncoding.ASCII.GetBytes(skey);
- des.IV = ASCIIEncoding.ASCII.GetBytes(skey);
- MemoryStream ms = new MemoryStream();
- CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
- cs.Write(inputByteArray, 0, inputByteArray.Length);
- cs.FlushFinalBlock();
+ des.Key = ASCIIEncoding.ASCII.GetBytes(skey);
+ des.IV = ASCIIEncoding.ASCII.GetBytes(skey);
+ MemoryStream ms = new MemoryStream();
+ CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
+ cs.Write(inputByteArray, 0, inputByteArray.Length);
+ cs.FlushFinalBlock();
- StringBuilder ret = new StringBuilder();
+ StringBuilder ret = new StringBuilder();
- return System.Text.Encoding.Default.GetString(ms.ToArray());
- }
- catch (Exception e)
- {
+ return System.Text.Encoding.Default.GetString(ms.ToArray());
+ }
+ catch (Exception e)
+ {
- //throw;
- }
- return "";
- }
- #endregion
+ //throw;
+ }
+ return "";
+ }
+ #endregion
- #endregion
+ #endregion
- ///
- /// 字符串转Unicode
- ///
- /// 源字符串
- /// Unicode编码后的字符串
- public static string String2Unicode(string source)
- {
- var bytes = Encoding.Unicode.GetBytes(source);
- var stringBuilder = new StringBuilder();
- for (var i = 0; i < bytes.Length; i += 2)
- {
- stringBuilder.AppendFormat("\\u{0}{1}", bytes[i + 1].ToString("x").PadLeft(2, '0'), bytes[i].ToString("x").PadLeft(2, '0'));
- }
- return stringBuilder.ToString();
- }
+ ///
+ /// 字符串转Unicode
+ ///
+ /// 源字符串
+ /// Unicode编码后的字符串
+ public static string String2Unicode(string source)
+ {
+ var bytes = Encoding.Unicode.GetBytes(source);
+ var stringBuilder = new StringBuilder();
+ for (var i = 0; i < bytes.Length; i += 2)
+ {
+ stringBuilder.AppendFormat("\\u{0}{1}", bytes[i + 1].ToString("x").PadLeft(2, '0'), bytes[i].ToString("x").PadLeft(2, '0'));
+ }
+ return stringBuilder.ToString();
+ }
- ///
- /// Unicode转字符串
- ///
- /// 经过Unicode编码的字符串
- /// 正常字符串
- public static string Unicode2String(string source)
- {
- return new Regex(@"\\u([0-9A-F]{4})", RegexOptions.IgnoreCase | RegexOptions.Compiled).Replace(source, x => Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16)).ToString());
- }
- }
+ ///
+ /// Unicode转字符串
+ ///
+ /// 经过Unicode编码的字符串
+ /// 正常字符串
+ public static string Unicode2String(string source)
+ {
+ return new Regex(@"\\u([0-9A-F]{4})", RegexOptions.IgnoreCase | RegexOptions.Compiled).Replace(source, x => Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16)).ToString());
+ }
+ }
}