You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
3.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Sln.Wcs.Repository.service.@base;
using Sln.Wcs.UI.Views.Base;
namespace Sln.Wcs.UI.ViewModels.Base;
public interface ICrudPageViewModel
{
void Load();
Avalonia.Controls.Control CreateView();
string PageTitle { get; }
}
public abstract partial class CrudPageViewModel<T> : ObservableObject, ICrudPageViewModel where T : class, new()
{
protected readonly IBaseService<T> _service;
[ObservableProperty]
private ObservableCollection<T> _items = new();
[ObservableProperty]
private T? _selectedItem;
[ObservableProperty]
private string _searchText = string.Empty;
[ObservableProperty]
private string _pageTitle = string.Empty;
[ObservableProperty]
private string _statusText = string.Empty;
public abstract List<FieldConfig> FieldConfigs { get; }
public abstract Avalonia.Controls.Control CreateView();
/// <summary>
/// Expression to search by name/code field. Override to customize.
/// Returns null to skip filtering (load all).
/// </summary>
protected abstract Expression<Func<T, bool>>? BuildSearchExpression(string search);
protected CrudPageViewModel(IBaseService<T> service)
{
_service = service;
AddCommand = new AsyncRelayCommand(Add);
EditCommand = new AsyncRelayCommand(Edit);
}
[RelayCommand]
public void Load()
{
try
{
List<T> list;
if (string.IsNullOrWhiteSpace(SearchText))
{
list = _service.Query();
}
else
{
var exp = BuildSearchExpression(SearchText);
list = exp != null ? _service.Query(exp) : _service.Query();
}
Items = new ObservableCollection<T>(list);
StatusText = $"共 {list.Count} 条记录";
}
catch (Exception ex)
{
StatusText = $"加载失败: {ex.Message}";
}
}
public AsyncRelayCommand AddCommand { get; }
public AsyncRelayCommand EditCommand { get; }
private async System.Threading.Tasks.Task Add()
{
var entity = new T();
var editor = new EntityEditWindow();
var result = await editor.ShowDialog(entity, FieldConfigs, false, GetMainWindow());
if (result)
{
_service.Insert(entity);
Load();
StatusText = "新增成功";
}
}
private async System.Threading.Tasks.Task Edit()
{
if (SelectedItem is null) return;
var editor = new EntityEditWindow();
var result = await editor.ShowDialog(SelectedItem, FieldConfigs, true, GetMainWindow());
if (result)
{
_service.Update(SelectedItem);
Load();
StatusText = "编辑成功";
}
}
[RelayCommand]
private void Delete()
{
if (SelectedItem is null) return;
var prop = typeof(T).GetProperty("objId") ?? typeof(T).GetProperty("ObjId");
if (prop is null) return;
var id = prop.GetValue(SelectedItem);
_service.DeleteById(id!);
Load();
StatusText = "删除成功";
}
[RelayCommand]
private void Search()
{
Load();
}
private Avalonia.Controls.Window GetMainWindow()
{
return (Avalonia.Controls.Window)Avalonia.Application.Current!
.ApplicationLifetime!.GetType()
.GetProperty("MainWindow")!
.GetValue(Avalonia.Application.Current.ApplicationLifetime)!;
}
}