feat: 更新识别工具逻辑与显示效果 (#12791)

* feat: 仓库识别持久化储存

* feat: 干员识别数据支持启动时显示

* fix: 小工具初始化

* perf: 干员识别使用 VirtualizingWrapPanel,加快加载速度

* perf: 掉落识别使用 VirtualizingWrapPanel,加快加载速度

* feat: 逐项滚动
This commit is contained in:
uye
2025-05-26 16:48:24 +08:00
committed by GitHub
parent 1803f77325
commit 87bbd07ecf
4 changed files with 98 additions and 56 deletions

View File

@@ -105,6 +105,8 @@ namespace MaaWpfGui.Constants
public const string AutoSetTime = "Recruit.AutoSetTime";
public const string RecruitmentShowPotential = "Recruit.ShowPotential";
public const string DepotResult = "Depot.DepotResult";
public const string InfrastMode = "Infrast.InfrastMode";
public const string DormThreshold = "Infrast.DormThreshold";
public const string UsesOfDrones = "Infrast.UsesOfDrones";

View File

@@ -134,6 +134,7 @@
<PackageReference Include="Stylet" Version="1.3.6" />
<PackageReference Include="System.Management" Version="8.0.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
<PackageReference Include="VirtualizingWrapPanel" Version="2.2.1" />
<PackageReference Include="WindowsAPICodePack" Version="8.0.6" />
</ItemGroup>

View File

@@ -54,6 +54,8 @@ namespace MaaWpfGui.ViewModels.UI
_peepImageTimer.Elapsed += RefreshPeepImageAsync;
_peepImageTimer.Interval = 1000d / PeepTargetFps;
_gachaTimer.Tick += RefreshGachaTip;
LoadDepotDetails();
LoadOperBoxDetails();
}
private void RunningState_IdleChanged(object? sender, bool e)
@@ -351,6 +353,31 @@ namespace MaaWpfGui.ViewModels.UI
public string? Count { get; set; }
}
private void SaveDepotDetails(JObject details)
{
var json = details.ToString(Formatting.None);
ConfigurationHelper.SetValue(ConfigurationKeys.DepotResult, json);
}
private void LoadDepotDetails()
{
var json = ConfigurationHelper.GetValue(ConfigurationKeys.DepotResult, string.Empty);
if (string.IsNullOrWhiteSpace(json))
{
return;
}
try
{
var details = JObject.Parse(json);
DepotParse(details);
}
catch
{
// 兼容老数据或异常时忽略
}
}
/// <summary>
/// Gets or sets the ArkPlanner result.
/// </summary>
@@ -424,6 +451,7 @@ namespace MaaWpfGui.ViewModels.UI
}
DepotInfo = LocalizationHelper.GetString("IdentificationCompleted");
SaveDepotDetails(details);
return true;
}
@@ -530,7 +558,7 @@ namespace MaaWpfGui.ViewModels.UI
public string OperBoxExportData { get; set; } = string.Empty;
private JArray _operBoxDataArray = (JArray)(JsonConvert.DeserializeObject(ConfigurationHelper.GetValue(ConfigurationKeys.OperBoxData, new JArray().ToString())) ?? new JArray());
private JArray _operBoxDataArray = [];
public JArray OperBoxDataArray
{
@@ -538,7 +566,6 @@ namespace MaaWpfGui.ViewModels.UI
set
{
SetAndNotify(ref _operBoxDataArray, value);
ConfigurationHelper.SetValue(ConfigurationKeys.OperBoxData, value.ToString());
_operBoxPotential = null; // reset
}
}
@@ -591,10 +618,7 @@ namespace MaaWpfGui.ViewModels.UI
public ObservableCollection<Operator> OperBoxHaveList
{
get => _operBoxHaveList;
set
{
SetAndNotify(ref _operBoxHaveList, value);
}
set => SetAndNotify(ref _operBoxHaveList, value);
}
private ObservableCollection<Operator> _operBoxNotHaveList = [];
@@ -602,9 +626,31 @@ namespace MaaWpfGui.ViewModels.UI
public ObservableCollection<Operator> OperBoxNotHaveList
{
get => _operBoxNotHaveList;
set
set => SetAndNotify(ref _operBoxNotHaveList, value);
}
private void SaveOperBoxDetails(JObject details)
{
var json = details.ToString(Formatting.None);
ConfigurationHelper.SetValue(ConfigurationKeys.OperBoxData, json);
}
private void LoadOperBoxDetails()
{
var json = ConfigurationHelper.GetValue(ConfigurationKeys.OperBoxData, string.Empty);
if (string.IsNullOrWhiteSpace(json))
{
SetAndNotify(ref _operBoxNotHaveList, value);
return;
}
try
{
var details = JObject.Parse(json);
OperBoxParse(details);
}
catch
{
// 兼容老数据或异常时忽略
}
}
@@ -613,15 +659,20 @@ namespace MaaWpfGui.ViewModels.UI
public bool OperBoxParse(JObject? details)
{
var allOpers = (details?["all_opers"] as JArray)?.Cast<JObject>().Where(o => o["id"] != null).ToList();
var ownOpers = (details?["own_opers"] as JArray)?.Cast<JObject>().Where(o => o["id"] != null).ToList();
if (details == null)
{
return false;
}
var allOpers = (details["all_opers"] as JArray)?.Cast<JObject>().Where(o => o["id"] != null).ToList();
var ownOpers = (details["own_opers"] as JArray)?.Cast<JObject>().Where(o => o["id"] != null).ToList();
if (allOpers == null || ownOpers == null)
{
return false;
}
bool done = (bool)(details?["done"] ?? false);
bool done = (bool)(details["done"] ?? false);
var ownOperDict = ownOpers.ToDictionary(o => (string)o["id"]!);
var allOperDict = allOpers.ToDictionary(o => (string)o["id"]!);
foreach (var operBox in allOpers)
@@ -671,7 +722,7 @@ namespace MaaWpfGui.ViewModels.UI
}
OperBoxExportData = exportList.ToString(Formatting.Indented);
_runningState.SetIdle(true);
SaveOperBoxDetails(details);
return true;
}

View File

@@ -11,6 +11,7 @@
xmlns:s="https://github.com/canton7/Stylet"
xmlns:ui="clr-namespace:MaaWpfGui.ViewModels.UI"
xmlns:uiBehaviors="clr-namespace:MaaWpfGui.Extensions.UIBehaviors"
xmlns:vwp="clr-namespace:WpfToolkit.Controls;assembly=VirtualizingWrapPanel"
d:DataContext="{d:DesignInstance {x:Type ui:RecognizerViewModel}}"
d:DesignHeight="600"
d:DesignWidth="800"
@@ -186,7 +187,7 @@
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="150" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<controls:TextBlock
@@ -199,24 +200,18 @@
Style="{StaticResource TextBlockDefaultBold}"
Text="{Binding OperBoxInfo}"
TextWrapping="Wrap" />
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<controls:TextBlock
Grid.Row="0"
Margin="10"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Text="{c:Binding OperBoxNotHaveList.Count,
StringFormat={StaticResource OperBoxNotHaveList}}"
Visibility="{c:Binding 'OperBoxNotHaveList.Count != 0'}" />
<TabControl
Grid.Row="1"
Background="{DynamicResource MouseOverRegionBrush}"
BorderThickness="0"
SelectedIndex="{c:Binding 'OperBoxNotHaveList.Count != 0 ? 0 : 1',
Mode=OneTime}"
Style="{StaticResource TabControlSliding}">
<TabItem
Header="{c:Binding OperBoxNotHaveList.Count}"
HeaderStringFormat="{StaticResource OperBoxNotHaveList}"
Visibility="{c:Binding 'OperBoxNotHaveList.Count != 0'}">
<DataGrid
Grid.Row="1"
Width="680"
HorizontalAlignment="Center"
VerticalAlignment="Stretch"
@@ -224,30 +219,24 @@
HeadersVisibility="None"
IsReadOnly="True"
ItemsSource="{Binding OperBoxNotHaveList}"
PreviewMouseWheel="{s:Action RouteMouseWheelToParent,
Target={x:Type helper:MouseWheelHelper}}"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Visibility="{c:Binding 'OperBoxNotHaveList.Count != 0'}">
VirtualizingPanel.ScrollUnit="Pixel">
<DataGrid.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Center" />
<vwp:VirtualizingWrapPanel HorizontalAlignment="Center" />
</ItemsPanelTemplate>
</DataGrid.ItemsPanel>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" />
<DataGridTextColumn MinWidth="130" Binding="{Binding Name}" />
</DataGrid.Columns>
</DataGrid>
<controls:TextBlock
Grid.Row="2"
Margin="10"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Text="{c:Binding OperBoxHaveList.Count,
StringFormat={StaticResource OperBoxHaveList}}"
Visibility="{c:Binding 'OperBoxHaveList.Count != 0'}" />
</TabItem>
<TabItem
Header="{c:Binding OperBoxHaveList.Count}"
HeaderStringFormat="{StaticResource OperBoxHaveList}"
Visibility="{c:Binding 'OperBoxHaveList.Count != 0'}">
<DataGrid
Grid.Row="3"
Width="680"
HorizontalAlignment="Center"
VerticalAlignment="Stretch"
@@ -255,25 +244,23 @@
HeadersVisibility="None"
IsReadOnly="True"
ItemsSource="{Binding OperBoxHaveList}"
PreviewMouseWheel="{s:Action RouteMouseWheelToParent,
Target={x:Type helper:MouseWheelHelper}}"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Visibility="{c:Binding 'OperBoxHaveList.Count != 0'}">
VirtualizingPanel.ScrollUnit="Pixel">
<DataGrid.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Center" />
<vwp:VirtualizingWrapPanel HorizontalAlignment="Center" />
</ItemsPanelTemplate>
</DataGrid.ItemsPanel>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" />
<DataGridTextColumn MinWidth="130" Binding="{Binding Name}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</ScrollViewer>
</TabItem>
</TabControl>
<StackPanel
Grid.Row="2"
Margin="27,0"
Margin="0,10,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsEnabled="{Binding Idle}"
@@ -281,14 +268,14 @@
<Button
Width="180"
Height="70"
Margin="30"
Margin="30,0"
Command="{s:Action ExportOperBox}"
Content="{DynamicResource OperBoxCopyToClipboard}"
IsEnabled="{Binding Idle}" />
<Button
Width="180"
Height="70"
Margin="30"
Margin="30,0"
Command="{s:Action StartOperBox}"
Content="{DynamicResource StartToOperBoxRecognition}"
IsEnabled="{Binding Idle}" />
@@ -323,10 +310,11 @@
IsReadOnly="True"
ItemsSource="{Binding DepotResult}"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
VirtualizingPanel.ScrollUnit="Pixel">
<DataGrid.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Center" />
<vwp:VirtualizingWrapPanel HorizontalAlignment="Center" />
</ItemsPanelTemplate>
</DataGrid.ItemsPanel>
<DataGrid.Columns>