396 lines
13 KiB
C#
396 lines
13 KiB
C#
using FATrace.Model;
|
||
using FATrace.WPLApp.Core;
|
||
using FATrace.WPLApp.Services;
|
||
using FreeSql;
|
||
using Prism.Commands;
|
||
using Prism.Services.Dialogs;
|
||
using System;
|
||
using System.Collections.ObjectModel;
|
||
using System.ComponentModel;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
|
||
namespace FATrace.WPLApp.ViewModels
|
||
{
|
||
/// <summary>
|
||
/// 用户管理页面 VM(TbUser 增删改查)
|
||
/// </summary>
|
||
public class UserManageViewModel : NavigationViewModel
|
||
{
|
||
private readonly IFreeSql _fsql;
|
||
private readonly ILogService _log;
|
||
private readonly IDialogService _dialog;
|
||
private readonly SysRunService _sys;
|
||
|
||
public UserManageViewModel(IFreeSql fsql, ILogService log, IDialogService dialogService, SysRunService sys)
|
||
{
|
||
_fsql = fsql;
|
||
_log = log;
|
||
_dialog = dialogService;
|
||
_sys = sys;
|
||
|
||
AccessLevelOptions = new ObservableCollection<string>(new[] { AccessLevels.All, AccessLevels.Admin, AccessLevels.Operator, AccessLevels.Guest });
|
||
AccessLevel = AccessLevels.All;
|
||
Items = new ObservableCollection<TbUser>();
|
||
|
||
SearchCommand = new DelegateCommand(async () => await SearchAsync(), () => !IsBusy)
|
||
.ObservesProperty(() => IsBusy);
|
||
ClearCommand = new DelegateCommand(ClearFilters, () => !IsBusy)
|
||
.ObservesProperty(() => IsBusy);
|
||
|
||
AddCommand = new DelegateCommand(AddUser, () => !IsBusy && CanEditUsers)
|
||
.ObservesProperty(() => IsBusy)
|
||
.ObservesProperty(() => CanEditUsers);
|
||
EditCommand = new DelegateCommand(EditUser, () => !IsBusy && CanEditUsers && SelectedItem != null)
|
||
.ObservesProperty(() => IsBusy)
|
||
.ObservesProperty(() => CanEditUsers)
|
||
.ObservesProperty(() => SelectedItem);
|
||
DeleteCommand = new DelegateCommand(async () => await DeleteUserAsync(), () => !IsBusy && CanEditUsers && SelectedItem != null)
|
||
.ObservesProperty(() => IsBusy)
|
||
.ObservesProperty(() => CanEditUsers)
|
||
.ObservesProperty(() => SelectedItem);
|
||
|
||
FirstPageCommand = new DelegateCommand(async () => { if (PageIndex == 1) return; PageIndex = 1; await SearchAsync(); }, () => !IsBusy && PageIndex > 1)
|
||
.ObservesProperty(() => IsBusy)
|
||
.ObservesProperty(() => PageIndex);
|
||
PrevPageCommand = new DelegateCommand(async () => { if (PageIndex <= 1) return; PageIndex -= 1; await SearchAsync(); }, () => !IsBusy && PageIndex > 1)
|
||
.ObservesProperty(() => IsBusy)
|
||
.ObservesProperty(() => PageIndex);
|
||
NextPageCommand = new DelegateCommand(async () => { if (PageIndex >= TotalPages) return; PageIndex += 1; await SearchAsync(); }, () => !IsBusy && PageIndex < TotalPages)
|
||
.ObservesProperty(() => IsBusy)
|
||
.ObservesProperty(() => PageIndex)
|
||
.ObservesProperty(() => TotalPages);
|
||
LastPageCommand = new DelegateCommand(async () => { if (TotalPages <= 0 || PageIndex == TotalPages) return; PageIndex = TotalPages; await SearchAsync(); }, () => !IsBusy && PageIndex < TotalPages)
|
||
.ObservesProperty(() => IsBusy)
|
||
.ObservesProperty(() => PageIndex)
|
||
.ObservesProperty(() => TotalPages);
|
||
|
||
_sys.PropertyChanged += SysOnPropertyChanged;
|
||
RaisePropertyChanged(nameof(CanEditUsers));
|
||
}
|
||
|
||
private void SysOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||
{
|
||
if (e.PropertyName == nameof(SysRunService.CurAccessLevel) || e.PropertyName == nameof(SysRunService.CurUser))
|
||
{
|
||
RaisePropertyChanged(nameof(CanEditUsers));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 是否允许编辑用户(仅管理员)
|
||
/// </summary>
|
||
public bool CanEditUsers => string.Equals(_sys.CurAccessLevel, AccessLevels.Admin, StringComparison.OrdinalIgnoreCase);
|
||
|
||
#region 查询条件
|
||
private string? _userName;
|
||
/// <summary>
|
||
/// 用户名(模糊匹配)
|
||
/// </summary>
|
||
public string? UserName
|
||
{
|
||
get => _userName;
|
||
set { _userName = value; RaisePropertyChanged(); }
|
||
}
|
||
|
||
private string? _accessLevel;
|
||
/// <summary>
|
||
/// 等级(精确匹配)
|
||
/// </summary>
|
||
public string? AccessLevel
|
||
{
|
||
get => _accessLevel;
|
||
set { _accessLevel = value; RaisePropertyChanged(); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 等级下拉选项
|
||
/// </summary>
|
||
public ObservableCollection<string> AccessLevelOptions { get; }
|
||
#endregion
|
||
|
||
#region 列表与分页
|
||
public ObservableCollection<TbUser> Items { get; }
|
||
|
||
private TbUser? _selectedItem;
|
||
/// <summary>
|
||
/// 当前选中行
|
||
/// </summary>
|
||
public TbUser? SelectedItem
|
||
{
|
||
get => _selectedItem;
|
||
set { _selectedItem = value; RaisePropertyChanged(); }
|
||
}
|
||
|
||
private bool _isBusy;
|
||
/// <summary>
|
||
/// 是否忙碌
|
||
/// </summary>
|
||
public bool IsBusy
|
||
{
|
||
get => _isBusy;
|
||
set { _isBusy = value; RaisePropertyChanged(); }
|
||
}
|
||
|
||
private int _totalCount;
|
||
/// <summary>
|
||
/// 总数
|
||
/// </summary>
|
||
public int TotalCount
|
||
{
|
||
get => _totalCount;
|
||
set { _totalCount = value; RaisePropertyChanged(); }
|
||
}
|
||
|
||
private int _pageIndex = 1;
|
||
/// <summary>
|
||
/// 页码(从1开始)
|
||
/// </summary>
|
||
public int PageIndex
|
||
{
|
||
get => _pageIndex;
|
||
set { _pageIndex = value < 1 ? 1 : value; RaisePropertyChanged(); }
|
||
}
|
||
|
||
private int _pageSize = 20;
|
||
/// <summary>
|
||
/// 页大小
|
||
/// </summary>
|
||
public int PageSize
|
||
{
|
||
get => _pageSize;
|
||
set
|
||
{
|
||
var v = value <= 0 ? 20 : value;
|
||
if (_pageSize != v)
|
||
{
|
||
_pageSize = v;
|
||
RaisePropertyChanged();
|
||
PageIndex = 1;
|
||
if (!IsBusy) _ = SearchAsync();
|
||
}
|
||
}
|
||
}
|
||
|
||
private int _totalPages;
|
||
/// <summary>
|
||
/// 总页数
|
||
/// </summary>
|
||
public int TotalPages
|
||
{
|
||
get => _totalPages;
|
||
set { _totalPages = value; RaisePropertyChanged(); }
|
||
}
|
||
#endregion
|
||
|
||
#region 命令
|
||
public DelegateCommand SearchCommand { get; }
|
||
public DelegateCommand ClearCommand { get; }
|
||
public DelegateCommand AddCommand { get; }
|
||
public DelegateCommand EditCommand { get; }
|
||
public DelegateCommand DeleteCommand { get; }
|
||
|
||
public DelegateCommand FirstPageCommand { get; }
|
||
public DelegateCommand PrevPageCommand { get; }
|
||
public DelegateCommand NextPageCommand { get; }
|
||
public DelegateCommand LastPageCommand { get; }
|
||
#endregion
|
||
|
||
private void ClearFilters()
|
||
{
|
||
UserName = string.Empty;
|
||
AccessLevel = AccessLevels.All;
|
||
}
|
||
|
||
private async Task SearchAsync()
|
||
{
|
||
if (IsBusy) return;
|
||
try
|
||
{
|
||
IsBusy = true;
|
||
await SearchCoreAsync();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_log.Error($"TbUser 查询失败: {ex}");
|
||
MessageBox.Show($"查询失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
finally
|
||
{
|
||
IsBusy = false;
|
||
}
|
||
}
|
||
|
||
private async Task SearchCoreAsync()
|
||
{
|
||
_log.Info("TbUser 查询开始");
|
||
|
||
var data = await Task.Run(() =>
|
||
{
|
||
var q = _fsql.Select<TbUser>();
|
||
|
||
if (!string.IsNullOrWhiteSpace(UserName))
|
||
q = q.Where(a => a.UserName != null && a.UserName.Contains(UserName));
|
||
|
||
if (!string.IsNullOrWhiteSpace(AccessLevel)
|
||
&& !string.Equals(AccessLevel, AccessLevels.All, StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
q = q.Where(a => a.AccessLevel == AccessLevel);
|
||
}
|
||
|
||
q = q.OrderByDescending(a => a.Id);
|
||
|
||
var page = PageIndex < 1 ? 1 : PageIndex;
|
||
var size = PageSize <= 0 ? 20 : PageSize;
|
||
|
||
var list = q.Count(out var total)
|
||
.Page(page, size)
|
||
.ToList();
|
||
|
||
var pages = total <= 0 || size <= 0 ? 0 : (int)Math.Ceiling(total * 1.0 / size);
|
||
if (pages > 0 && page > pages)
|
||
{
|
||
page = pages;
|
||
list = q.Page(page, size).ToList();
|
||
}
|
||
|
||
return (items: list, total: (int)total, normalizedPage: page, totalPages: pages);
|
||
});
|
||
|
||
Application.Current.Dispatcher.Invoke(() =>
|
||
{
|
||
Items.Clear();
|
||
foreach (var it in data.items) Items.Add(it);
|
||
TotalCount = data.total;
|
||
TotalPages = data.totalPages;
|
||
PageIndex = data.normalizedPage == 0 ? 1 : data.normalizedPage;
|
||
});
|
||
|
||
_log.Info($"TbUser 查询完成,记录数: {TotalCount}");
|
||
}
|
||
|
||
private void AddUser()
|
||
{
|
||
var p = new DialogParameters
|
||
{
|
||
{ DialogKeys.Mode, DialogModes.Add }
|
||
};
|
||
|
||
_dialog.ShowDialog("DialogUserEditView", p, async r =>
|
||
{
|
||
if (r.Result == ButtonResult.OK)
|
||
{
|
||
PageIndex = 1;
|
||
await SearchAsync();
|
||
}
|
||
});
|
||
}
|
||
|
||
private void EditUser()
|
||
{
|
||
if (SelectedItem == null)
|
||
{
|
||
MessageBox.Show("请选择要编辑的用户", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||
return;
|
||
}
|
||
|
||
var p = new DialogParameters
|
||
{
|
||
{ DialogKeys.Mode, DialogModes.Edit },
|
||
{ DialogKeys.UserId, SelectedItem.Id }
|
||
};
|
||
|
||
_dialog.ShowDialog("DialogUserEditView", p, async r =>
|
||
{
|
||
if (r.Result == ButtonResult.OK)
|
||
{
|
||
await SearchAsync();
|
||
}
|
||
});
|
||
}
|
||
|
||
private async Task DeleteUserAsync()
|
||
{
|
||
if (SelectedItem == null)
|
||
{
|
||
MessageBox.Show("请选择要删除的用户", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||
return;
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(_sys.CurUser)
|
||
&& string.Equals(_sys.CurUser, SelectedItem.UserName, StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
MessageBox.Show("不能删除当前登录用户", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||
return;
|
||
}
|
||
|
||
var ok = MessageBox.Show($"确认删除用户:{SelectedItem.UserName} ?", "确认", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||
if (ok != MessageBoxResult.Yes) return;
|
||
|
||
if (IsBusy) return;
|
||
try
|
||
{
|
||
IsBusy = true;
|
||
|
||
var id = SelectedItem.Id;
|
||
await Task.Run(() =>
|
||
{
|
||
_fsql.Delete<TbUser>(id).ExecuteAffrows();
|
||
});
|
||
|
||
_log.Info($"删除用户成功,Id={id}");
|
||
SelectedItem = null;
|
||
await SearchCoreAsync();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_log.Error($"删除用户失败: {ex}");
|
||
MessageBox.Show($"删除失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
finally
|
||
{
|
||
IsBusy = false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 进入页面自动加载
|
||
/// </summary>
|
||
/// <param name="navigationContext">导航上下文</param>
|
||
public override async void OnNavigatedTo(Prism.Regions.NavigationContext navigationContext)
|
||
{
|
||
await SearchAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 权限等级常量
|
||
/// </summary>
|
||
public static class AccessLevels
|
||
{
|
||
public const string All = "全部";
|
||
public const string Admin = "管理员";
|
||
public const string Operator = "操作员";
|
||
public const string Guest = "访客";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 弹窗参数 Key
|
||
/// </summary>
|
||
public static class DialogKeys
|
||
{
|
||
public const string Mode = "Mode";
|
||
public const string UserId = "UserId";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 弹窗模式
|
||
/// </summary>
|
||
public static class DialogModes
|
||
{
|
||
public const string Add = "Add";
|
||
public const string Edit = "Edit";
|
||
}
|
||
}
|
||
}
|