新增MES库区管理功能,包含免密接口、数据处理逻辑及相关控制器、服务和实体的实现。支持库区的增删改查操作,优化用户体验并增强系统的实时数据同步能力。
This commit is contained in:
@@ -0,0 +1,262 @@
|
||||
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.Views.WarehouseArea;
|
||||
|
||||
namespace YY.Admin.ViewModels.WarehouseArea;
|
||||
|
||||
public class WarehouseAreaListViewModel : BaseViewModel
|
||||
{
|
||||
private readonly IWarehouseAreaService _warehouseAreaService;
|
||||
private readonly IWarehouseService _warehouseService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private SubscriptionToken? _changedToken;
|
||||
private SubscriptionToken? _syncConflictToken;
|
||||
|
||||
private ObservableCollection<MesXslWarehouseArea> _areas = new();
|
||||
public ObservableCollection<MesXslWarehouseArea> Areas
|
||||
{
|
||||
get => _areas;
|
||||
set => SetProperty(ref _areas, 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? _filterAreaCode;
|
||||
public string? FilterAreaCode { get => _filterAreaCode; set => SetProperty(ref _filterAreaCode, value); }
|
||||
|
||||
private string? _filterAreaName;
|
||||
public string? FilterAreaName { get => _filterAreaName; set => SetProperty(ref _filterAreaName, value); }
|
||||
|
||||
private string? _filterWarehouseId;
|
||||
public string? FilterWarehouseId { get => _filterWarehouseId; set => SetProperty(ref _filterWarehouseId, value); }
|
||||
|
||||
private string? _filterStatus;
|
||||
public string? FilterStatus { get => _filterStatus; set => SetProperty(ref _filterStatus, value); }
|
||||
|
||||
public ObservableCollection<KeyValuePair<string, string>> WarehouseOptions { get; } = new();
|
||||
public ObservableCollection<KeyValuePair<string, string>> StatusOptions { get; } = new();
|
||||
|
||||
public DelegateCommand SearchCommand { get; }
|
||||
public DelegateCommand ResetCommand { get; }
|
||||
public DelegateCommand AddCommand { get; }
|
||||
public DelegateCommand<MesXslWarehouseArea> EditCommand { get; }
|
||||
public DelegateCommand<MesXslWarehouseArea> DeleteCommand { get; }
|
||||
public DelegateCommand<MesXslWarehouseArea> ToggleStatusCommand { get; }
|
||||
public DelegateCommand PrevPageCommand { get; }
|
||||
public DelegateCommand NextPageCommand { get; }
|
||||
|
||||
public WarehouseAreaListViewModel(
|
||||
IWarehouseAreaService warehouseAreaService,
|
||||
IWarehouseService warehouseService,
|
||||
IContainerExtension container,
|
||||
IDialogService dialogService,
|
||||
IRegionManager regionManager) : base(container, regionManager)
|
||||
{
|
||||
_warehouseAreaService = warehouseAreaService;
|
||||
_warehouseService = warehouseService;
|
||||
_dialogService = dialogService;
|
||||
|
||||
SearchCommand = new DelegateCommand(async () => { PageNo = 1; await LoadAsync(); });
|
||||
ResetCommand = new DelegateCommand(async () =>
|
||||
{
|
||||
FilterAreaCode = null;
|
||||
FilterAreaName = null;
|
||||
FilterWarehouseId = null;
|
||||
FilterStatus = null;
|
||||
PageNo = 1;
|
||||
await LoadAsync();
|
||||
});
|
||||
AddCommand = new DelegateCommand(async () => await ShowAddDialogAsync());
|
||||
EditCommand = new DelegateCommand<MesXslWarehouseArea>(async a => await ShowEditDialogAsync(a));
|
||||
DeleteCommand = new DelegateCommand<MesXslWarehouseArea>(async a => await DeleteAsync(a));
|
||||
ToggleStatusCommand = new DelegateCommand<MesXslWarehouseArea>(async a => await ToggleStatusAsync(a));
|
||||
PrevPageCommand = new DelegateCommand(async () => { if (PageNo > 1) { PageNo--; await LoadAsync(); } });
|
||||
NextPageCommand = new DelegateCommand(async () => { if ((long)PageNo * PageSize < Total) { PageNo++; await LoadAsync(); } });
|
||||
|
||||
_changedToken = _eventAggregator
|
||||
.GetEvent<WarehouseAreaChangedEvent>()
|
||||
.Subscribe(async p => await OnChangedAsync(p), ThreadOption.UIThread);
|
||||
|
||||
_syncConflictToken = _eventAggregator.GetEvent<SyncConflictEvent>()
|
||||
.Subscribe(OnSyncConflict, ThreadOption.UIThread);
|
||||
|
||||
_ = InitializeAsync();
|
||||
}
|
||||
|
||||
private async Task OnChangedAsync(WarehouseAreaChangedPayload payload)
|
||||
{
|
||||
if (payload.Action == "edit" && !string.IsNullOrWhiteSpace(payload.WarehouseAreaId))
|
||||
await RefreshSingleAsync(payload.WarehouseAreaId!);
|
||||
else
|
||||
await LoadAsync();
|
||||
}
|
||||
|
||||
private async Task RefreshSingleAsync(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var updated = await _warehouseAreaService.GetByIdAsync(id);
|
||||
if (updated == null) return;
|
||||
var idx = Areas.ToList().FindIndex(a => string.Equals(a.Id, id, StringComparison.OrdinalIgnoreCase));
|
||||
if (idx >= 0) Areas[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
|
||||
{
|
||||
StatusOptions.Clear();
|
||||
StatusOptions.Add(new KeyValuePair<string, string>("全部", ""));
|
||||
StatusOptions.Add(new KeyValuePair<string, string>("启用", "0"));
|
||||
StatusOptions.Add(new KeyValuePair<string, string>("停用", "1"));
|
||||
|
||||
await LoadWarehouseOptionsAsync();
|
||||
await UIHelper.WaitForRenderAsync();
|
||||
await LoadAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"库区列表初始化失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadWarehouseOptionsAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var warehouses = await _warehouseService.GetAllAsync();
|
||||
WarehouseOptions.Clear();
|
||||
WarehouseOptions.Add(new KeyValuePair<string, string>("全部", ""));
|
||||
foreach (var w in warehouses.Where(w => !string.IsNullOrWhiteSpace(w.Id)))
|
||||
WarehouseOptions.Add(new KeyValuePair<string, string>(w.WarehouseName ?? w.Id!, w.Id!));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[库区] 加载仓库选项失败: {ex.Message}");
|
||||
if (WarehouseOptions.Count == 0)
|
||||
WarehouseOptions.Add(new KeyValuePair<string, string>("全部", ""));
|
||||
}
|
||||
}
|
||||
|
||||
public async Task LoadAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
IsLoading = true;
|
||||
var result = await _warehouseAreaService.PageAsync(PageNo, PageSize, FilterAreaCode, FilterAreaName, FilterWarehouseId, FilterStatus);
|
||||
Areas = new ObservableCollection<MesXslWarehouseArea>(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<WarehouseAreaEditDialogView>()
|
||||
.Initialize<WarehouseAreaEditDialogViewModel>(vm => vm.InitializeForAdd())
|
||||
.GetResultAsync<bool>();
|
||||
if (result) await LoadAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Growl.Error($"打开新增对话框失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ShowEditDialogAsync(MesXslWarehouseArea area)
|
||||
{
|
||||
if (area == null) return;
|
||||
try
|
||||
{
|
||||
var result = await HandyControl.Controls.Dialog.Show<WarehouseAreaEditDialogView>()
|
||||
.Initialize<WarehouseAreaEditDialogViewModel>(vm => vm.InitializeForEdit(area))
|
||||
.GetResultAsync<bool>();
|
||||
if (result) await LoadAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Growl.Error($"打开编辑对话框失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteAsync(MesXslWarehouseArea area)
|
||||
{
|
||||
if (area?.Id == null) return;
|
||||
var confirm = System.Windows.MessageBox.Show($"确定删除库区「{area.AreaCode}」?此操作不可恢复!", "确认删除",
|
||||
MessageBoxButton.OKCancel, MessageBoxImage.Question);
|
||||
if (confirm != System.Windows.MessageBoxResult.OK) return;
|
||||
|
||||
var ok = await _warehouseAreaService.DeleteAsync(area.Id);
|
||||
if (ok) { Growl.Success("删除成功!"); await LoadAsync(); }
|
||||
else Growl.Error("删除失败!");
|
||||
}
|
||||
|
||||
private async Task ToggleStatusAsync(MesXslWarehouseArea area)
|
||||
{
|
||||
if (area?.Id == null) return;
|
||||
var newStatus = area.Status == "1" ? "0" : "1";
|
||||
var ok = await _warehouseAreaService.UpdateStatusAsync(area.Id, newStatus);
|
||||
if (ok) { area.Status = newStatus; RaisePropertyChanged(nameof(Areas)); }
|
||||
else Growl.Error("状态切换失败!");
|
||||
}
|
||||
|
||||
protected override void CleanUp()
|
||||
{
|
||||
base.CleanUp();
|
||||
if (_changedToken != null)
|
||||
{
|
||||
_eventAggregator.GetEvent<WarehouseAreaChangedEvent>().Unsubscribe(_changedToken);
|
||||
_changedToken = null;
|
||||
}
|
||||
if (_syncConflictToken != null)
|
||||
{
|
||||
_eventAggregator.GetEvent<SyncConflictEvent>().Unsubscribe(_syncConflictToken);
|
||||
_syncConflictToken = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user