1
0
mirror of https://github.com/wangdage12/Snap.Hutao.git synced 2026-07-31 04:10:25 +08:00

在养成计划,同步所有角色与武器 弹出的 批量添加或更新到当前养成计划 中增加 同步背包物品 ,同步角色信息 (同我的角色,同步角色信息) 两个勾选项

This commit is contained in:
mfkvfhpdx
2026-05-04 14:23:41 +08:00
parent 7a3f125846
commit 9ea2bb1a6e
5 changed files with 98 additions and 5 deletions
@@ -21,4 +21,14 @@ internal sealed class CultivateProjectAvatarPropertyBatchPreferences
public int ConsumptionSaveStrategyIndex { get; set; }
public bool ClearAvatarAndWeaponEntriesBeforeSync { get; set; }
/// <summary>
/// 执行批量前是否先通过养成计算器将游戏背包同步到当前计划(与养成计划「同步背包物品」一致)。
/// </summary>
public bool SyncInventoryItems { get; set; }
/// <summary>
/// 执行批量前是否先从米游社原神战绩同步「我的角色」数据(与我的角色「同步角色信息」一致)。
/// </summary>
public bool SyncCharacterInfo { get; set; }
}
@@ -5,10 +5,17 @@ using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Factory.ContentDialog;
using Snap.Hutao.Model.Calculable;
using Snap.Hutao.Model.Cultivation;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.Entity.Primitive;
using Snap.Hutao.Model.Primitive;
using Snap.Hutao.Service.AvatarInfo;
using Snap.Hutao.Service.AvatarInfo.Factory;
using Snap.Hutao.Service.Cultivation.Consumption;
using Snap.Hutao.Service.Cultivation.Offline;
using Snap.Hutao.Service.Inventory;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Service.Metadata.ContextAbstraction;
using Snap.Hutao.Service.User;
using Snap.Hutao.UI.Xaml.View.Dialog;
using Snap.Hutao.ViewModel.AvatarProperty;
using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
@@ -62,13 +69,66 @@ internal sealed partial class AvatarPropertyBatchCultivateService : IAvatarPrope
BatchCultivateResult result = default;
using (await contentDialogFactory.BlockAsync(progressDialog).ConfigureAwait(false))
{
ImmutableArray<AvatarView> avatarsToProcess = targetAvatars;
if (baseline.SyncCharacterInfo)
{
IUserService userService = serviceProvider.GetRequiredService<IUserService>();
if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid)
{
IServiceScopeFactory scopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
using (IServiceScope scope = scopeFactory.CreateScope())
{
IAvatarInfoService avatarInfoService = scope.ServiceProvider.GetRequiredService<IAvatarInfoService>();
Summary? refreshed = await avatarInfoService
.GetSummaryAsync(metadataContext, userAndUid, global::Snap.Hutao.Service.AvatarInfo.RefreshOptionKind.RequestFromHoyolabGameRecord, cancellationToken)
.ConfigureAwait(false);
if (refreshed?.Avatars.Source is { Count: > 0 } sourceAvatars)
{
HashSet<AvatarId> wanted = [.. targetAvatars.Select(static a => a.Id)];
ImmutableArray<AvatarView>.Builder filtered = ImmutableArray.CreateBuilder<AvatarView>();
foreach (AvatarView avatar in sourceAvatars)
{
if (wanted.Contains(avatar.Id))
{
filtered.Add(avatar);
}
}
if (filtered.Count > 0)
{
avatarsToProcess = filtered.ToImmutable();
}
}
}
}
}
if (baseline.SyncInventoryItems)
{
CultivateProject? project = await cultivationService.GetCurrentProjectAsync().ConfigureAwait(false);
if (project is not null)
{
IMetadataService metadataService = serviceProvider.GetRequiredService<IMetadataService>();
ICultivationMetadataContext cultivationContext = await metadataService
.GetContextAsync<CultivationMetadataContext>(cancellationToken)
.ConfigureAwait(false);
IInventoryService inventoryService = serviceProvider.GetRequiredService<IInventoryService>();
await inventoryService
.RefreshInventoryAsync(RefreshOptions.CreateForWebCalculator(project, cultivationContext))
.ConfigureAwait(false);
}
}
if (baseline.ClearAvatarAndWeaponEntriesBeforeSync)
{
await cultivationService.RemoveAvatarAndWeaponEntriesForCurrentProjectAsync().ConfigureAwait(false);
}
ImmutableArray<CalculatorAvatarPromotionDelta>.Builder deltasBuilder = ImmutableArray.CreateBuilder<CalculatorAvatarPromotionDelta>();
foreach (AvatarView avatar in targetAvatars)
foreach (AvatarView avatar in avatarsToProcess)
{
if (!baseline.Delta.TryGetNonErrorCopy(avatar, out CalculatorAvatarPromotionDelta? copy))
{
@@ -121,6 +181,8 @@ internal sealed partial class AvatarPropertyBatchCultivateService : IAvatarPrope
WeaponLevelTarget = d.Weapon?.LevelTarget ?? 90U,
ConsumptionSaveStrategyIndex = (int)baseline.Strategy,
ClearAvatarAndWeaponEntriesBeforeSync = baseline.ClearAvatarAndWeaponEntriesBeforeSync,
SyncInventoryItems = baseline.SyncInventoryItems,
SyncCharacterInfo = baseline.SyncCharacterInfo,
};
}
@@ -20,7 +20,9 @@
<x:Double x:Key="SettingsCardWrapThreshold">0</x:Double>
<x:Double x:Key="SettingsCardWrapNoIconThreshold">0</x:Double>
</ContentDialog.Resources>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
<!-- ScrollViewer:随 ContentDialog 主题高度上限自适应;内容过高时纵向滚动,避免裁切或写死 MaxHeight -->
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
<cwc:SettingsCard Header="{shuxm:ResourceString Name=ViewDialogCultivateBatchAvatarLevelTarget}">
<NumberBox
MinWidth="{StaticResource NumberBoxMinWidth}"
@@ -82,5 +84,14 @@
Margin="0,13,0,0"
Content="{shuxm:ResourceString Name=ViewDialogCultivateBatchClearAvatarAndWeaponEntries}"
IsChecked="{x:Bind ClearAvatarAndWeaponEntriesBeforeSync, Mode=TwoWay}"/>
</StackPanel>
<CheckBox
Margin="0,6,0,0"
Content="{shuxm:ResourceString Name=ViewPageCultivationRefreshInventory}"
IsChecked="{x:Bind SyncInventoryItems, Mode=TwoWay}"/>
<CheckBox
Margin="0,6,0,0"
Content="{shuxm:ResourceString Name=ViewAvatarPropertySyncDataButtonLabel}"
IsChecked="{x:Bind SyncCharacterInfo, Mode=TwoWay}"/>
</StackPanel>
</ScrollViewer>
</ContentDialog>
@@ -12,6 +12,8 @@ namespace Snap.Hutao.UI.Xaml.View.Dialog;
[DependencyProperty<AvatarPromotionDelta>("PromotionDelta", NotNull = true, CreateDefaultValueCallbackName = nameof(CreatePromotionDeltaDefaultValue))]
[DependencyProperty<bool>("ClearAvatarAndWeaponEntriesBeforeSync", DefaultValue = false, NotNull = true)]
[DependencyProperty<bool>("SyncInventoryItems", DefaultValue = false, NotNull = true)]
[DependencyProperty<bool>("SyncCharacterInfo", DefaultValue = false, NotNull = true)]
internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
{
private readonly IContentDialogFactory contentDialogFactory;
@@ -56,7 +58,7 @@ internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
LocalSetting.Set(SettingKeys.CultivationWeapon90LevelTarget, weapon.LevelTarget);
}
return new(true, new CultivatePromotionDeltaOptions(PromotionDelta, (ConsumptionSaveStrategyKind)SaveModeSelector.SelectedIndex, ClearAvatarAndWeaponEntriesBeforeSync));
return new(true, new CultivatePromotionDeltaOptions(PromotionDelta, (ConsumptionSaveStrategyKind)SaveModeSelector.SelectedIndex, ClearAvatarAndWeaponEntriesBeforeSync, SyncInventoryItems, SyncCharacterInfo));
}
private void ApplyInitialPreferences(CultivateProjectAvatarPropertyBatchPreferences p)
@@ -77,6 +79,8 @@ internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
SaveModeSelector.SelectedIndex = int.Clamp(p.ConsumptionSaveStrategyIndex, 0, 2);
ClearAvatarAndWeaponEntriesBeforeSync = p.ClearAvatarAndWeaponEntriesBeforeSync;
SyncInventoryItems = p.SyncInventoryItems;
SyncCharacterInfo = p.SyncCharacterInfo;
}
private static object CreatePromotionDeltaDefaultValue()
@@ -8,7 +8,7 @@ namespace Snap.Hutao.UI.Xaml.View.Dialog;
internal sealed class CultivatePromotionDeltaOptions
{
public CultivatePromotionDeltaOptions(AvatarPromotionDelta delta, ConsumptionSaveStrategyKind strategy, bool clearAvatarAndWeaponEntriesBeforeSync = false)
public CultivatePromotionDeltaOptions(AvatarPromotionDelta delta, ConsumptionSaveStrategyKind strategy, bool clearAvatarAndWeaponEntriesBeforeSync = false, bool syncInventoryItems = false, bool syncCharacterInfo = false)
{
delta.AvatarLevelTarget = delta.AvatarLevelTarget switch
{
@@ -20,6 +20,8 @@ internal sealed class CultivatePromotionDeltaOptions
Delta = delta;
Strategy = strategy;
ClearAvatarAndWeaponEntriesBeforeSync = clearAvatarAndWeaponEntriesBeforeSync;
SyncInventoryItems = syncInventoryItems;
SyncCharacterInfo = syncCharacterInfo;
}
public AvatarPromotionDelta Delta { get; }
@@ -30,4 +32,8 @@ internal sealed class CultivatePromotionDeltaOptions
/// 批量同步前是否清空当前计划中已有的角色与武器养成条目(不含家具等其它类型)。
/// </summary>
public bool ClearAvatarAndWeaponEntriesBeforeSync { get; }
public bool SyncInventoryItems { get; }
public bool SyncCharacterInfo { get; }
}