提交用户部分代码
This commit is contained in:
1 parent
9b9e4cbd82
commit
127fc22de5
26 files changed
+1110
-206
No files matched your search
@@ -8,6 +8,7 @@ using Store.Management.Views;
|
||||
using Store.Management.ViewModels;
|
||||
using Store.Management.Framework.Controls;
|
||||
using Store.Management.Api;
|
||||
using Store.Management.Api.Users;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
@@ -75,10 +76,10 @@ class Program
|
||||
Check(pageVm.Unloads == 1, "移出页面触发卸载");
|
||||
window.Content = page;
|
||||
app.Dispatcher.Invoke(() => { }, DispatcherPriority.ApplicationIdle);
|
||||
Check(pageVm.Loads == 2, "重新加入页面再次加载");
|
||||
Check(pageVm.Loads == 2 && pageVm.FirstLoads == 1, "重新加入页面再次加载");
|
||||
var replacement = new LifecycleProbe();
|
||||
page.DataContext = replacement;
|
||||
Check(pageVm.Unloads == 2 && replacement.Loads == 1, "已加载的页面更换 ViewModel 后转移通知");
|
||||
Check(pageVm.Unloads == 2 && replacement.Loads == 1 && replacement.FirstLoads == 1, "已加载的页面更换 ViewModel 后转移通知");
|
||||
windowVm.CancelClose = true;
|
||||
window.Close();
|
||||
Check(window.IsVisible && windowVm.Closes == 0, "ViewModel 可以取消关闭");
|
||||
@@ -142,12 +143,120 @@ class Program
|
||||
await usersVm.SearchCommand.Execute();
|
||||
Check(status.Current.Level == StatusLevel.Error && usersVm.CanInteract, "查询失败后显示错误并允许重试");
|
||||
await usersClient.Auth.LoginAsync(new() { UserName = "admin", Password = "320BB1D43EC042096A83DBAC6DC9294A" });
|
||||
var usersPage = new UserManagementPage { DataContext = usersVm };
|
||||
var grid = ((DockPanel)usersPage.Content).Children.OfType<DataGridEx>().Single();
|
||||
var sample = new UserInfo { GroupId = 4, SaLevel = UserAdminLevel.SuperAdmin, OemId = "A01", Authority = "在线寄件,商品采集" };
|
||||
foreach (var (header, expected) in new[] { ("分组", "客服"), ("代理编码", "A01"), ("超管等级", "超级管理员"), ("权限", "在线寄件,商品采集") })
|
||||
{
|
||||
var column = grid.Columns.OfType<DataGridTextColumn>().Single(c => Equals(c.Header, header));
|
||||
var cell = new TextBlock { DataContext = sample };
|
||||
cell.SetBinding(TextBlock.TextProperty, column.Binding);
|
||||
Check(cell.Text == expected, $"用户列表{header}显示错误:{cell.Text}");
|
||||
cell.DataContext = new UserInfo { GroupId = 5 };
|
||||
Check(cell.Text == (header == "分组" ? "5" : ""), $"用户列表{header}历史数据或空值显示错误");
|
||||
}
|
||||
var groupFilter = LogicalTreeHelper.FindLogicalNode(usersPage, "GroupFilter") as ComboBox;
|
||||
Check(groupFilter?.Items.Count == Enum.GetValues<UserGroup>().Length + 1, "用户组包含全部和当前枚举选项");
|
||||
await app.Dispatcher.InvokeAsync(() => { }, DispatcherPriority.ApplicationIdle);
|
||||
var menu = grid.RowContextMenu;
|
||||
Check(grid.SelectRowOnRightClick && ReferenceEquals(menu, usersPage.Resources["UserRowMenu"]), "使用页面行菜单并选中右键行");
|
||||
var actions = menu.Items.OfType<MenuItem>().Select(item => item.Command).ToArray();
|
||||
Check(actions.SequenceEqual(new System.Windows.Input.ICommand[] { usersVm.EditCommand, usersVm.BillingCommand, usersVm.DeleteCommand, usersVm.CreateCommand }),
|
||||
"行菜单绑定编辑、删除和创建用户命令");
|
||||
Check(groupFilter!.Text == "全部", "默认显示全部用户组");
|
||||
groupFilter.SelectedIndex = 1;
|
||||
Check(usersVm.SelectedGroup == Store.Management.Api.Users.UserGroup.MainAccount, "选择主号更新搜索条件");
|
||||
Task search = usersVm.SearchCommand.Execute();
|
||||
Check(!usersVm.CanInteract && status.Current.Level == StatusLevel.Info, "查询期间禁用操作");
|
||||
await search;
|
||||
Check(usersVm.CanInteract && usersVm.Total == 51 && status.Current.Level == StatusLevel.Success, "重试查询成功");
|
||||
var narrowWindow = new Window { Content = usersPage, Width = 900, Height = 560, ShowInTaskbar = false };
|
||||
narrowWindow.Show();
|
||||
narrowWindow.UpdateLayout();
|
||||
var listScroll = (ScrollViewer)grid.Template.FindName("DG_ScrollViewer", grid);
|
||||
Check(listScroll.ComputedHorizontalScrollBarVisibility == Visibility.Visible && listScroll.ScrollableWidth > 0,
|
||||
"窄窗口显示用户列表横向滚动条");
|
||||
listScroll.ScrollToRightEnd();
|
||||
narrowWindow.UpdateLayout();
|
||||
Check(listScroll.HorizontalOffset > 0 && Math.Abs(listScroll.HorizontalOffset - listScroll.ScrollableWidth) < 1,
|
||||
"用户列表可滚动到最右列");
|
||||
narrowWindow.Close();
|
||||
Check(handler.LastGroupId == 3, "查询按主号分组");
|
||||
groupFilter.SelectedIndex = 0;
|
||||
await usersVm.PageCommand.Execute(new DataGridPageRequest(2, 50));
|
||||
Check(usersVm.Page == 2 && usersVm.CanInteract && status.Current.Level == StatusLevel.Success, "分页查询成功");
|
||||
Check(handler.LastGroupId == 3, "翻页保留已查询的用户组");
|
||||
await usersVm.SearchCommand.Execute();
|
||||
Check(handler.LastGroupId == null && usersVm.Page == 1, "全部清除分组并返回首页");
|
||||
var billing = new Store.Management.Views.Dialogs.UserBillingDialogViewModel(userService);
|
||||
billing.OnDialogOpened(new DialogParameters { { "parameter", new UserInfo
|
||||
{
|
||||
Id = 7, UserName = "billing", ShopPointsPerMonth = 45, PostagePerOrder = 3.5m,
|
||||
RefundPostagePerOrder = 4m, GiftOemAmountPerOrder = null, SyncLogisticsPerOrder = 0m
|
||||
} } });
|
||||
var billingView = new Store.Management.Views.Dialogs.UserBillingDialog { DataContext = billing };
|
||||
var billingWindow = new Window { Content = billingView, ShowInTaskbar = false };
|
||||
billingWindow.Show();
|
||||
billingWindow.UpdateLayout();
|
||||
Check(billing.Fields.Length == 5 && billing.Fields[0].Value == 45 && billing.Fields[3].EnteredValue == null &&
|
||||
billing.Fields[4].EnteredValue == 0, "计费配置回填原值并区分空值和零");
|
||||
var saveBilling = (Prism.Commands.AsyncDelegateCommand)billing.ConfirmCommand;
|
||||
int beforeBilling = handler.RequestCount;
|
||||
await saveBilling.Execute();
|
||||
Check(handler.RequestCount == beforeBilling, "未改动计费配置不发送请求");
|
||||
billing.Fields[0].Value = 29;
|
||||
await saveBilling.Execute();
|
||||
Check(handler.RequestCount == beforeBilling && billing.ErrorMsg.Length > 0, "拦截无效积分");
|
||||
billing.Fields[0].Value = 50;
|
||||
var fields = (ItemsControl)billingView.Content;
|
||||
var presenter = (ContentPresenter)fields.ItemContainerGenerator.ContainerFromIndex(3);
|
||||
var title = (MAX.Common.WPF.Controls.TitleContent)System.Windows.Media.VisualTreeHelper.GetChild(presenter, 0);
|
||||
var amount = (HandyControl.Controls.NumericUpDown)title.Content;
|
||||
Check(amount.IsEnabled, "空金额可以直接输入");
|
||||
var amountInput = (TextBox)amount.Template.FindName("PART_TextBox", amount);
|
||||
amountInput.Focus();
|
||||
amountInput.SelectAll();
|
||||
amountInput.SelectedText = "0";
|
||||
await saveBilling.Execute();
|
||||
using (var json = System.Text.Json.JsonDocument.Parse(handler.LastUpdateBody!))
|
||||
{
|
||||
var body = json.RootElement;
|
||||
Check(body.EnumerateObject().Count() == 3 && body.GetProperty("id").GetInt32() == 7 &&
|
||||
body.GetProperty("shopPointsPerMonth").GetInt32() == 50 && body.GetProperty("giftOemAmountPerOrder").GetDecimal() == 0,
|
||||
"计费更新请求仅含用户 ID 和两项改动");
|
||||
}
|
||||
billingWindow.Close();
|
||||
var editor = new UserEditorDialogViewModel(userService);
|
||||
editor.OnDialogOpened(new DialogParameters { { "user", null } });
|
||||
var editorView = new UserEditorDialog { DataContext = editor };
|
||||
editor.Draft.Mobile = "13800000000";
|
||||
editor.Draft.NickName = "测试";
|
||||
editor.Group = UserGroup.CustomerService;
|
||||
editor.ParentUserName = "parent";
|
||||
editor.AgentCode = "agent";
|
||||
editor.Level = UserAdminLevel.SuperAdmin;
|
||||
editor.Permissions[0].IsSelected = true;
|
||||
var editorPassword = (PasswordBox)editorView.FindName("NewPassword");
|
||||
var confirmation = (PasswordBox)editorView.FindName("Confirmation");
|
||||
editorPassword.Password = "secret";
|
||||
await ((Prism.Commands.AsyncDelegateCommand)editor.ConfirmCommand).Execute();
|
||||
Check(editor.ErrorMsg.Contains("不一致"), "密码不一致应阻止保存");
|
||||
confirmation.Password = "secret";
|
||||
await ((Prism.Commands.AsyncDelegateCommand)editor.ConfirmCommand).Execute();
|
||||
Check(handler.SavedCreate is { UserName: "13800000000", GroupId: UserGroup.CustomerService,
|
||||
ParentUserName: "parent", Authority: "微信回采", OemId: "agent", SaLevel: UserAdminLevel.SuperAdmin },
|
||||
"新增子账号提交手机号、分组、代理和权限");
|
||||
editor.OnDialogClosed();
|
||||
editor = new UserEditorDialogViewModel(userService);
|
||||
editor.OnDialogOpened(new DialogParameters { { "user", new UserInfo { Id = 1, UserName = "old-login",
|
||||
GroupId = 3, Authority = "微信回采,历史权限", Mobile = "13800000000", NickName = "测试" } } });
|
||||
Check(editor.Permissions[0].IsSelected, "编辑回填权限");
|
||||
editor.Permissions[0].IsSelected = false;
|
||||
await ((Prism.Commands.AsyncDelegateCommand)editor.ConfirmCommand).Execute();
|
||||
Check(handler.SavedUpdate?.Authority == "历史权限" && handler.PasswordTarget == null, "保留未知权限,留空不改密");
|
||||
editor.UpdatePasswords("new-password", "new-password", "");
|
||||
await ((Prism.Commands.AsyncDelegateCommand)editor.ConfirmCommand).Execute();
|
||||
Check(handler.PasswordTarget == "old-login", "按原登录名修改密码");
|
||||
await userService.DeleteAsync(1);
|
||||
Console.WriteLine("PASS: status bar bindings, colors and background progress reports.");
|
||||
return;
|
||||
@@ -267,10 +376,16 @@ class Program
|
||||
|
||||
sealed class LifecycleProbe : ViewModelBase
|
||||
{
|
||||
public int FirstLoads { get; private set; }
|
||||
public int Loads { get; private set; }
|
||||
public int Unloads { get; private set; }
|
||||
public int Closes { get; private set; }
|
||||
public bool CancelClose { get; set; }
|
||||
protected override void OnLoadedOnce()
|
||||
{
|
||||
if (Loads != 0) throw new InvalidOperationException("首次加载应先于 OnLoaded");
|
||||
FirstLoads++;
|
||||
}
|
||||
protected override void OnLoaded() => Loads++;
|
||||
protected override void OnUnloaded() => Unloads++;
|
||||
protected override void OnClosing(System.ComponentModel.CancelEventArgs e) => e.Cancel = CancelClose;
|
||||
@@ -279,18 +394,45 @@ sealed class LifecycleProbe : ViewModelBase
|
||||
|
||||
sealed class LoginHandler : HttpMessageHandler
|
||||
{
|
||||
public UserCreateRequest? SavedCreate { get; private set; }
|
||||
public string? LastUpdateBody { get; private set; }
|
||||
public UserUpdateRequest? SavedUpdate { get; private set; }
|
||||
public string? PasswordTarget { get; private set; }
|
||||
public int? LastGroupId { get; private set; }
|
||||
public int RequestCount { get; private set; }
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
RequestCount++;
|
||||
if (request.RequestUri?.AbsolutePath == "/api/v1/user/GetAllUser")
|
||||
{
|
||||
using var query = System.Text.Json.JsonDocument.Parse(await request.Content!.ReadAsStringAsync(cancellationToken));
|
||||
LastGroupId = query.RootElement.TryGetProperty("groupId", out var group) && group.ValueKind == System.Text.Json.JsonValueKind.Number
|
||||
? group.GetInt32() : null;
|
||||
await Task.Delay(30, cancellationToken);
|
||||
return new HttpResponseMessage(HttpStatusCode.OK)
|
||||
{
|
||||
Content = new StringContent("""{"code":200,"data":{"total":51,"items":[{"id":1,"userName":"admin"}]}}""", Encoding.UTF8, "application/json")
|
||||
};
|
||||
}
|
||||
string? route = request.RequestUri?.AbsolutePath;
|
||||
if (route is "/api/v1/user/AddSubUser" or "/api/v1/user/UpdateUser" or "/api/v1/user/ChangePassword")
|
||||
{
|
||||
string bodyText = await request.Content!.ReadAsStringAsync(cancellationToken);
|
||||
var options = new System.Text.Json.JsonSerializerOptions(System.Text.Json.JsonSerializerDefaults.Web);
|
||||
if (route.EndsWith("/AddSubUser"))
|
||||
SavedCreate = System.Text.Json.JsonSerializer.Deserialize<UserCreateRequest>(bodyText, options);
|
||||
else if (route.EndsWith("/UpdateUser"))
|
||||
{
|
||||
LastUpdateBody = bodyText;
|
||||
SavedUpdate = System.Text.Json.JsonSerializer.Deserialize<UserUpdateRequest>(bodyText, options);
|
||||
}
|
||||
else
|
||||
PasswordTarget = System.Text.Json.JsonSerializer.Deserialize<ChangePasswordRequest>(bodyText, options)?.UserName;
|
||||
return new HttpResponseMessage(HttpStatusCode.OK)
|
||||
{
|
||||
Content = new StringContent("""{"code":200,"data":{"id":1,"userName":"old-login","groupId":3,"authority":"历史权限"}}""", Encoding.UTF8, "application/json")
|
||||
};
|
||||
}
|
||||
if (request.Method == HttpMethod.Post && request.RequestUri?.PathAndQuery == "/api/v1/user/DelUser?id=1")
|
||||
{
|
||||
return new HttpResponseMessage(HttpStatusCode.OK)
|
||||
|
||||
Reference in new issue
Block a user