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; using Work.BaseForms; 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 ObservableCollection _selectedShops; private string _selectedPlatform; /// 上一次真正生效(并据此计算过日期)的时间范围选项,避免同一个选项被重复应用 private TimeRangeOption _appliedTimeRange; 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); // 只有用户真正切换到“另一个”时间范围选项时才重新计算起止日期。 // 页签切换时下拉框会把同一个选项(甚至先 null 再回写)重放一遍, // 若照样重算,就会把用户手工调过的日期覆盖掉。 if (value != null && !ReferenceEquals(_appliedTimeRange, value)) { _appliedTimeRange = 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 ObservableCollection SelectedShops { get { return _selectedShops; } set { _selectedShops = value; OnPropertyChanged(nameof(SelectedShops)); } } #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 { // 店铺选项(全部店铺由多选控件“全部商铺”表示,不再额外加入“全部店铺”项) var shops = await _service.GetShopOptionsAsync(); foreach (var shop in shops) ShopOptions.Add(shop); SelectedShops = new ObservableCollection(ShopOptions); // 默认时间范围:本月 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; } } /// /// 根据选中店铺生成查询用 ERP 店铺ID 列表(接口 ShopIds 使用 ShopLoginInfo.ErpShopId): /// 未选/全选/选中“全部店铺”时返回空列表(表示全部店铺)。 /// private List BuildSelectedShopIds() { var selected = SelectedShops; if (selected == null || selected.Count == 0) return new List(); var ids = selected.Select(s => s == null ? string.Empty : s.ErpShopId).ToList(); if (ids.Any(string.IsNullOrEmpty)) return new List(); if (selected.Count >= ShopOptions.Count) return new List(); return ids; } /// 组装查询参数(起止日期已保证先后顺序) private ShopRevenueStatisticsQuery BuildQuery() { if (StartDate == EndDate) { EndDate = EndDate.AddDays(1).AddSeconds(-1); } else if (StartDate > EndDate) { var temp = StartDate; StartDate = EndDate; EndDate = temp; } return new ShopRevenueStatisticsQuery { StartDate = StartDate, EndDate = EndDate, ShopIds = BuildSelectedShopIds(), }; } /// 执行查询,刷新页面所有统计数据 private async Task LoadAsync() { IsLoading = true; try { var result = await _service.QueryAsync(BuildQuery()); Summary = result.Summary; TrendData = new ObservableCollection(result.Trend ?? new List()); ShopProportionData = new ObservableCollection(result.ShopProportions ?? new List()); ShopStatistics = new ObservableCollection(result.ShopStatistics ?? new List()); } catch (Exception ex) { // 查询异常:保留上一次数据,并弹框提示 BaseMsgForm.ShowError("查询失败:" + ex.Message, "提示"); } finally { IsLoading = false; } } /// 重置查询条件并重新加载 private async void Reset() { SelectedShops = new ObservableCollection(ShopOptions); SelectedTimeRange = TimeRangeOptions.FirstOrDefault(t => t.Value == "month"); ApplyTimeRange(); await LoadAsync(); } #endregion public ICommand ShowOrderListCommand => new AsyncDelegateCommand(ShowOrderList); private async Task ShowOrderList(string type) { var detailType = ParseDetailType(type); List showList; IsLoading = true; try { showList = await _service.QueryOrderRowsAsync(BuildQuery(), detailType) ?? new List(); } catch (Exception ex) { BaseMsgForm.ShowError("订单明细查询失败:" + ex.Message, "提示"); return; } finally { IsLoading = false; } if (showList.Count == 0) { BaseMsgForm.ShowInfo("未查询到符合条件的订单明细。", "提示"); return; } new DialogWindow(GetWindow()) { Title = "订单列表", Content = new ShowOrderDialogView(showList, detailType, _service), DataContext = showList }.Show(); } /// 卡片“明细”按钮参数 → 订单明细类型(对应接口参数 OrderType) private static ShopOrderDetailType ParseDetailType(string type) { switch (type) { case "RefundOrderCount": return ShopOrderDetailType.Refund; //退款订单 case "BuyerRefundRemainingAmount": return ShopOrderDetailType.BuyerUnrefunded; //买手未退回金额的订单 case "ProfitOrder": return ShopOrderDetailType.Profit; //买手未退回金额的订单 default: return ShopOrderDetailType.Valid; //有效订单 } } public Func GetWindow; } }