userviewmodel partion 1

This commit is contained in:
DismissedLight
2022-06-18 00:01:59 +08:00
parent 7342bfd590
commit 7a4777cf8f
10 changed files with 200 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
@@ -39,6 +40,7 @@ public partial class App : Application
{
IServiceProvider services = new ServiceCollection()
.AddLogging(builder => builder.AddDebug())
.AddSingleton<IMessenger>(WeakReferenceMessenger.Default)
.AddMemoryCache()
.AddDatebase()
.AddHttpClients()

View File

@@ -66,6 +66,20 @@ public static class EnumerableExtensions
return source ?? new();
}
/// <summary>
/// 对集合中的每个物品执行指定的操作
/// </summary>
/// <typeparam name="TSource">集合类型</typeparam>
/// <param name="source">集合</param>
/// <param name="action">指定的操作</param>
public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
{
foreach (TSource item in source)
{
action(item);
}
}
/// <summary>
/// 表示一个对 <see cref="TItem"/> 类型的计数器
/// </summary>

View File

@@ -0,0 +1,31 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using System.Collections.Generic;
namespace Snap.Hutao.Extension;
/// <summary>
/// 任务扩展
/// </summary>
public static class TaskExtensions
{
/// <summary>
/// 安全的触发任务
/// </summary>
/// <param name="task">任务</param>
/// <param name="logger">日志器</param>
[SuppressMessage("", "VSTHRD003")]
[SuppressMessage("", "VSTHRD100")]
public static async void SafeForget(this Task task, ILogger? logger = null)
{
try
{
await task;
}
catch (Exception e)
{
logger?.LogError(e, "{caller}:{exception}", nameof(SafeForget), e.GetBaseException());
}
}
}

View File

@@ -22,4 +22,4 @@ public static class TupleExtensions
{
return new Dictionary<TKey, TValue>(1) { { tuple.Key, tuple.Value } };
}
}
}

View File

@@ -8,16 +8,18 @@
mc:Ignorable="d">
<Grid>
<Grid.Background>
<ImageBrush ImageSource="https://i.loli.net/2020/07/07/2wSuTsFci3ZKNMl.jpg"/>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="48.8"/>
<RowDefinition/>
</Grid.RowDefinitions>
<view:TitleView
x:Name="TitleBarView">
</view:TitleView>
<view:MainView Grid.Row="1"/>
Grid.Row="0"
x:Name="TitleBarView"/>
<view:MainView
Grid.Row="1"/>
</Grid>
</Window>

View File

@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Web.Hoyolab.Bbs.User;
using System.ComponentModel.DataAnnotations.Schema;
namespace Snap.Hutao.Model.Entity;
@@ -15,4 +16,10 @@ public class User
/// 用户的Cookie
/// </summary>
public string? Cookie { get; set; }
/// <summary>
/// 用户信息
/// </summary>
[NotMapped]
public UserInfo? UserInfo { get; set; }
}

View File

@@ -2,6 +2,8 @@
// Licensed under the MIT license.
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Web.Hoyolab.Bbs.User;
using System.Collections.Generic;
namespace Snap.Hutao.Service.Abstraction;
@@ -14,4 +16,11 @@ public interface IUserService
/// 获取当前用户信息
/// </summary>
User Current { get; }
/// <summary>
/// 获取用户信息枚举
/// 每个用户信息都应准备完成
/// </summary>
/// <returns>准备完成的用户信息枚举</returns>
Task<IEnumerable<User>> GetInitializedUsersAsync();
}

View File

@@ -0,0 +1,20 @@
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Snap.Hutao.Service;
/// <summary>
/// 用户服务
/// </summary>
[Injection(InjectAs.Transient)]
internal class UserService : IUserService
{
public User Current { get => throw new NotImplementedException(); }
}

View File

@@ -45,9 +45,6 @@
</Style>
</Flyout.FlyoutPresenterStyle>
<StackPanel Width="192">
<CommandBar DefaultLabelPosition="Right">
<AppBarButton Icon="Add" Label="添加新用户"/>
</CommandBar>
<ListView
Grid.Row="1"
Margin="4"
@@ -56,6 +53,9 @@
<ListViewItem Content="角色2"/>
</ListView>
<MenuFlyoutSeparator/>
<CommandBar DefaultLabelPosition="Right">
<AppBarButton Icon="Add" Label="添加新用户"/>
</CommandBar>
<ListView
Grid.Row="1"
Margin="4"
@@ -64,6 +64,8 @@
<ListViewItem Content="用户2"/>
<ListViewItem Content="用户3"/>
<ListViewItem Content="用户4"/>
<ListViewItem Content="用户1"/>
<ListViewItem Content="用户1"/>
</ListView>
</StackPanel>
</Flyout>

View File

@@ -0,0 +1,104 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Snap.Hutao.Extension;
using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
namespace Snap.Hutao.ViewModel;
/// <summary>
/// 用户视图模型
/// </summary>
[Injection(InjectAs.Transient)]
internal class UserViewModel : ObservableObject
{
private readonly IUserService userService;
private readonly UserGameRoleClient userGameRoleClient;
private readonly ILogger<UserViewModel> logger;
private User? selectedUserInfo;
private ObservableCollection<User>? userInfos;
private UserGameRole? selectedUserGameRole;
private ObservableCollection<UserGameRole>? userGameRoles;
/// <summary>
/// 构造一个新的用户视图模型
/// </summary>
/// <param name="userService">用户服务</param>
/// <param name="userGameRoleClient">用户角色信息客户端</param>
/// <param name="asyncRelayCommandFactory">异步命令工厂</param>
public UserViewModel(IUserService userService, UserGameRoleClient userGameRoleClient, IAsyncRelayCommandFactory asyncRelayCommandFactory, ILogger<UserViewModel> logger)
{
this.userService = userService;
this.userGameRoleClient = userGameRoleClient;
this.logger = logger;
OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
}
/// <summary>
/// 当前选择的用户信息
/// </summary>
public User? SelectedUser
{
get => selectedUserInfo;
set
{
if (SetProperty(ref selectedUserInfo, value) && value != null)
{
UpdateUserGameRolesAsync().SafeForget(logger);
}
}
}
/// <summary>
/// 用户信息集合
/// </summary>
public ObservableCollection<User>? Users { get => userInfos; set => SetProperty(ref userInfos, value); }
/// <summary>
/// 选择的角色信息
/// </summary>
public UserGameRole? SelectedUserGameRole { get => selectedUserGameRole; set => SetProperty(ref selectedUserGameRole, value); }
/// <summary>
/// 角色信息集合
/// </summary>
public ObservableCollection<UserGameRole>? UserGameRoles
{
get => userGameRoles;
set
{
if (SetProperty(ref userGameRoles, value))
{
if (value != null)
{
SelectedUserGameRole = value.FirstOrDefault(role => role.IsChosen) ?? value.FirstOrDefault();
}
else
{
SelectedUserGameRole = null;
}
}
}
}
/// <summary>
/// 打开界面命令
/// </summary>
public ICommand OpenUICommand { get; }
private async Task OpenUIAsync()
{
Users = new(await userService.GetInitializedUsersAsync());
SelectedUser = Users.FirstOrDefault();
}
private async Task UpdateUserGameRolesAsync()
{
UserGameRoles = new(await userGameRoleClient.GetUserGameRolesAsync());
}
}