From b0ec6ef3ea88d76084e1609b6b0e504af2923814 Mon Sep 17 00:00:00 2001 From: chfei Date: Tue, 1 Sep 2026 09:21:21 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E9=A1=B5=E9=9D=A2=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=AE=A2=E5=8D=95=E8=AF=A6=E6=83=85=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 29WxOrderWpf/App.xaml | 1 + 29WxOrderWpf/Converters/FenToYuanConverter.cs | 36 ++++ .../Ctrls/Statistics/RevenueSummaryCards.xaml | 190 +++++++++++------- .../Services/ShopRevenueStatisticsService.cs | 42 +++- .../Ctrls/Statistics/ShowOrderDialogView.xaml | 105 ++++++++++ .../Statistics/ShowOrderDialogView.xaml.cs | 50 +++++ .../PeriodRevenueStatisticsViewModel.cs | 50 ++++- .../ShopRevenueStatisticsViewModel.cs | 50 ++++- 29WxOrderWpf/Styles/BaseButtonStyle.xaml | 43 ++++ 9 files changed, 484 insertions(+), 83 deletions(-) create mode 100644 29WxOrderWpf/Converters/FenToYuanConverter.cs create mode 100644 29WxOrderWpf/Ctrls/Statistics/ShowOrderDialogView.xaml create mode 100644 29WxOrderWpf/Ctrls/Statistics/ShowOrderDialogView.xaml.cs diff --git a/29WxOrderWpf/App.xaml b/29WxOrderWpf/App.xaml index a779701..1c7d122 100644 --- a/29WxOrderWpf/App.xaml +++ b/29WxOrderWpf/App.xaml @@ -15,6 +15,7 @@ + diff --git a/29WxOrderWpf/Converters/FenToYuanConverter.cs b/29WxOrderWpf/Converters/FenToYuanConverter.cs new file mode 100644 index 0000000..4264c7d --- /dev/null +++ b/29WxOrderWpf/Converters/FenToYuanConverter.cs @@ -0,0 +1,36 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace _29WxOrderWpf.Converters +{ + /// + /// 金额转换:分 -> 元(除以 100)。 + /// 用于把后台返回的以“分”为单位的金额字段显示为“元”。 + /// + public class FenToYuanConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + decimal fen; + if (value is int intValue) + fen = intValue; + else if (value is long longValue) + fen = longValue; + else if (value is decimal decimalValue) + fen = decimalValue; + else if (value is double doubleValue) + fen = (decimal)doubleValue; + else + return 0m; + + return fen / 100m; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + // 单向绑定,反向转换不实现 + throw new NotImplementedException(); + } + } +} diff --git a/29WxOrderWpf/Ctrls/Statistics/RevenueSummaryCards.xaml b/29WxOrderWpf/Ctrls/Statistics/RevenueSummaryCards.xaml index 4ec5398..36172ba 100644 --- a/29WxOrderWpf/Ctrls/Statistics/RevenueSummaryCards.xaml +++ b/29WxOrderWpf/Ctrls/Statistics/RevenueSummaryCards.xaml @@ -7,6 +7,7 @@ xmlns:vm="clr-namespace:_29WxOrderWpf.Ctrls.Statistics.ViewModels" d:DataContext="{d:DesignInstance Type=vm:ShopRevenueStatisticsViewModel, IsDesignTimeCreatable=True}" + d:Width="1200" mc:Ignorable="d"> @@ -55,26 +56,45 @@ - - - - - - - + + + + + + + + + + + + + @@ -178,7 +198,7 @@ Text="预计技术服务费" /> - + @@ -201,44 +221,60 @@ - - + + + + + + + + + + + FontSize="14" + Foreground="#888888" + Text="总采购金额" /> + Margin="0,12,0,0" + FontSize="30" + FontWeight="Bold" + Foreground="#333333" + Text="{Binding Summary.BuyerRefundAmount, StringFormat={}¥{0:N2}}" /> + Margin="0,10,0,0" + FontSize="12" + Foreground="#999999" + Text="售后采购金额" /> @@ -263,26 +299,42 @@ - - - + + + + + + + + + + + diff --git a/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs b/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs index 7941294..ee66da0 100644 --- a/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs +++ b/29WxOrderWpf/Ctrls/Statistics/Services/ShopRevenueStatisticsService.cs @@ -45,6 +45,9 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services /// 获取店铺下拉列表(用于查询条件) Task> GetShopOptionsAsync(); + + + } /// @@ -133,8 +136,8 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services int totalOrderCount = list.Count(); int refundOrderCount = refunded.Select(r => r.OrderId).Distinct().Count(); Debug.WriteLine($"计算利润:{(salesAmount - buyerPaymentAmount - platformFeeTotal)}"); - Debug.WriteLine($"正常订单利润:{valid.Sum(r => (decimal)(r.Profit))/100}"); - Debug.WriteLine($"售后订单利润:{refunded.Sum(r => (decimal)(r.Profit))/100}"); + Debug.WriteLine($"正常订单利润:{valid.Sum(r => (decimal)(r.Profit)) / 100}"); + Debug.WriteLine($"售后订单利润:{refunded.Sum(r => (decimal)(r.Profit)) / 100}"); return new ShopRevenueSummary { SalesAmount = salesAmount, @@ -152,6 +155,41 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services BuyerRefundSuccessedAmount = buyerRefundSuccessedAmount, }; } + /// + /// 获取有效订单 + /// + /// + /// + public static List GetValidOrder(IEnumerable rows) + { + var list = GetPaymentOrderList(rows); //买手付钱后的订单数量 + return list.Where(IsValidOrder).ToList(); + } + /// + /// 获取退款订单 + /// + /// + /// + public static List GetRefundOrder(IEnumerable rows) + { + var list = GetPaymentOrderList(rows); //买手付钱后的订单数量 + return list.Where(IsRefunded).ToList(); + } + /// + /// 获取退款订单 + /// + /// + /// + public static List GetBuyerRefundRemainingOrder(IEnumerable rows) + { + var list = GetPaymentOrderList(rows); //买手付钱后的订单数量 + var refunded = list.Where(IsRefunded).ToList(); + + decimal buyerRefundAmount = refunded.Sum(r => (decimal)(r.OutAmount)) / 100m; //买手号退款金额(采购退款金额) + decimal buyerRefundSuccessedAmount = refunded.Where(a => IsBuyerRefundSuccessful(a) == false).Sum(r => (decimal)(r.BuyerRefundAmount)) / 100m; //买手号退款成功金额 + + return refunded.Where(a => IsBuyerRefundSuccessful(a) == false).ToList(); + } /// 销售趋势(按天,缺失日期补 0,仅统计有效订单) public static List GetSalesTrend(IEnumerable rows, DateTime startDate, DateTime endDate) diff --git a/29WxOrderWpf/Ctrls/Statistics/ShowOrderDialogView.xaml b/29WxOrderWpf/Ctrls/Statistics/ShowOrderDialogView.xaml new file mode 100644 index 0000000..6eb7118 --- /dev/null +++ b/29WxOrderWpf/Ctrls/Statistics/ShowOrderDialogView.xaml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/29WxOrderWpf/Ctrls/Statistics/ShowOrderDialogView.xaml.cs b/29WxOrderWpf/Ctrls/Statistics/ShowOrderDialogView.xaml.cs new file mode 100644 index 0000000..8bbb966 --- /dev/null +++ b/29WxOrderWpf/Ctrls/Statistics/ShowOrderDialogView.xaml.cs @@ -0,0 +1,50 @@ +using _29WxOrderWpf.Ctrls.Statistics.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace _29WxOrderWpf.Ctrls.Statistics; + +/// +/// ShowOrderDialogView.xaml 的交互逻辑 +/// +public partial class ShowOrderDialogView : UserControl +{ + public ShowOrderDialogView(List list) + { + InitializeComponent(); + this.DataContext = new ShowOrderDialogViewModel(list); + } + + /// + /// 复制订单号到剪贴板 + /// + private void CopyOrderId_Click(object sender, RoutedEventArgs e) + { + if (sender is FrameworkElement element + && element.DataContext is ShopRevenueStatisticsRow row + && !string.IsNullOrEmpty(row.OrderId)) + { + Clipboard.SetText(row.OrderId); + } + } +} +class ShowOrderDialogViewModel +{ + public List Data { get; set; } + public ShowOrderDialogViewModel(List list) + { + Data = list ?? new List(); + } +} diff --git a/29WxOrderWpf/Ctrls/Statistics/ViewModels/PeriodRevenueStatisticsViewModel.cs b/29WxOrderWpf/Ctrls/Statistics/ViewModels/PeriodRevenueStatisticsViewModel.cs index b41b843..39b55cc 100644 --- a/29WxOrderWpf/Ctrls/Statistics/ViewModels/PeriodRevenueStatisticsViewModel.cs +++ b/29WxOrderWpf/Ctrls/Statistics/ViewModels/PeriodRevenueStatisticsViewModel.cs @@ -1,14 +1,15 @@ -using System; +using _29WxOrderWpf.Commands; +using _29WxOrderWpf.Common; +using _29WxOrderWpf.Ctrls.Statistics.Models; +using _29WxOrderWpf.Ctrls.Statistics.Services; +using AllBase.Model.MvvmBaseClasses; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; -using System.Windows.Input; using System.Windows; -using AllBase.Model.MvvmBaseClasses; -using _29WxOrderWpf.Ctrls.Statistics.Models; -using _29WxOrderWpf.Ctrls.Statistics.Services; -using _29WxOrderWpf.Commands; +using System.Windows.Input; namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels { @@ -545,5 +546,42 @@ namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels } #endregion + + + + public ICommand ShowOrderListCommand => new AsyncDelegateCommand(ShowOrderList); + + private async Task ShowOrderList(string type) + { + var query = new ShopRevenueStatisticsQuery + { + StartDate = StartDate, + EndDate = EndDate, + ShopKeys = BuildSelectedShopKeys(), + }; + var rows = await _service.QueryRowsAsync(query); + List showList = new List(); + switch (type) + { + case "ValidOrderCount": + showList = RevenueStatisticsAggregator.GetValidOrder(rows); + break; //有效订单 + case "RefundOrderCount": + showList = RevenueStatisticsAggregator.GetRefundOrder(rows); + break;//退款订单 + case "BuyerRefundRemainingAmount": + showList = RevenueStatisticsAggregator.GetBuyerRefundRemainingOrder(rows); + break;//待退回采购金额 + default: + break; + } + + new DialogWindow() + { + Title = "订单列表", + Content = new ShowOrderDialogView(showList), + DataContext = rows + }.ShowDialog(); + } } } \ No newline at end of file diff --git a/29WxOrderWpf/Ctrls/Statistics/ViewModels/ShopRevenueStatisticsViewModel.cs b/29WxOrderWpf/Ctrls/Statistics/ViewModels/ShopRevenueStatisticsViewModel.cs index ca2b6da..979a401 100644 --- a/29WxOrderWpf/Ctrls/Statistics/ViewModels/ShopRevenueStatisticsViewModel.cs +++ b/29WxOrderWpf/Ctrls/Statistics/ViewModels/ShopRevenueStatisticsViewModel.cs @@ -1,14 +1,16 @@ -using System; +using _29WxOrderWpf.Commands; +using _29WxOrderWpf.Common; +using _29WxOrderWpf.Ctrls.Statistics.Models; +using _29WxOrderWpf.Ctrls.Statistics.Services; +using AllBase.Model.MvvmBaseClasses; +using CefSharp; +using NPOI.SS.Formula.Functions; +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 { @@ -300,5 +302,41 @@ namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels } #endregion + + + public ICommand ShowOrderListCommand => new AsyncDelegateCommand(ShowOrderList); + + private async Task ShowOrderList(string type) + { + var query = new ShopRevenueStatisticsQuery + { + StartDate = StartDate, + EndDate = EndDate, + ShopKeys = BuildSelectedShopKeys(), + }; + var rows = await _service.QueryRowsAsync(query); + List showList = new List(); + switch (type) + { + case "ValidOrderCount": + showList = RevenueStatisticsAggregator.GetValidOrder(rows); + break; //有效订单 + case "RefundOrderCount": + showList = RevenueStatisticsAggregator.GetRefundOrder(rows); + break;//退款订单 + case "BuyerRefundRemainingAmount": + showList = RevenueStatisticsAggregator.GetBuyerRefundRemainingOrder(rows); + break;//待退回采购金额 + default: + break; + } + + new DialogWindow() + { + Title="订单列表", + Content = new ShowOrderDialogView(showList), + DataContext = rows + }.ShowDialog(); + } } } \ No newline at end of file diff --git a/29WxOrderWpf/Styles/BaseButtonStyle.xaml b/29WxOrderWpf/Styles/BaseButtonStyle.xaml index 9c6e70b..79c3141 100644 --- a/29WxOrderWpf/Styles/BaseButtonStyle.xaml +++ b/29WxOrderWpf/Styles/BaseButtonStyle.xaml @@ -229,4 +229,47 @@ + + + \ No newline at end of file