mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
userviewmodel partion 1
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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>
|
||||
|
||||
31
src/Snap.Hutao/Snap.Hutao/Extension/TaskExtensions.cs
Normal file
31
src/Snap.Hutao/Snap.Hutao/Extension/TaskExtensions.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,4 +22,4 @@ public static class TupleExtensions
|
||||
{
|
||||
return new Dictionary<TKey, TValue>(1) { { tuple.Key, tuple.Value } };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
20
src/Snap.Hutao/Snap.Hutao/Service/UserService.cs
Normal file
20
src/Snap.Hutao/Snap.Hutao/Service/UserService.cs
Normal 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(); }
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
104
src/Snap.Hutao/Snap.Hutao/ViewModel/UserViewModel.cs
Normal file
104
src/Snap.Hutao/Snap.Hutao/ViewModel/UserViewModel.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user