利润统计 增加快递费筛选
快递费 页面支持导出全部
This commit is contained in:
1 parent
71614f64e4
commit
78a64aa661
10 files changed
+268
-126
No files matched your search
@@ -23,6 +23,10 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Models
|
||||
/// 空/Null 表示全部店铺(服务层会取全部店铺的 ErpShopId)。
|
||||
/// </summary>
|
||||
public List<string> ShopIds { get; set; }
|
||||
/// <summary>
|
||||
/// 是否统计快递费用
|
||||
/// </summary>
|
||||
public bool StatPackages { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -111,6 +115,10 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Models
|
||||
/// 被拒绝金额(分)
|
||||
/// </summary>
|
||||
public long RejectedRefund { get; set; }
|
||||
/// <summary>
|
||||
/// 包裹费用
|
||||
/// </summary>
|
||||
public long PackageAmount { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -199,6 +207,7 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Models
|
||||
/// </summary>
|
||||
public int UnrefundedAmount { get; set; }
|
||||
|
||||
public long PackageAmount { get; set; }
|
||||
/// <summary>
|
||||
/// 买手订单信息(一个订单号对应多个买手订单)
|
||||
/// </summary>
|
||||
@@ -288,6 +297,10 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Models
|
||||
public decimal BuyerRefundSuccessedAmount { get; set; }
|
||||
/// <summary>买手号剩余退款金额(尚未成功退款的金额,元)</summary>
|
||||
public decimal BuyerRefundRemainingAmount => BuyerRefundAmount - BuyerRefundSuccessedAmount;
|
||||
/// <summary>
|
||||
/// 包裹费用
|
||||
/// </summary>
|
||||
public decimal PackageAmount { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -355,6 +368,10 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Models
|
||||
|
||||
/// <summary>平均利润率(利润 / 采购金额,百分数,如 12.34 表示 12.34%)</summary>
|
||||
public decimal AverageProfitRate { get; set; }
|
||||
/// <summary>
|
||||
/// 包裹费用
|
||||
/// </summary>
|
||||
public decimal PackageAmount { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:_29WxOrderWpf.Ctrls.Statistics.ViewModels"
|
||||
xmlns:wpf="WPFCommon"
|
||||
d:DataContext="{d:DesignInstance Type=vm:ShopRevenueStatisticsViewModel,
|
||||
IsDesignTimeCreatable=True}"
|
||||
mc:Ignorable="d">
|
||||
@@ -48,9 +49,9 @@
|
||||
Width="110"
|
||||
Height="32"
|
||||
VerticalContentAlignment="Center"
|
||||
BorderThickness="1"
|
||||
DisplayMemberPath="Text"
|
||||
IsReadOnly="True"
|
||||
BorderThickness="1"
|
||||
ItemsSource="{Binding TimeRangeOptions}"
|
||||
SelectedItem="{Binding SelectedTimeRange, Mode=TwoWay}"
|
||||
Style="{StaticResource RoundedComboBox}" />
|
||||
@@ -60,9 +61,10 @@
|
||||
FontSize="14"
|
||||
Foreground="#666666"
|
||||
Text="日期" />
|
||||
<DatePicker BorderBrush="{StaticResource pageColorBrush}"
|
||||
<DatePicker
|
||||
Height="32"
|
||||
VerticalContentAlignment="Center"
|
||||
BorderBrush="{StaticResource pageColorBrush}"
|
||||
SelectedDate="{Binding StartDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<TextBlock
|
||||
Margin="6,0"
|
||||
@@ -70,9 +72,10 @@
|
||||
FontSize="14"
|
||||
Foreground="#666666"
|
||||
Text="~" />
|
||||
<DatePicker BorderBrush="{StaticResource pageColorBrush}"
|
||||
<DatePicker
|
||||
Height="32"
|
||||
VerticalContentAlignment="Center"
|
||||
BorderBrush="{StaticResource pageColorBrush}"
|
||||
SelectedDate="{Binding EndDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<TextBlock
|
||||
Margin="14,0,6,0"
|
||||
@@ -95,6 +98,14 @@
|
||||
ItemsSource="{Binding ShopOptions}"
|
||||
SelectedItem="{Binding SelectedShop, Mode=TwoWay}"
|
||||
Style="{StaticResource BaseComboBoxStyle}" />-->
|
||||
<wpf:TitleContent
|
||||
Title="去除快递费"
|
||||
Margin="10,0,0,0"
|
||||
VerticalContentAlignment="Center"
|
||||
Placement="Left"
|
||||
TitleVerticalAlignment="Center">
|
||||
<CheckBox IsChecked="{Binding StatPackages}" Style="{StaticResource ToggleSwitch}" />
|
||||
</wpf:TitleContent>
|
||||
<Button
|
||||
Height="32"
|
||||
Margin="18,0,0,0"
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services
|
||||
decimal buyerPaymentAmount = ToYuan(list.Sum(a => a.TotalPurchase));
|
||||
decimal buyerRefundAmount = ToYuan(list.Sum(a => a.TotalRefund));
|
||||
decimal buyerRefundSuccessedAmount = ToYuan(list.Sum(a => a.DoneRefund));
|
||||
|
||||
decimal packageAmount = ToYuan(list.Sum(a => a.PackageAmount));
|
||||
int validOrderCount = list.Sum(a => a.OrderCount); // 新接口 OrderCount 不含退款订单
|
||||
int refundOrderCount = list.Sum(a => a.RefundOrderCount);
|
||||
int totalOrderCount = validOrderCount + refundOrderCount;
|
||||
@@ -128,6 +128,7 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services
|
||||
BuyerPaymentAmount = buyerPaymentAmount,
|
||||
BuyerRefundAmount = buyerRefundAmount,
|
||||
BuyerRefundSuccessedAmount = buyerRefundSuccessedAmount,
|
||||
PackageAmount = packageAmount
|
||||
};
|
||||
}
|
||||
|
||||
@@ -248,7 +249,7 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services
|
||||
decimal profit = ToYuan(list.Sum(a => a.ProfitAmount));
|
||||
decimal buyerPaymentAmount = ToYuan(list.Sum(a => a.TotalPurchase));
|
||||
int orderCount = list.Sum(a => a.OrderCount);
|
||||
|
||||
decimal packageAmount = ToYuan(list.Sum(a => a.PackageAmount));
|
||||
return new ShopStatisticsItem
|
||||
{
|
||||
ShopName = ResolveShopName(shopId),
|
||||
@@ -260,7 +261,8 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services
|
||||
PlatformFeeTotal = ToYuan(list.Sum(a => a.PlatformFee)),
|
||||
Commission = 0m, // 新接口无“达人佣金”字段,保留占位
|
||||
AvgOrderAmount = orderCount == 0 ? 0m : salesAmount / orderCount,
|
||||
AverageProfitRate = buyerPaymentAmount == 0m ? 0m : profit / buyerPaymentAmount * 100m
|
||||
AverageProfitRate = buyerPaymentAmount == 0m ? 0m : profit / buyerPaymentAmount * 100m,
|
||||
PackageAmount = packageAmount
|
||||
};
|
||||
}
|
||||
|
||||
@@ -385,7 +387,13 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services
|
||||
// 顺序请求:签名中的 time/code 由当前时间生成,并发请求有被判重复签名的风险。
|
||||
var summaryStats = await RequestStatsAsync(query, ShopStatsGroupType.Summary);
|
||||
var trend = await RequestTrendAsync(query);
|
||||
|
||||
if (query.StatPackages)
|
||||
{
|
||||
foreach (var item in summaryStats)
|
||||
{
|
||||
item.ProfitAmount -= item.PackageAmount;
|
||||
}
|
||||
}
|
||||
return new ShopRevenueStatisticsResult
|
||||
{
|
||||
Summary = ShopStatsAggregator.GetSummary(summaryStats),
|
||||
@@ -399,7 +407,13 @@ namespace _29WxOrderWpf.Ctrls.Statistics.Services
|
||||
{
|
||||
// 按天/周/月粒度取数;接口不返回整段汇总,卡片由返回的周期记录在客户端合计
|
||||
var stats = await RequestStatsAsync(query, ToGroupType(periodType));
|
||||
|
||||
if (query.StatPackages)
|
||||
{
|
||||
foreach (var item in stats)
|
||||
{
|
||||
item.ProfitAmount -= item.PackageAmount;
|
||||
}
|
||||
}
|
||||
return new ShopPeriodStatisticsResult
|
||||
{
|
||||
Summary = ShopStatsAggregator.GetSummary(stats),
|
||||
|
||||
@@ -274,30 +274,32 @@
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
<!-- helper -->
|
||||
<Border
|
||||
Margin="0,20,30,0"
|
||||
Padding="10"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{StaticResource pageColorBrush}"
|
||||
BorderThickness="1"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonDown="help_mouseLeftButtonDown">
|
||||
<WrapPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Foreground="White"
|
||||
Style="{StaticResource TextBlockIcon}"
|
||||
Text="{StaticResource txt-chat_help}" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="Black"
|
||||
Foreground="White"
|
||||
Text="利润计算逻辑" />
|
||||
</WrapPanel>
|
||||
</Border>
|
||||
|
||||
<WrapPanel
|
||||
Margin="0,20,30,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top">
|
||||
<Border
|
||||
Padding="10"
|
||||
Background="{StaticResource pageColorBrush}"
|
||||
BorderThickness="1"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonDown="help_mouseLeftButtonDown">
|
||||
<WrapPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Foreground="White"
|
||||
Style="{StaticResource TextBlockIcon}"
|
||||
Text="{StaticResource txt-chat_help}" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="Black"
|
||||
Foreground="White"
|
||||
Text="利润计算逻辑" />
|
||||
</WrapPanel>
|
||||
</Border>
|
||||
</WrapPanel>
|
||||
<!-- Popup 弹出层 -->
|
||||
<Popup
|
||||
x:Name="InfoPopup"
|
||||
|
||||
@@ -157,7 +157,11 @@
|
||||
Binding="{Binding ProfitAmount, Converter={StaticResource FenToYuanConverter}, StringFormat={}¥{0:N2}}"
|
||||
ElementStyle="{StaticResource CenterCellTextStyle}"
|
||||
Header="利润" />
|
||||
|
||||
<DataGridTextColumn
|
||||
Width="*"
|
||||
Binding="{Binding PackageAmount, Converter={StaticResource FenToYuanConverter}, StringFormat={}¥{0:N2}}"
|
||||
ElementStyle="{StaticResource CenterCellTextStyle}"
|
||||
Header="快递费" />
|
||||
<!-- 买手订单:一笔买手订单占一行,不合并 -->
|
||||
<DataGridTextColumn
|
||||
Width="1.6*"
|
||||
|
||||
@@ -166,7 +166,10 @@ class ShopOrderDetailRow : BindableBaseEx
|
||||
/// 利润
|
||||
/// </summary>
|
||||
public long ProfitAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 包裹费用
|
||||
/// </summary>
|
||||
public long PackageAmount { get; set; }
|
||||
/// <summary>
|
||||
/// 平台佣金
|
||||
/// </summary>
|
||||
@@ -246,6 +249,7 @@ class ShopOrderDetailRow : BindableBaseEx
|
||||
OrderPrice = item.OrderPrice,
|
||||
OrderRefundAmount = item.OrderRefundAmount,
|
||||
ProfitAmount = item.ProfitAmount,
|
||||
PackageAmount = item.PackageAmount,
|
||||
PlatformFee = item.PlatformFee,
|
||||
OutAmount = item.OutAmount,
|
||||
UnrefundedAmount = item.UnrefundedAmount,
|
||||
@@ -411,7 +415,7 @@ class ShowOrderDialogViewModel : BindableBaseEx
|
||||
bool includeRemark = _detailType == ShopOrderDetailType.BuyerUnrefunded;
|
||||
|
||||
// 表头
|
||||
List<string> headers = ["店名", "订单", "创建时间", "金额", "退款金额", "平台费用", "利润", "买手单号", "外采金额", "买手退款", "退款状态"];
|
||||
List<string> headers = ["店名", "订单", "创建时间", "金额", "退款金额", "平台费用", "利润","快递费", "买手单号", "外采金额", "买手退款", "退款状态"];
|
||||
if (includeRemark)
|
||||
headers.Add("备注");
|
||||
sb.AppendLine(string.Join("\t", headers));
|
||||
@@ -428,6 +432,7 @@ class ShowOrderDialogViewModel : BindableBaseEx
|
||||
(item.OrderRefundAmount / 100m).ToString("0.00"),
|
||||
(item.PlatformFee / 100m).ToString("0.00"),
|
||||
(item.ProfitAmount / 100m).ToString("0.00"),
|
||||
(item.PackageAmount / 100m).ToString("0.00"),
|
||||
CsvEscape(item.OutOrderSn),
|
||||
(item.BuyerOutAmount / 100m).ToString("0.00"),
|
||||
(item.BuyerRefundAmount / 100m).ToString("0.00"),
|
||||
|
||||
@@ -177,7 +177,11 @@ namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels
|
||||
#endregion
|
||||
|
||||
#region 查询条件
|
||||
|
||||
public bool StatPackages
|
||||
{
|
||||
get { return this.GetValue(x => x.StatPackages); }
|
||||
set { this.SetValue(x => x.StatPackages, value); }
|
||||
}
|
||||
/// <summary>时间范围选项</summary>
|
||||
public ObservableCollection<TimeRangeOption> TimeRangeOptions { get; }
|
||||
|
||||
@@ -455,20 +459,20 @@ namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels
|
||||
EndDate = now;
|
||||
break;
|
||||
case "week":
|
||||
{
|
||||
int diff = today.DayOfWeek == DayOfWeek.Sunday ? 6 : (int)today.DayOfWeek - 1;
|
||||
StartDate = today.AddDays(-diff);
|
||||
EndDate = now;
|
||||
}
|
||||
break;
|
||||
{
|
||||
int diff = today.DayOfWeek == DayOfWeek.Sunday ? 6 : (int)today.DayOfWeek - 1;
|
||||
StartDate = today.AddDays(-diff);
|
||||
EndDate = now;
|
||||
}
|
||||
break;
|
||||
case "lastweek":
|
||||
{
|
||||
int diff = today.DayOfWeek == DayOfWeek.Sunday ? 6 : (int)today.DayOfWeek - 1;
|
||||
var thisWeekStart = today.AddDays(-diff);
|
||||
StartDate = thisWeekStart.AddDays(-7);
|
||||
EndDate = thisWeekStart.AddDays(-1).AddHours(23).AddMinutes(59).AddSeconds(59);
|
||||
}
|
||||
break;
|
||||
{
|
||||
int diff = today.DayOfWeek == DayOfWeek.Sunday ? 6 : (int)today.DayOfWeek - 1;
|
||||
var thisWeekStart = today.AddDays(-diff);
|
||||
StartDate = thisWeekStart.AddDays(-7);
|
||||
EndDate = thisWeekStart.AddDays(-1).AddHours(23).AddMinutes(59).AddSeconds(59);
|
||||
}
|
||||
break;
|
||||
case "last2weeks":
|
||||
StartDate = today.AddDays(-13);
|
||||
EndDate = now;
|
||||
@@ -482,12 +486,12 @@ namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels
|
||||
EndDate = now;
|
||||
break;
|
||||
case "lastmonth":
|
||||
{
|
||||
var firstOfThisMonth = new DateTime(today.Year, today.Month, 1);
|
||||
StartDate = firstOfThisMonth.AddMonths(-1);
|
||||
EndDate = firstOfThisMonth.AddDays(-1).AddHours(23).AddMinutes(59).AddSeconds(59);
|
||||
}
|
||||
break;
|
||||
{
|
||||
var firstOfThisMonth = new DateTime(today.Year, today.Month, 1);
|
||||
StartDate = firstOfThisMonth.AddMonths(-1);
|
||||
EndDate = firstOfThisMonth.AddDays(-1).AddHours(23).AddMinutes(59).AddSeconds(59);
|
||||
}
|
||||
break;
|
||||
case "last3months":
|
||||
StartDate = new DateTime(today.Year, today.Month, 1).AddMonths(-2);
|
||||
EndDate = now;
|
||||
@@ -541,6 +545,7 @@ namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels
|
||||
StartDate = StartDate,
|
||||
EndDate = EndDate,
|
||||
ShopIds = BuildSelectedShopIds(),
|
||||
StatPackages = StatPackages
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,11 @@ namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels
|
||||
|
||||
InitializeAsync();
|
||||
}
|
||||
public bool StatPackages
|
||||
{
|
||||
get { return this.GetValue(x => x.StatPackages); }
|
||||
set { this.SetValue(x => x.StatPackages, value); }
|
||||
}
|
||||
|
||||
#region 查询条件
|
||||
|
||||
@@ -288,6 +293,7 @@ namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels
|
||||
StartDate = StartDate,
|
||||
EndDate = EndDate,
|
||||
ShopIds = BuildSelectedShopIds(),
|
||||
StatPackages = StatPackages,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -298,7 +304,7 @@ namespace _29WxOrderWpf.Ctrls.Statistics.ViewModels
|
||||
try
|
||||
{
|
||||
var result = await _service.QueryAsync(BuildQuery());
|
||||
|
||||
|
||||
Summary = result.Summary;
|
||||
TrendData = new ObservableCollection<RevenueTrendPoint>(result.Trend ?? new List<RevenueTrendPoint>());
|
||||
ShopProportionData = new ObservableCollection<ShopSalesProportionItem>(result.ShopProportions ?? new List<ShopSalesProportionItem>());
|
||||
|
||||
@@ -141,57 +141,75 @@ namespace Work._29Tools.Forms.UserForms
|
||||
}
|
||||
|
||||
private List<user_payment_record> paymentList;
|
||||
public async void GetBalanceList()
|
||||
private string GetBalanceFilters()
|
||||
{
|
||||
int pageCount = 1;
|
||||
int pageSize = 50;
|
||||
var data3 = "&user_name_in=" + BaseClass.UserName;
|
||||
data3 += "&create_time_begin=" + dtpTimeBegin.Value.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
data3 += "&create_time_end=" + dtpTimeEnd.Value.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
if (cmbType.Text == "充值")
|
||||
data3 += "&type_in=1,30";
|
||||
else if (cmbType.Text == "管理员充值")
|
||||
data3 += "&type_in=1";
|
||||
else if (cmbType.Text == "支付宝充值")
|
||||
data3 += "&type_in=30";
|
||||
else if (cmbType.Text == "礼物单支出/礼物单退费")
|
||||
data3 += "&type_in=16,34";
|
||||
else if (cmbType.Text == "拍单扣除/作废返还")
|
||||
data3 += "&type_in=20,23";
|
||||
else if (cmbType.Text == "超重扣费支出")
|
||||
data3 += "&type_in=24,28,33,37,41";
|
||||
else if (cmbType.Text == "退货包裹扣费支出/返还")
|
||||
data3 += "&type_in=26,38";
|
||||
else if (cmbType.Text == "额外包裹扣费支出/返还")
|
||||
data3 += "&type_in=35,36";
|
||||
else if (cmbType.Text == "云仓退货扣费支出")
|
||||
data3 += "&type_in=31";
|
||||
if (!string.IsNullOrEmpty(txtOutOrderId.Text.Trim()))
|
||||
data3 += "&order_id_in=" + txtOutOrderId.Text.Trim();
|
||||
if (!string.IsNullOrEmpty(txtShopOrderNo.Text.Trim()))
|
||||
data3 += "&remark_fulltext=" + txtShopOrderNo.Text.Trim();
|
||||
return data3;
|
||||
}
|
||||
|
||||
private static List<user_payment_record> ReadBalancePage(string filters, int page, int pageSize, out int count, out decimal seconds)
|
||||
{
|
||||
var url = BaseClass.Build29WxObjString("user/get_user_balance");
|
||||
var data = UserLogin.GetSignaturex() + filters + "&page=" + page + "&page_size=" + pageSize;
|
||||
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"))
|
||||
throw new InvalidOperationException($"第 {page} 页查询失败:" + (string.IsNullOrEmpty(html) ? "服务器无响应" : BaseRegex.GetStringJsonByRegs(ref html, html, "msg")));
|
||||
|
||||
var result = JObject.Parse(html);
|
||||
count = (int)result["count"];
|
||||
seconds = BaseRegex.GetDecimalJson(ref html, "seconds");
|
||||
return JsonConvert.DeserializeObject<List<user_payment_record>>(result["data"]?.ToString() ?? "null") ?? throw new InvalidOperationException($"第 {page} 页缺少消费记录");
|
||||
}
|
||||
|
||||
public void GetBalanceList()
|
||||
{
|
||||
int page = 1, pageSize = 50;
|
||||
string filters = null;
|
||||
Invoke(new Action(() =>
|
||||
{
|
||||
this.dgvPayment.Rows.Clear();
|
||||
}));
|
||||
var url3 = BaseClass.Build29WxObjString("user/get_user_balance");
|
||||
var data3 = UserLogin.GetSignaturex();
|
||||
Invoke(new Action(() =>
|
||||
{
|
||||
data3 += "&user_name_in=" + BaseClass.UserName;
|
||||
data3 += "&create_time_begin=" + dtpTimeBegin.Value.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
data3 += "&create_time_end=" + dtpTimeEnd.Value.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
if (cmbType.Text == "充值")
|
||||
data3 += "&type_in=1,30";
|
||||
else if (cmbType.Text == "管理员充值")
|
||||
data3 += "&type_in=1";
|
||||
else if (cmbType.Text == "支付宝充值")
|
||||
data3 += "&type_in=30";
|
||||
else if (cmbType.Text == "礼物单支出/礼物单退费")
|
||||
data3 += "&type_in=16,34";
|
||||
else if (cmbType.Text == "拍单扣除/作废返还")
|
||||
data3 += "&type_in=20,23";
|
||||
else if (cmbType.Text == "超重扣费支出")
|
||||
data3 += "&type_in=24,28,33,37,41";
|
||||
else if (cmbType.Text == "退货包裹扣费支出/返还")
|
||||
data3 += "&type_in=26,38";
|
||||
else if (cmbType.Text == "额外包裹扣费支出/返还")
|
||||
data3 += "&type_in=35,36";
|
||||
else if (cmbType.Text == "云仓退货扣费支出")
|
||||
data3 += "&type_in=31";
|
||||
if (!string.IsNullOrEmpty(txtOutOrderId.Text.Trim()))
|
||||
data3 += "&order_id_in=" + txtOutOrderId.Text.Trim();
|
||||
if (!string.IsNullOrEmpty(txtShopOrderNo.Text.Trim()))
|
||||
data3 += "&remark_fulltext=" + txtShopOrderNo.Text.Trim();
|
||||
data3 += "&page=" + ucSplitPage1.CurrentPage;
|
||||
data3 += "&page_size=" + ucSplitPage1.PageSize;
|
||||
paymentList = null;
|
||||
filters = GetBalanceFilters();
|
||||
page = ucSplitPage1.CurrentPage;
|
||||
pageSize = ucSplitPage1.PageSize;
|
||||
}));
|
||||
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"))
|
||||
int count;
|
||||
decimal seconds;
|
||||
try
|
||||
{
|
||||
BaseMsgForm.ShowError("查询失败:" + BaseRegex.GetStringJsonByRegs(ref html3, html3, "msg"));
|
||||
paymentList = ReadBalancePage(filters, page, pageSize, out count, out seconds);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
BaseMsgForm.ShowError("查询失败:" + ex.Message);
|
||||
return;
|
||||
}
|
||||
paymentList = new List<user_payment_record>();
|
||||
paymentList = JsonHelper.DeserializeJsonToList<user_payment_record>(JsonHelper.JObjectParse(html3)["data"].ParseToString());
|
||||
foreach (var payment in paymentList)
|
||||
{
|
||||
if (!this.Created)
|
||||
@@ -210,12 +228,11 @@ namespace Work._29Tools.Forms.UserForms
|
||||
this.dgvPayment.Rows[rowIndex].Height = 60;
|
||||
}));
|
||||
}
|
||||
int count = BaseRegex.GetIntJson(ref html3, "count");
|
||||
pageCount = Math.Ceiling(1.0 * count / pageSize).ParseToInt();
|
||||
int pageCount = Math.Ceiling(1.0 * count / pageSize).ParseToInt();
|
||||
pageCount = Math.Max(pageCount, 1);
|
||||
ucSplitPage1.TotalPage = pageCount;
|
||||
#if DEBUG
|
||||
Invoke(new Action(() => { statusBarUserControl1.lblTaskStatus.Text = BaseRegex.GetDecimalJson(ref html3, "seconds") + "秒"; }));
|
||||
Invoke(new Action(() => { statusBarUserControl1.lblTaskStatus.Text = seconds + "秒"; }));
|
||||
#endif
|
||||
Invoke(new Action(() =>
|
||||
{
|
||||
@@ -275,7 +292,20 @@ namespace Work._29Tools.Forms.UserForms
|
||||
|
||||
private void exportRecord_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
if (paymentList != null)
|
||||
var menu = new ContextMenuStrip();
|
||||
menu.Items.Add("导出当页", null, async (s, args) => await ExportRecords(false)).Enabled = paymentList != null;
|
||||
menu.Items.Add("导出全部", null, async (s, args) => await ExportRecords(true));
|
||||
menu.Closed += (s, args) => BeginInvoke(new Action(menu.Dispose));
|
||||
menu.Show(exportRecord, 0, exportRecord.Height);
|
||||
}
|
||||
|
||||
private async Task ExportRecords(bool allPages)
|
||||
{
|
||||
var records = paymentList;
|
||||
var filters = GetBalanceFilters();
|
||||
int pageSize = ucSplitPage1.PageSize;
|
||||
exportRecord.Enabled = false;
|
||||
try
|
||||
{
|
||||
using (SaveFileDialog saveFileDialog = new SaveFileDialog())
|
||||
{
|
||||
@@ -285,40 +315,86 @@ namespace Work._29Tools.Forms.UserForms
|
||||
saveFileDialog.RestoreDirectory = true;
|
||||
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("类型,订单ID,金额,余额,创建时间,备注");
|
||||
|
||||
foreach (var item in paymentList)
|
||||
if (allPages)
|
||||
{
|
||||
//var rowIndex = this.dgvPayment.Rows.Add(
|
||||
// false,
|
||||
// ((EnumOrderPaymentType)payment.type.ParseToInt()).ParseToString(),
|
||||
// item.order_id,
|
||||
// item.amount,
|
||||
// item.balance,
|
||||
// item.create_time.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
// item.remark
|
||||
//);
|
||||
string type = "未知";
|
||||
if (item.type.HasValue)
|
||||
{
|
||||
if (Enum.TryParse<EnumOrderPaymentType>(item.type.Value.ToString(), out EnumOrderPaymentType v))
|
||||
{
|
||||
type = v.ToString();
|
||||
}
|
||||
}
|
||||
statusBarUserControl1.pgbTaskProgress.Maximum = 100;
|
||||
statusBarUserControl1.InitProgressBar();
|
||||
statusBarUserControl1.UpdateProgressBarStatus("正在读取第 1 页…");
|
||||
records = await ReadAllBalancePages(filters, pageSize);
|
||||
statusBarUserControl1.UpdateProgressBarStatus($"正在保存 {records.Count} 条记录…");
|
||||
}
|
||||
|
||||
|
||||
sb.AppendLine($"{type},{item.order_id},{item.amount},{item.balance},{item.create_time.ToString("yyyy-MM-dd HH:mm:ss")},{item.remark}");
|
||||
var fileName = saveFileDialog.FileName;
|
||||
await Task.Run(() => SaveBalanceRecords(fileName, records));
|
||||
if (allPages && !IsDisposed)
|
||||
{
|
||||
statusBarUserControl1.UpdateProgressBar(100);
|
||||
statusBarUserControl1.FinishProgressBar($"导出完成,共 {records.Count} 条记录");
|
||||
}
|
||||
File.WriteAllText(saveFileDialog.FileName, sb.ToString(), Encoding.UTF8);
|
||||
MessageBox.Show("导出成功");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (allPages && !IsDisposed)
|
||||
statusBarUserControl1.UpdateProgressBarStatus("导出失败:" + ex.Message);
|
||||
BaseMsgForm.ShowError("导出失败:" + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!IsDisposed)
|
||||
exportRecord.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveBalanceRecords(string fileName, List<user_payment_record> records)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("类型,订单ID,金额,余额,创建时间,备注");
|
||||
|
||||
foreach (var item in records)
|
||||
{
|
||||
string type = "未知";
|
||||
if (item.type.HasValue)
|
||||
{
|
||||
if (Enum.TryParse<EnumOrderPaymentType>(item.type.Value.ToString(), out EnumOrderPaymentType v))
|
||||
{
|
||||
type = v.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sb.AppendLine($"{type},{item.order_id},{item.amount},{item.balance},{item.create_time.ToString("yyyy-MM-dd HH:mm:ss")},{item.remark}");
|
||||
}
|
||||
File.WriteAllText(fileName, sb.ToString(), Encoding.UTF8);
|
||||
}
|
||||
|
||||
private async Task<List<user_payment_record>> ReadAllBalancePages(string filters, int pageSize)
|
||||
{
|
||||
var records = new List<user_payment_record>();
|
||||
int expectedCount = 0;
|
||||
for (int page = 1; ; page++)
|
||||
{
|
||||
int count = 0;
|
||||
var batch = await Task.Run(() => ReadBalancePage(filters, page, pageSize, out count, out _));
|
||||
if (page == 1)
|
||||
expectedCount = count;
|
||||
if (count != expectedCount || batch.Count != Math.Min(pageSize, expectedCount - records.Count))
|
||||
throw new InvalidOperationException($"第 {page} 页记录数有变化,请重新导出。");
|
||||
|
||||
records.AddRange(batch);
|
||||
int totalPages = Math.Max(1, (int)Math.Ceiling((double)expectedCount / pageSize));
|
||||
statusBarUserControl1.UpdateProgressBar((int)(99L * page / totalPages));
|
||||
statusBarUserControl1.UpdateProgressBarStatus($"已读取 {page}/{totalPages} 页,共 {records.Count}/{expectedCount} 条");
|
||||
if (records.Count == expectedCount)
|
||||
{
|
||||
Debug.Assert(page == totalPages);
|
||||
return records;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GetUserAmountSummary()
|
||||
{
|
||||
|
||||
@@ -24,7 +24,9 @@ namespace WxOrder.Framework.Commons
|
||||
public DialogWindow(Window owner = null)
|
||||
{
|
||||
InitializeComponent();
|
||||
Owner = owner ?? Application.Current.MainWindow;
|
||||
Owner = owner ?? Application.Current.Windows
|
||||
.OfType<Window>()
|
||||
.FirstOrDefault(w => w.IsActive) ?? Application.Current.MainWindow;
|
||||
isConstructorSuccessful = true;
|
||||
dialogWindowStyle = (Style)TryFindResource("DialogWindowStyle");
|
||||
Loaded += DialogWindow_Loaded;
|
||||
|
||||
Reference in new issue
Block a user