统计页面增加订单详情页

This commit is contained in:
chfei committed 2026-09-01 09:21:21 +08:00
1 parent 545a0751c8
commit b0ec6ef3ea
9 files changed
+484 -83

No files matched your search

+1
View File
@@ -15,6 +15,7 @@
<converters:VisibleToVisibilityConverter x:Key="visibleToVisibilityConverter" />
<converters:ImageUrlToBitmapImageConverter x:Key="ImageUrlToBitmapImage" />
<converters:ValueMinus24Converter x:Key="ValueMinus24Converter" />
<converters:FenToYuanConverter x:Key="FenToYuanConverter" />
<converters:StatusToColorBrushConverter x:Key="statusToColorBrushConverter" />
<converters:ListBoxIndexConverter x:Key="listBoxIndexConverter" />
<converters:FlagColorConverter x:Key="flagColorConverter" />
@@ -0,0 +1,36 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace _29WxOrderWpf.Converters
{
/// <summary>
/// 金额转换:分 -> 元(除以 100)。
/// 用于把后台返回的以“分”为单位的金额字段显示为“元”。
/// </summary>
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();
}
}
}
@@ -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">
<UserControl.Resources>
<!-- 卡片样式(白底、圆角、阴影) -->
@@ -55,26 +56,45 @@
</Border>
<!-- 有效订单 -->
<Border Style="{StaticResource CardBorderStyle}">
<StackPanel>
<TextBlock
FontSize="14"
Foreground="#888888"
Text="有效订单" />
<TextBlock
Margin="0,12,0,0"
FontSize="30"
FontWeight="Bold"
Foreground="#333333"
Text="{Binding Summary.ValidOrderCount, StringFormat={}{0:N0}}" />
<TextBlock
Margin="0,10,0,0"
FontSize="12"
Foreground="#999999"
Text="已扣除退款订单" />
</StackPanel>
</Border>
<Grid>
<Border Style="{StaticResource CardBorderStyle}">
<StackPanel>
<Grid>
<TextBlock
FontSize="14"
Foreground="#888888"
Text="有效订单" />
</Grid>
<TextBlock
Margin="0,12,0,0"
FontSize="30"
FontWeight="Bold"
Foreground="#333333"
Text="{Binding Summary.ValidOrderCount, StringFormat={}{0:N0}}" />
<TextBlock
Margin="0,10,0,0"
FontSize="12"
Foreground="#999999"
Text="已扣除退款订单" />
</StackPanel>
</Border>
<Button
Height="16"
Margin="10"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Command="{Binding ShowOrderListCommand}"
CommandParameter="ValidOrderCount"
Foreground="{StaticResource pageColorBrush}"
Style="{StaticResource IconButtonStyle}">
<TextBlock
FontSize="24"
Style="{StaticResource TextBlockIcon}"
Text="{StaticResource txt-more_horizontal}" />
</Button>
</Grid>
<!-- 采购金额 -->
<Border Style="{StaticResource CardBorderStyle}">
<StackPanel>
@@ -178,7 +198,7 @@
Text="预计技术服务费" />
</StackPanel>
</Border>
<!-- 退款金额 -->
<Border Style="{StaticResource CardBorderStyle}">
<StackPanel>
@@ -201,44 +221,60 @@
</Border>
<!-- 退款订单 -->
<Border Style="{StaticResource CardBorderStyle}">
<StackPanel>
<Grid>
<Border Style="{StaticResource CardBorderStyle}">
<StackPanel>
<TextBlock
FontSize="14"
Foreground="#888888"
Text="退款订单" />
<TextBlock
Margin="0,12,0,0"
FontSize="30"
FontWeight="Bold"
Foreground="#333333"
Text="{Binding Summary.RefundOrderCount, StringFormat={}{0:N0}}" />
<TextBlock
Margin="0,10,0,0"
FontSize="12"
Foreground="#999999"
Text="退款订单" />
</StackPanel>
</Border>
<Button
Height="16"
Margin="10"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Command="{Binding ShowOrderListCommand}"
CommandParameter="RefundOrderCount"
Foreground="{StaticResource pageColorBrush}"
Style="{StaticResource IconButtonStyle}">
<TextBlock
FontSize="14"
Foreground="#888888"
Text="退款订单" />
<TextBlock
Margin="0,12,0,0"
FontSize="30"
FontWeight="Bold"
Foreground="#333333"
Text="{Binding Summary.RefundOrderCount, StringFormat={}{0:N0}}" />
<TextBlock
Margin="0,10,0,0"
FontSize="12"
Foreground="#999999"
Text="退款订单" />
</StackPanel>
</Border>
FontSize="24"
Style="{StaticResource TextBlockIcon}"
Text="{StaticResource txt-more_horizontal}" />
</Button>
</Grid>
<!-- 采购退款成功金额 -->
<Border Style="{StaticResource CardBorderStyle}">
<StackPanel>
<TextBlock
FontSize="14"
Foreground="#888888"
Text="总采购金额" />
FontSize="14"
Foreground="#888888"
Text="总采购金额" />
<TextBlock
Margin="0,12,0,0"
FontSize="30"
FontWeight="Bold"
Foreground="#333333"
Text="{Binding Summary.BuyerRefundAmount, StringFormat={}¥{0:N2}}" />
Margin="0,12,0,0"
FontSize="30"
FontWeight="Bold"
Foreground="#333333"
Text="{Binding Summary.BuyerRefundAmount, StringFormat={}¥{0:N2}}" />
<TextBlock
Margin="0,10,0,0"
FontSize="12"
Foreground="#999999"
Text="售后采购金额" />
Margin="0,10,0,0"
FontSize="12"
Foreground="#999999"
Text="售后采购金额" />
</StackPanel>
</Border>
@@ -263,26 +299,42 @@
</StackPanel>
</Border>
<!-- 采购退款成功金额 -->
<Border Style="{StaticResource CardBorderStyle}">
<StackPanel>
<!-- 待退回采购金额 -->
<Grid>
<Border Style="{StaticResource CardBorderStyle}">
<StackPanel>
<TextBlock
FontSize="14"
Foreground="#888888"
Text="待退回采购金额" />
<TextBlock
Margin="0,12,0,0"
FontSize="30"
FontWeight="Bold"
Foreground="#333333"
Text="{Binding Summary.BuyerRefundRemainingAmount, StringFormat={}¥{0:N2}}" />
<TextBlock
Margin="0,10,0,0"
FontSize="12"
Foreground="#999999"
Text="待退回采购金额" />
</StackPanel>
</Border>
<Button
Height="16"
Margin="10"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Command="{Binding ShowOrderListCommand}"
CommandParameter="BuyerRefundRemainingAmount"
Foreground="{StaticResource pageColorBrush}"
Style="{StaticResource IconButtonStyle}">
<TextBlock
FontSize="14"
Foreground="#888888"
Text="待退回采购金额" />
<TextBlock
Margin="0,12,0,0"
FontSize="30"
FontWeight="Bold"
Foreground="#333333"
Text="{Binding Summary.BuyerRefundRemainingAmount, StringFormat={}¥{0:N2}}" />
<TextBlock
Margin="0,10,0,0"
FontSize="12"
Foreground="#999999"
Text="待退回采购金额" />
</StackPanel>
</Border>
FontSize="24"
Style="{StaticResource TextBlockIcon}"
Text="{StaticResource txt-more_horizontal}" />
</Button>
</Grid>
<!-- 退款率 -->
<Border Style="{StaticResource CardBorderStyle}">
@@ -45,6 +45,9 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services
/// <summary>获取店铺下拉列表(用于查询条件)</summary>
Task<List<ShopOption>> GetShopOptionsAsync();
}
/// <summary>
@@ -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,
};
}
/// <summary>
/// 获取有效订单
/// </summary>
/// <param name="rows"></param>
/// <returns></returns>
public static List<ShopRevenueStatisticsRow> GetValidOrder(IEnumerable<ShopRevenueStatisticsRow> rows)
{
var list = GetPaymentOrderList(rows); //买手付钱后的订单数量
return list.Where(IsValidOrder).ToList();
}
/// <summary>
/// 获取退款订单
/// </summary>
/// <param name="rows"></param>
/// <returns></returns>
public static List<ShopRevenueStatisticsRow> GetRefundOrder(IEnumerable<ShopRevenueStatisticsRow> rows)
{
var list = GetPaymentOrderList(rows); //买手付钱后的订单数量
return list.Where(IsRefunded).ToList();
}
/// <summary>
/// 获取退款订单
/// </summary>
/// <param name="rows"></param>
/// <returns></returns>
public static List<ShopRevenueStatisticsRow> GetBuyerRefundRemainingOrder(IEnumerable<ShopRevenueStatisticsRow> 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();
}
/// <summary>销售趋势(按天,缺失日期补 0,仅统计有效订单)</summary>
public static List<RevenueTrendPoint> GetSalesTrend(IEnumerable<ShopRevenueStatisticsRow> rows, DateTime startDate, DateTime endDate)
@@ -0,0 +1,105 @@
<UserControl
x:Class="_29WxOrderWpf.Ctrls.Statistics.ShowOrderDialogView"
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:local="clr-namespace:_29WxOrderWpf.Ctrls.Statistics"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:Background="White"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<UserControl.Resources>
<!-- 单元格文字居中 -->
<Style x:Key="CenterCellTextStyle" TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</UserControl.Resources>
<Grid>
<DataGrid
d:ItemsSource="{d:SampleData ItemCount=10}"
AlternatingRowBackground="#FAFAFA"
AutoGenerateColumns="False"
Background="Transparent"
BorderThickness="0"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
CanUserResizeRows="False"
ColumnHeaderStyle="{StaticResource BaseDataGridColumnHeaderStyle}"
GridLinesVisibility="Horizontal"
HeadersVisibility="Column"
HorizontalGridLinesBrush="#EEEEEE"
IsReadOnly="True"
ItemsSource="{Binding Data}"
RowHeight="44"
SelectionMode="Single"
SelectionUnit="FullRow"
VerticalScrollBarVisibility="Auto">
<DataGrid.Columns>
<!-- 店名 -->
<DataGridTextColumn
Width="*"
Binding="{Binding ShopName}"
ElementStyle="{StaticResource CenterCellTextStyle}"
Header="店名" />
<!-- 订单(可复制) -->
<DataGridTemplateColumn Width="2*" Header="订单">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Text="{Binding OrderId}"
ToolTip="点击“复制”复制订单号" />
<Button
Margin="5,0,0,0"
Click="CopyOrderId_Click"
Foreground="{StaticResource pageColorBrush}"
ToolTip="复制订单号">
<Button.Style>
<Style BasedOn="{StaticResource IconButtonStyle}" TargetType="Button">
<Setter Property="Foreground" Value="{StaticResource pageColorBrush}" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=IsSelected}" Value="True">
<Setter Property="Foreground" Value="White" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<TextBlock Style="{StaticResource TextBlockIcon}" Text="{StaticResource txt-copy}" />
</Button>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- 金额(分转元) -->
<DataGridTextColumn
Width="*"
Binding="{Binding OrderPrice, Converter={StaticResource FenToYuanConverter}, StringFormat={}¥{0:N2}}"
ElementStyle="{StaticResource CenterCellTextStyle}"
Header="金额" />
<DataGridTextColumn
Width="*"
Binding="{Binding RefundAmount, Converter={StaticResource FenToYuanConverter}, StringFormat={}¥{0:N2}}"
ElementStyle="{StaticResource CenterCellTextStyle}"
Header="退款金额" />
<DataGridTextColumn
Width="*"
Binding="{Binding OutAmount, Converter={StaticResource FenToYuanConverter}, StringFormat={}¥{0:N2}}"
ElementStyle="{StaticResource CenterCellTextStyle}"
Header="外采金额" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
@@ -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;
/// <summary>
/// ShowOrderDialogView.xaml 的交互逻辑
/// </summary>
public partial class ShowOrderDialogView : UserControl
{
public ShowOrderDialogView(List<ShopRevenueStatisticsRow> list)
{
InitializeComponent();
this.DataContext = new ShowOrderDialogViewModel(list);
}
/// <summary>
/// 复制订单号到剪贴板
/// </summary>
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<ShopRevenueStatisticsRow> Data { get; set; }
public ShowOrderDialogViewModel(List<ShopRevenueStatisticsRow> list)
{
Data = list ?? new List<ShopRevenueStatisticsRow>();
}
}
@@ -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<string>(ShowOrderList);
private async Task ShowOrderList(string type)
{
var query = new ShopRevenueStatisticsQuery
{
StartDate = StartDate,
EndDate = EndDate,
ShopKeys = BuildSelectedShopKeys(),
};
var rows = await _service.QueryRowsAsync(query);
List<ShopRevenueStatisticsRow> showList = new List<ShopRevenueStatisticsRow>();
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();
}
}
}
@@ -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<string>(ShowOrderList);
private async Task ShowOrderList(string type)
{
var query = new ShopRevenueStatisticsQuery
{
StartDate = StartDate,
EndDate = EndDate,
ShopKeys = BuildSelectedShopKeys(),
};
var rows = await _service.QueryRowsAsync(query);
List<ShopRevenueStatisticsRow> showList = new List<ShopRevenueStatisticsRow>();
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();
}
}
}
+43
View File
@@ -229,4 +229,47 @@
</Setter.Value>
</Setter>
</Style>
<Style x:Key="IconButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Padding" Value="4" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Focusable" Value="False" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground" Value="#0b0b0b" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
x:Name="border"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value=".9" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value=".6" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.4" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>