Files
29WxOrder/29WxOrderWpf/Ctrls/Statistics/ViewModels/ShopRevenueStatisticsViewModel.cs
T
2026-10-07 16:16:55 +08:00

343 lines
9.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
using System.Windows.Input;
namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels
{
/// <summary>
/// 店铺营收统计 - 页面 ViewModel(MVVM)。
/// 通过 IShopRevenueStatisticsService 调用数据接口;
/// 接入真实接口时传入自定义实现:new ShopRevenueStatisticsViewModel(你的服务实现)。
/// </summary>
public class ShopRevenueStatisticsViewModel : PropertyNotifyObject
{
private readonly IShopRevenueStatisticsService _service;
private ShopRevenueSummary _summary;
private ObservableCollection<RevenueTrendPoint> _trendData;
private ObservableCollection<ShopSalesProportionItem> _shopProportionData;
private ObservableCollection<ShopStatisticsItem> _shopStatistics;
private ObservableCollection<ShopOption> _selectedShops;
private string _selectedPlatform;
public ShopRevenueStatisticsViewModel()
: this(new ShopRevenueStatisticsService())
{
}
public ShopRevenueStatisticsViewModel(IShopRevenueStatisticsService service)
{
_service = service ?? new ShopRevenueStatisticsService();
TimeRangeOptions = new ObservableCollection<TimeRangeOption>
{
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<ShopOption>();
QueryCommand = new DelegateCommand(async () => await LoadAsync());
ResetCommand = new DelegateCommand(Reset);
InitializeAsync();
}
#region 查询条件
/// <summary>时间范围选项</summary>
public ObservableCollection<TimeRangeOption> TimeRangeOptions { get; }
/// <summary>选中的时间范围</summary>
public TimeRangeOption SelectedTimeRange
{
get { return this.GetValue(x => x.SelectedTimeRange); }
set
{
this.SetValue(x => x.SelectedTimeRange, value);
ApplyTimeRange();
OnPropertyChanged(nameof(IsCustomDateRange));
}
}
/// <summary>是否为自定义时间范围</summary>
public bool IsCustomDateRange
{
get { return SelectedTimeRange != null && SelectedTimeRange.Value == "custom"; }
}
/// <summary>开始日期</summary>
public DateTime StartDate
{
get { return this.GetValue(x => x.StartDate); }
set { this.SetValue(x => x.StartDate, value); }
}
/// <summary>结束日期</summary>
public DateTime EndDate
{
get { return this.GetValue(x => x.EndDate); }
set { this.SetValue(x => x.EndDate, value); }
}
/// <summary>店铺选项(“全部店铺”由多选控件“全部商铺”表示)</summary>
public ObservableCollection<ShopOption> ShopOptions { get; }
/// <summary>选中的店铺</summary>
public ObservableCollection<ShopOption> SelectedShops
{
get { return _selectedShops; }
set
{
_selectedShops = value;
OnPropertyChanged(nameof(SelectedShops));
}
}
#endregion
#region 统计结果
/// <summary>汇总卡片数据</summary>
public ShopRevenueSummary Summary
{
get { return _summary; }
private set
{
_summary = value;
OnPropertyChanged(nameof(Summary));
}
}
/// <summary>销售趋势数据</summary>
public ObservableCollection<RevenueTrendPoint> TrendData
{
get { return _trendData; }
private set
{
_trendData = value;
OnPropertyChanged(nameof(TrendData));
}
}
/// <summary>店铺销售占比数据</summary>
public ObservableCollection<ShopSalesProportionItem> ShopProportionData
{
get { return _shopProportionData; }
private set
{
_shopProportionData = value;
OnPropertyChanged(nameof(ShopProportionData));
}
}
/// <summary>店铺统计表格数据</summary>
public ObservableCollection<ShopStatisticsItem> ShopStatistics
{
get { return _shopStatistics; }
private set
{
_shopStatistics = value;
OnPropertyChanged(nameof(ShopStatistics));
}
}
/// <summary>是否正在加载</summary>
public bool IsLoading
{
get { return this.GetValue(x => x.IsLoading); }
set { this.SetValue(x => x.IsLoading, value); }
}
#endregion
#region 命令
/// <summary>查询命令</summary>
public ICommand QueryCommand { get; }
/// <summary>重置命令</summary>
public ICommand ResetCommand { get; }
#endregion
#region 初始化
private async void InitializeAsync()
{
try
{
// 店铺选项(全部店铺由多选控件“全部商铺”表示,不再额外加入“全部店铺”项)
var shops = await _service.GetShopOptionsAsync();
foreach (var shop in shops)
ShopOptions.Add(shop);
SelectedShops = new ObservableCollection<ShopOption>(ShopOptions);
// 默认时间范围:本月
SelectedTimeRange = TimeRangeOptions.FirstOrDefault(t => t.Value == "month");
ApplyTimeRange();
await LoadAsync();
}
catch (Exception)
{
// 初始化失败(如接口不可用),页面保持可查询状态;可在此接入日志/提示
}
}
#endregion
#region 业务逻辑
/// <summary>根据时间范围选项计算起止日期</summary>
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;
}
}
/// <summary>根据选中店铺生成查询店铺 key 列表:未选/全选/选中“全部店铺”时返回空列表(表示全部店铺)</summary>
private List<string> BuildSelectedShopKeys()
{
var selected = SelectedShops;
if (selected == null || selected.Count == 0)
return new List<string>();
var keys = selected.Select(s => s == null ? string.Empty : s.AppKey).ToList();
if (keys.Any(string.IsNullOrEmpty))
return new List<string>();
if (selected.Count >= ShopOptions.Count)
return new List<string>();
return keys;
}
/// <summary>执行查询,刷新页面所有统计数据</summary>
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,
ShopKeys = BuildSelectedShopKeys(),
};
Summary = await _service.GetSummaryAsync(query);
var trend = await _service.GetSalesTrendAsync(query);
TrendData = new ObservableCollection<RevenueTrendPoint>(trend);
var proportion = await _service.GetShopSalesProportionAsync(query);
ShopProportionData = new ObservableCollection<ShopSalesProportionItem>(proportion);
var table = await _service.GetShopStatisticsAsync(query);
ShopStatistics = new ObservableCollection<ShopStatisticsItem>(table);
}
catch (Exception)
{
// 查询异常:保留上一次数据,可在此接入日志/错误提示
}
finally
{
IsLoading = false;
}
}
/// <summary>重置查询条件并重新加载</summary>
private async void Reset()
{
SelectedShops = new ObservableCollection<ShopOption>(ShopOptions);
SelectedTimeRange = TimeRangeOptions.FirstOrDefault(t => t.Value == "month");
ApplyTimeRange();
await LoadAsync();
}
#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(GetWindow())
{
Title="订单列表",
Content = new ShowOrderDialogView(showList),
DataContext = rows
}.Show();
}
public Func<Window> GetWindow;
}
}