新增物料类型处理逻辑,确保在保存和编辑称重记录时自动设置默认物料类型。更新前端表单以支持密炼物料的选择和显示,优化用户体验。添加分类字典和数据字典的事件广播功能,增强系统的实时数据同步能力。

This commit is contained in:
geht
2026-05-07 17:53:48 +08:00
parent ce9dc8efd8
commit f60a4fb203
55 changed files with 2968 additions and 375 deletions

View File

@@ -62,6 +62,28 @@ public class MixerMaterialListViewModel : BaseViewModel
public ObservableCollection<KeyValuePair<string, string>> MajorCategoryOptions { get; } = new();
public ObservableCollection<KeyValuePair<string, string>> MinorCategoryOptions { get; } = new();
public ObservableCollection<CategoryFilterNode> TreeNodes { get; } = new();
private CategoryFilterNode? _selectedTreeNode;
public CategoryFilterNode? SelectedTreeNode
{
get => _selectedTreeNode;
set => SetProperty(ref _selectedTreeNode, value);
}
private bool _isTreeAllExpanded = true;
public bool IsTreeAllExpanded
{
get => _isTreeAllExpanded;
set
{
if (SetProperty(ref _isTreeAllExpanded, value))
RaisePropertyChanged(nameof(ToggleExpandButtonText));
}
}
public string ToggleExpandButtonText => _isTreeAllExpanded ? "折叠全部" : "展开全部";
public DelegateCommand SearchCommand { get; }
public DelegateCommand ResetCommand { get; }
public DelegateCommand AddCommand { get; }
@@ -69,6 +91,7 @@ public class MixerMaterialListViewModel : BaseViewModel
public DelegateCommand<MesMixerMaterial> DeleteCommand { get; }
public DelegateCommand PrevPageCommand { get; }
public DelegateCommand NextPageCommand { get; }
public DelegateCommand ToggleExpandCommand { get; }
public MixerMaterialListViewModel(
IMixerMaterialService mixerMaterialService,
@@ -83,10 +106,12 @@ public class MixerMaterialListViewModel : BaseViewModel
FilterMaterialCode = null;
FilterMaterialName = null;
FilterErpCode = null;
FilterMajorCategoryId = null;
_filterMajorCategoryId = null;
RaisePropertyChanged(nameof(FilterMajorCategoryId));
FilterMinorCategoryId = null;
PageNo = 1;
SelectedTreeNode = null;
await LoadMinorCategoryOptionsAsync();
PageNo = 1;
await LoadAsync();
});
AddCommand = new DelegateCommand(async () => await ShowAddDialogAsync());
@@ -94,6 +119,7 @@ public class MixerMaterialListViewModel : BaseViewModel
DeleteCommand = new DelegateCommand<MesMixerMaterial>(async m => await DeleteAsync(m));
PrevPageCommand = new DelegateCommand(async () => { if (PageNo > 1) { PageNo--; await LoadAsync(); } });
NextPageCommand = new DelegateCommand(async () => { if ((long)PageNo * PageSize < Total) { PageNo++; await LoadAsync(); } });
ToggleExpandCommand = new DelegateCommand(ToggleExpand);
_materialChangedToken = _eventAggregator
.GetEvent<MixerMaterialChangedEvent>()
@@ -106,6 +132,7 @@ public class MixerMaterialListViewModel : BaseViewModel
{
try
{
await LoadCategoryTreeAsync();
await LoadMajorCategoryOptionsAsync();
await LoadMinorCategoryOptionsAsync();
await UIHelper.WaitForRenderAsync();
@@ -117,6 +144,70 @@ public class MixerMaterialListViewModel : BaseViewModel
}
}
private async Task LoadCategoryTreeAsync()
{
try
{
var tree = await _mixerMaterialService.GetMaterialCategoryTreeAsync();
TreeNodes.Clear();
var root = new CategoryFilterNode("", "全部", null, false, null, []) { IsExpanded = true };
foreach (var major in tree)
{
var majorNode = new CategoryFilterNode(major.Id, major.Name ?? major.Code ?? major.Id, major.Code, true, null, []);
foreach (var minor in major.Children)
{
majorNode.Children.Add(new CategoryFilterNode(minor.Id, minor.Name ?? minor.Code ?? minor.Id, minor.Code, false, major.Id, []));
}
root.Children.Add(majorNode);
}
TreeNodes.Add(root);
IsTreeAllExpanded = false;
}
catch (Exception ex)
{
Debug.WriteLine($"加载物料分类树失败: {ex.Message}");
}
}
private void ToggleExpand()
{
var expand = !_isTreeAllExpanded;
foreach (var root in TreeNodes)
{
root.IsExpanded = true; // 根节点始终展开
foreach (var major in root.Children)
major.IsExpanded = expand;
}
IsTreeAllExpanded = expand;
}
public async Task OnTreeNodeSelectedAsync(CategoryFilterNode? node)
{
SelectedTreeNode = node;
if (node == null || node.Id == "")
{
_filterMajorCategoryId = null;
RaisePropertyChanged(nameof(FilterMajorCategoryId));
FilterMinorCategoryId = null;
}
else if (node.IsMajor)
{
_filterMajorCategoryId = node.Id;
RaisePropertyChanged(nameof(FilterMajorCategoryId));
FilterMinorCategoryId = null;
}
else
{
_filterMajorCategoryId = node.ParentId;
RaisePropertyChanged(nameof(FilterMajorCategoryId));
FilterMinorCategoryId = node.Id;
}
await LoadMinorCategoryOptionsAsync();
PageNo = 1;
await LoadAsync();
}
private async Task LoadMajorCategoryOptionsAsync()
{
MajorCategoryOptions.Clear();
@@ -132,11 +223,11 @@ public class MixerMaterialListViewModel : BaseViewModel
{
MinorCategoryOptions.Clear();
MinorCategoryOptions.Add(new KeyValuePair<string, string>("全部", ""));
if (string.IsNullOrWhiteSpace(FilterMajorCategoryId))
if (string.IsNullOrWhiteSpace(_filterMajorCategoryId))
{
return;
}
var options = await _mixerMaterialService.GetMinorCategoryOptionsAsync(FilterMajorCategoryId!);
var options = await _mixerMaterialService.GetMinorCategoryOptionsAsync(_filterMajorCategoryId!);
foreach (var item in options)
{
MinorCategoryOptions.Add(item);
@@ -155,7 +246,7 @@ public class MixerMaterialListViewModel : BaseViewModel
{
IsLoading = true;
var result = await _mixerMaterialService.PageAsync(
PageNo, PageSize, FilterMaterialCode, FilterMaterialName, FilterErpCode, FilterMajorCategoryId, FilterMinorCategoryId);
PageNo, PageSize, FilterMaterialCode, FilterMaterialName, FilterErpCode, _filterMajorCategoryId, FilterMinorCategoryId);
Materials = new ObservableCollection<MesMixerMaterial>(result.Records);
Total = result.Total;
}
@@ -228,5 +319,40 @@ public class MixerMaterialListViewModel : BaseViewModel
_materialChangedToken = null;
}
}
}
public class CategoryFilterNode : System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged;
public string Id { get; }
public string DisplayName { get; }
public string? Code { get; }
public bool IsMajor { get; }
public string? ParentId { get; }
public ObservableCollection<CategoryFilterNode> Children { get; }
private bool _isExpanded;
public bool IsExpanded
{
get => _isExpanded;
set
{
if (_isExpanded != value)
{
_isExpanded = value;
PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(IsExpanded)));
}
}
}
public CategoryFilterNode(string id, string? displayName, string? code, bool isMajor, string? parentId, List<CategoryFilterNode> children)
{
Id = id;
DisplayName = displayName ?? id;
Code = code;
IsMajor = isMajor;
ParentId = parentId;
Children = new ObservableCollection<CategoryFilterNode>(children);
}
}
}