289 lines
11 KiB
C#
289 lines
11 KiB
C#
using HandyControl.Controls;
|
||
using HandyControl.Tools.Extension;
|
||
using Prism.Events;
|
||
using System.Collections.ObjectModel;
|
||
using System.Diagnostics;
|
||
using System.Windows;
|
||
using YY.Admin.Core;
|
||
using YY.Admin.Core.Events;
|
||
using YY.Admin.Core.Helper;
|
||
using YY.Admin.Core.Entity;
|
||
using YY.Admin.Core.Services;
|
||
using YY.Admin.Services.Service;
|
||
using YY.Admin.Services.Service.Customer;
|
||
using YY.Admin.Views.Customer;
|
||
|
||
namespace YY.Admin.ViewModels.Customer;
|
||
|
||
public class CustomerListViewModel : BaseViewModel
|
||
{
|
||
private readonly ICustomerService _customerService;
|
||
private readonly IJeecgDictSyncService _dictSyncService;
|
||
private readonly IDialogService _dialogService;
|
||
private SubscriptionToken? _customerChangedToken;
|
||
private SubscriptionToken? _syncConflictToken;
|
||
|
||
private ObservableCollection<MesXslCustomer> _customers = new();
|
||
public ObservableCollection<MesXslCustomer> Customers
|
||
{
|
||
get => _customers;
|
||
set => SetProperty(ref _customers, value);
|
||
}
|
||
|
||
private long _total;
|
||
public long Total { get => _total; set => SetProperty(ref _total, value); }
|
||
|
||
private int _pageNo = 1;
|
||
public int PageNo { get => _pageNo; set => SetProperty(ref _pageNo, value); }
|
||
|
||
private int _pageSize = 20;
|
||
public int PageSize { get => _pageSize; set => SetProperty(ref _pageSize, value); }
|
||
|
||
private string? _filterCustomerCode;
|
||
public string? FilterCustomerCode { get => _filterCustomerCode; set => SetProperty(ref _filterCustomerCode, value); }
|
||
|
||
private string? _filterCustomerName;
|
||
public string? FilterCustomerName { get => _filterCustomerName; set => SetProperty(ref _filterCustomerName, value); }
|
||
|
||
private string? _filterStatus;
|
||
public string? FilterStatus { get => _filterStatus; set => SetProperty(ref _filterStatus, value); }
|
||
|
||
private string? _filterCustomerRegion;
|
||
public string? FilterCustomerRegion { get => _filterCustomerRegion; set => SetProperty(ref _filterCustomerRegion, value); }
|
||
|
||
public ObservableCollection<KeyValuePair<string, string>> StatusOptions { get; } = new();
|
||
public ObservableCollection<KeyValuePair<string, string>> CustomerRegionOptions { get; } = new();
|
||
|
||
public DelegateCommand SearchCommand { get; }
|
||
public DelegateCommand ResetCommand { get; }
|
||
public DelegateCommand AddCommand { get; }
|
||
public DelegateCommand<MesXslCustomer> EditCommand { get; }
|
||
public DelegateCommand<MesXslCustomer> DeleteCommand { get; }
|
||
public DelegateCommand<MesXslCustomer> ToggleStatusCommand { get; }
|
||
public DelegateCommand PrevPageCommand { get; }
|
||
public DelegateCommand NextPageCommand { get; }
|
||
|
||
public CustomerListViewModel(
|
||
ICustomerService customerService,
|
||
IJeecgDictSyncService dictSyncService,
|
||
IContainerExtension container,
|
||
IDialogService dialogService,
|
||
IRegionManager regionManager) : base(container, regionManager)
|
||
{
|
||
_customerService = customerService;
|
||
_dictSyncService = dictSyncService;
|
||
_dialogService = dialogService;
|
||
|
||
SearchCommand = new DelegateCommand(async () => { PageNo = 1; await LoadAsync(); });
|
||
ResetCommand = new DelegateCommand(async () =>
|
||
{
|
||
FilterCustomerCode = null; FilterCustomerName = null;
|
||
FilterStatus = null; FilterCustomerRegion = null;
|
||
PageNo = 1; await LoadAsync();
|
||
});
|
||
AddCommand = new DelegateCommand(async () => await ShowAddDialogAsync());
|
||
EditCommand = new DelegateCommand<MesXslCustomer>(async c => await ShowEditDialogAsync(c));
|
||
DeleteCommand = new DelegateCommand<MesXslCustomer>(async c => await DeleteAsync(c));
|
||
ToggleStatusCommand = new DelegateCommand<MesXslCustomer>(async c => await ToggleStatusAsync(c));
|
||
PrevPageCommand = new DelegateCommand(async () => { if (PageNo > 1) { PageNo--; await LoadAsync(); } });
|
||
NextPageCommand = new DelegateCommand(async () => { if ((long)PageNo * PageSize < Total) { PageNo++; await LoadAsync(); } });
|
||
|
||
_customerChangedToken = _eventAggregator.GetEvent<CustomerChangedEvent>()
|
||
.Subscribe(async p => await OnCustomerChangedAsync(p), ThreadOption.UIThread);
|
||
|
||
_syncConflictToken = _eventAggregator.GetEvent<SyncConflictEvent>()
|
||
.Subscribe(OnSyncConflict, ThreadOption.UIThread);
|
||
|
||
_ = InitializeAsync();
|
||
}
|
||
|
||
private async Task OnCustomerChangedAsync(CustomerChangedPayload payload)
|
||
{
|
||
if (payload.Action == "edit" && !string.IsNullOrWhiteSpace(payload.CustomerId))
|
||
{
|
||
await RefreshSingleAsync(payload.CustomerId!);
|
||
}
|
||
else
|
||
{
|
||
await LoadAsync();
|
||
}
|
||
}
|
||
|
||
private async Task RefreshSingleAsync(string customerId)
|
||
{
|
||
try
|
||
{
|
||
var updated = await _customerService.GetByIdAsync(customerId);
|
||
if (updated == null) return;
|
||
var idx = Customers.ToList().FindIndex(c => string.Equals(c.Id, customerId, StringComparison.OrdinalIgnoreCase));
|
||
if (idx >= 0)
|
||
Customers[idx] = updated;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"[客户] 单条刷新失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void OnSyncConflict(SyncConflictPayload payload)
|
||
{
|
||
if (!string.Equals(payload.EntityName, "客户", StringComparison.OrdinalIgnoreCase)) return;
|
||
|
||
var parts = new List<string>();
|
||
if (payload.PushedCount > 0)
|
||
parts.Add($"已同步 {payload.PushedCount} 条本地改动到服务器");
|
||
if (payload.NewRecordsPushed > 0)
|
||
parts.Add($"已上传 {payload.NewRecordsPushed} 条本地新增记录");
|
||
if (payload.ConflictCount > 0)
|
||
parts.Add($"{payload.ConflictCount} 条记录与服务器版本冲突,已保留服务器版本");
|
||
|
||
if (parts.Count == 0) return;
|
||
|
||
var message = string.Join("\n", parts);
|
||
if (payload.ConflictCount > 0)
|
||
Growl.Warning(message);
|
||
else
|
||
Growl.Success(message);
|
||
}
|
||
|
||
private async Task InitializeAsync()
|
||
{
|
||
try
|
||
{
|
||
await LoadDictOptionsAsync();
|
||
await UIHelper.WaitForRenderAsync();
|
||
await LoadAsync();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"客户列表初始化失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private async Task LoadDictOptionsAsync()
|
||
{
|
||
try
|
||
{
|
||
var statusOpts = await _dictSyncService.GetDictOptionsAsync("xslmes_customer_status", includeAll: true);
|
||
var regionOpts = await _dictSyncService.GetDictOptionsAsync("xslmes_customer_region", includeAll: true);
|
||
|
||
StatusOptions.Clear();
|
||
foreach (var item in statusOpts) StatusOptions.Add(item);
|
||
CustomerRegionOptions.Clear();
|
||
foreach (var item in regionOpts) CustomerRegionOptions.Add(item);
|
||
|
||
if (StatusOptions.Count == 0)
|
||
{
|
||
StatusOptions.Add(new KeyValuePair<string, string>("全部", ""));
|
||
StatusOptions.Add(new KeyValuePair<string, string>("启用", "0"));
|
||
StatusOptions.Add(new KeyValuePair<string, string>("停用", "1"));
|
||
}
|
||
if (CustomerRegionOptions.Count == 0)
|
||
CustomerRegionOptions.Add(new KeyValuePair<string, string>("全部", ""));
|
||
}
|
||
catch
|
||
{
|
||
StatusOptions.Clear();
|
||
StatusOptions.Add(new KeyValuePair<string, string>("全部", ""));
|
||
StatusOptions.Add(new KeyValuePair<string, string>("启用", "0"));
|
||
StatusOptions.Add(new KeyValuePair<string, string>("停用", "1"));
|
||
CustomerRegionOptions.Clear();
|
||
CustomerRegionOptions.Add(new KeyValuePair<string, string>("全部", ""));
|
||
}
|
||
}
|
||
|
||
public async Task LoadAsync()
|
||
{
|
||
try
|
||
{
|
||
IsLoading = true;
|
||
var result = await _customerService.PageAsync(PageNo, PageSize,
|
||
FilterCustomerCode, FilterCustomerName, FilterStatus, FilterCustomerRegion);
|
||
Customers = new ObservableCollection<MesXslCustomer>(result.Records);
|
||
Total = result.Total;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Growl.Error($"加载客户列表失败:{ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
IsLoading = false;
|
||
}
|
||
}
|
||
|
||
private async Task ShowAddDialogAsync()
|
||
{
|
||
try
|
||
{
|
||
var result = await HandyControl.Controls.Dialog.Show<CustomerEditDialogView>()
|
||
.Initialize<CustomerEditDialogViewModel>(vm => vm.InitializeForAdd())
|
||
.GetResultAsync<bool>();
|
||
if (result) await LoadAsync();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Growl.Error($"打开新增对话框失败:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
private async Task ShowEditDialogAsync(MesXslCustomer customer)
|
||
{
|
||
if (customer == null) return;
|
||
try
|
||
{
|
||
var result = await HandyControl.Controls.Dialog.Show<CustomerEditDialogView>()
|
||
.Initialize<CustomerEditDialogViewModel>(vm => vm.InitializeForEdit(customer))
|
||
.GetResultAsync<bool>();
|
||
if (result) await LoadAsync();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Growl.Error($"打开编辑对话框失败:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
private async Task DeleteAsync(MesXslCustomer customer)
|
||
{
|
||
if (customer?.Id == null) return;
|
||
var confirm = System.Windows.MessageBox.Show(
|
||
$"确定删除客户【{customer.CustomerName}】?此操作不可恢复!",
|
||
"确认删除", MessageBoxButton.OKCancel, MessageBoxImage.Question);
|
||
if (confirm != System.Windows.MessageBoxResult.OK) return;
|
||
|
||
var ok = await _customerService.DeleteAsync(customer.Id);
|
||
if (ok) { Growl.Success("删除成功!"); await LoadAsync(); }
|
||
else Growl.Error("删除失败!");
|
||
}
|
||
|
||
private async Task ToggleStatusAsync(MesXslCustomer customer)
|
||
{
|
||
if (customer?.Id == null) return;
|
||
var newStatus = customer.Status == "1" ? "0" : "1";
|
||
var ok = await _customerService.UpdateStatusAsync(customer.Id, newStatus);
|
||
if (ok)
|
||
{
|
||
// 客户列表离线场景下只改行对象字段,DataGrid 对计算列(StatusText)可能不会立即重绘。
|
||
// 这里统一重载一次列表,确保状态、筛选结果和分页统计立即一致。
|
||
await LoadAsync();
|
||
}
|
||
else Growl.Error("状态切换失败!");
|
||
}
|
||
|
||
protected override void CleanUp()
|
||
{
|
||
base.CleanUp();
|
||
if (_customerChangedToken != null)
|
||
{
|
||
_eventAggregator.GetEvent<CustomerChangedEvent>().Unsubscribe(_customerChangedToken);
|
||
_customerChangedToken = null;
|
||
}
|
||
|
||
if (_syncConflictToken != null)
|
||
{
|
||
_eventAggregator.GetEvent<SyncConflictEvent>().Unsubscribe(_syncConflictToken);
|
||
_syncConflictToken = null;
|
||
}
|
||
}
|
||
}
|