128 lines
4.9 KiB
C#
128 lines
4.9 KiB
C#
using Prism.Commands;
|
|
using Prism.Services.Dialogs;
|
|
using Store.Management.Api.Transport;
|
|
using Store.Management.Api.Users;
|
|
using Store.Management.Framework.Controls;
|
|
using Store.Management.Framework.Services;
|
|
using NumericUpDown = HandyControl.Controls.NumericUpDown;
|
|
using System.Globalization;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
|
|
namespace Store.Management.Views.Dialogs;
|
|
|
|
public partial class UserBillingDialog : UserControl
|
|
{
|
|
public UserBillingDialog() => InitializeComponent();
|
|
|
|
private void OnAmountValueChanged(object sender, HandyControl.Data.FunctionEventArgs<double> e)
|
|
{
|
|
if (sender is NumericUpDown { IsKeyboardFocusWithin: true, DataContext: UserBillingDialogViewModel.BillingField field })
|
|
{
|
|
field.Value = (decimal)e.Info;
|
|
}
|
|
}
|
|
|
|
private void OnAmountTextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
// 显式输入与控件初始值相同的金额时,Value 不会触发变化。
|
|
if (sender is NumericUpDown { IsKeyboardFocusWithin: true, DataContext: UserBillingDialogViewModel.BillingField field }
|
|
&& e.OriginalSource is TextBox input
|
|
&& decimal.TryParse(input.Text, NumberStyles.Number, CultureInfo.CurrentCulture, out decimal amount)
|
|
&& amount == field.Value)
|
|
{
|
|
field.Value = amount;
|
|
}
|
|
}
|
|
}
|
|
|
|
public sealed class UserBillingDialogViewModel(IUserService userService) : ConfirmDialogViewModel<UserInfo>
|
|
{
|
|
public sealed class BillingField(string label, decimal? original, decimal minimum,
|
|
Action<UserBillingUpdateRequest, decimal> apply, bool integer = false)
|
|
{
|
|
private readonly decimal? originalValue = original;
|
|
public string Label { get; } = label;
|
|
public decimal? EnteredValue { get; private set; } = original;
|
|
public decimal Value
|
|
{
|
|
get => EnteredValue ?? minimum;
|
|
set => EnteredValue = value;
|
|
}
|
|
public decimal Minimum => Math.Min(originalValue ?? minimum, minimum);
|
|
public decimal Maximum => Math.Max(originalValue ?? minimum, integer ? int.MaxValue : 999999m);
|
|
public int DecimalPlaces => integer ? 0 : 2;
|
|
public decimal Increment => integer ? 1m : 0.01m;
|
|
|
|
internal bool ApplyChange(UserBillingUpdateRequest request)
|
|
{
|
|
if (EnteredValue is not decimal value || value == originalValue)
|
|
{
|
|
return false;
|
|
}
|
|
decimal maximum = integer ? int.MaxValue : 999999m;
|
|
if (value < minimum || value > maximum || decimal.Round(value, DecimalPlaces) != value)
|
|
{
|
|
throw new FormatException($"{Label}范围为 {minimum} 至 {maximum}" + (integer ? ",请输入整数。" : ",最多两位小数。"));
|
|
}
|
|
apply(request, value);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public BillingField[] Fields { get; private set => SetProperty(ref field, value); } = [];
|
|
|
|
public override void OnDialogOpened(IDialogParameters parameters)
|
|
{
|
|
base.OnDialogOpened(parameters);
|
|
Title = $"计费配置 · {Parameter.UserName}";
|
|
Fields =
|
|
[
|
|
new("店铺每月续费积分(积分/月)", Parameter.ShopPointsPerMonth, 30m, (request, value) => request.ShopPointsPerMonth = (int)value, integer: true),
|
|
new("中转仓快递费(元/单)", Parameter.PostagePerOrder, 2.20m, (request, value) => request.PostagePerOrder = value),
|
|
new("中转仓退货快递费(元/单)", Parameter.RefundPostagePerOrder, 2.50m, (request, value) => request.RefundPostagePerOrder = value),
|
|
new("礼物单附加费(元/单)", Parameter.GiftOemAmountPerOrder, 0m, (request, value) => request.GiftOemAmountPerOrder = value),
|
|
new("物流同步费(元/单)", Parameter.SyncLogisticsPerOrder, 0m, (request, value) => request.SyncLogisticsPerOrder = value)
|
|
];
|
|
}
|
|
|
|
public override bool CanCloseDialog() => !IsLoading;
|
|
public override ICommand ConfirmCommand => field ??= new AsyncDelegateCommand(SaveAsync);
|
|
|
|
private async Task SaveAsync()
|
|
{
|
|
var request = new UserBillingUpdateRequest { Id = Parameter.Id };
|
|
try
|
|
{
|
|
bool changed = false;
|
|
foreach (BillingField field in Fields)
|
|
{
|
|
changed |= field.ApplyChange(request);
|
|
}
|
|
if (!changed)
|
|
{
|
|
OnRequestClose(new DialogResult(ButtonResult.Cancel));
|
|
return;
|
|
}
|
|
ErrorMsg = "";
|
|
IsLoading = true;
|
|
await userService.UpdateBillingAsync(request);
|
|
}
|
|
catch (FormatException ex)
|
|
{
|
|
ErrorMsg = ex.Message;
|
|
return;
|
|
}
|
|
catch (ApiException ex)
|
|
{
|
|
ErrorMsg = ex.Message;
|
|
return;
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
OnRequestClose(new DialogResult(ButtonResult.OK));
|
|
}
|
|
}
|