This commit is contained in:
辉鸭蛋
2025-04-14 00:38:55 +08:00
parent 8ad8193d8e
commit 694043e7b7
14 changed files with 556 additions and 238 deletions

View File

@@ -106,6 +106,7 @@ public partial class App : Application
services.AddView<MapPathingPage, MapPathingViewModel>();
services.AddView<OneDragonFlowPage, OneDragonFlowViewModel>();
services.AddSingleton<PathingConfigViewModel>();
services.AddView<TaskGroupPage, TaskGroupPageViewModel>();
// services.AddView<PathingConfigView, PathingConfigViewModel>();
services.AddView<KeyBindingsSettingsPage, KeyBindingsSettingsPageViewModel>();

View File

@@ -1,148 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<LangVersion>12.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationIcon>Assets\Images\logo.ico</ApplicationIcon>
<AssemblyName>BetterGI</AssemblyName>
<AssemblyVersion>0.36.2</AssemblyVersion>
<Platforms>x64</Platforms>
<DebugType>embedded</DebugType>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\Images\*.jpg" />
<None Remove="Assets\Images\*" />
<None Remove="Assets\Images\*.png" />
<None Remove="Assets\Images\*.ico" />
<None Remove="Assets\Fonts\*.ttf" />
<None Remove="Assets\Highlighting\*.xshd" />
<None Remove="Assets\Strings\*.html" />
<None Remove="Assets\Strings\*.md" />
<None Remove="Assets\Audios\*.mp3" />
</ItemGroup>
<ItemGroup>
<Resource Include="Assets\Images\*.jpg" />
<Resource Include="Assets\Images\Anniversary\*" />
<Resource Include="Assets\Images\*.png" />
<Resource Include="Assets\Images\*.ico" />
<Resource Include="Assets\Fonts\*.ttf" />
<Resource Include="Assets\Highlighting\*.xshd" />
<Resource Include="Assets\Strings\*.html" />
<Resource Include="Assets\Strings\*.md" />
<Resource Include="Assets\Audios\*.mp3" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AvalonEdit" Version="6.3.0.90" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.ML.OnnxRuntime.DirectML" Version="1.18.1" />
<PackageReference Include="Microsoft.ML.OnnxRuntime.Managed" Version="1.18.1" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2592.51" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
<PackageReference Include="OpenCvSharp4.WpfExtensions" Version="4.8.0.20230708" />
<PackageReference Include="OpenCvSharp4.Extensions" Version="4.8.0.20230708" />
<PackageReference Include="OpenCvSharp4.Windows" Version="4.8.0.20230708" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.122" />
<PackageReference Include="Microsoft.ClearScript.V8" Version="7.4.5" />
<PackageReference Include="Microsoft.ClearScript.V8.Native.win-x64" Version="7.4.5" />
<PackageReference Include="MouseKeyHook" Version="5.7.1" />
<PackageReference Include="PresentMonFps" Version="2.0.5" />
<PackageReference Include="Sdcb.PaddleInference" Version="2.5.0.1" />
<PackageReference Include="Sdcb.PaddleInference.runtime.win64.openblas" Version="2.5.1" />
<PackageReference Include="Sdcb.PaddleOCR" Version="2.7.0" />
<PackageReference Include="Sdcb.PaddleOCR.Models.Online" Version="2.7.0.1" />
<PackageReference Include="Sdl.MultiSelectComboBox" Version="1.0.103" />
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.RichTextBoxEx.Wpf" Version="1.1.0.1" />
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
<PackageReference Include="Vanara.PInvoke.NtDll" Version="4.0.2" />
<PackageReference Include="Vanara.PInvoke.SHCore" Version="4.0.2" />
<PackageReference Include="Vanara.PInvoke.User32" Version="4.0.2" />
<PackageReference Include="WPF-UI" Version="3.0.5" />
<PackageReference Include="WPF-UI.Tray" Version="3.0.5" />
<PackageReference Include="WPF-UI.Violeta" Version="3.0.5.23" />
<PackageReference Include="YoloV8" Version="4.1.7" />
<PackageReference Include="gong-wpf-dragdrop" Version="3.2.1" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Debug'">
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Fischless.GameCapture\Fischless.GameCapture.csproj" />
<ProjectReference Include="..\Fischless.HotkeyCapture\Fischless.HotkeyCapture.csproj" />
<ProjectReference Include="..\Fischless.WindowsInput\Fischless.WindowsInput.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Assets\Map\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Assets\Model\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoFight\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoFight\Assets\combat_avatar.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoFishing\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoGeniusInvokation\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoGeniusInvokation\Assets\tcg_character_card.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoPick\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoSkip\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoSkip\Assets\hangout.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoTrackPath\Assets\tp.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\Common\Element\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoWood\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\GameLoading\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\QuickTeleport\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\QuickSereniteaPot\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="User\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="GameTask\Common\Element\Assets\新文件夹\" />
<Folder Include="GameTask\OneDragon\" />
<Folder Include="User\AutoPathing\" />
</ItemGroup>
</Project>

View File

@@ -47,6 +47,7 @@
<PackageReference Include="DeviceId.Windows" Version="6.8.0" />
<PackageReference Include="DeviceId.Windows.Wmi" Version="6.8.0" />
<PackageReference Include="Emoji.Wpf" Version="0.3.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="2.0.0-preview1-final" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.14" />

View File

@@ -0,0 +1,87 @@
// <auto-generated />
using System;
using BetterGenshinImpact.Model.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace BetterGenshinImpact.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20250413162606_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "8.0.3");
modelBuilder.Entity("BetterGenshinImpact.Model.Database.TaskGroup", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasColumnName("id");
b.Property<string>("Category")
.HasMaxLength(50)
.HasColumnType("TEXT")
.HasColumnName("category");
b.Property<string>("Hotkey")
.HasMaxLength(50)
.HasColumnType("TEXT")
.HasColumnName("hotkey");
b.Property<string>("Hotkey2")
.HasMaxLength(50)
.HasColumnType("TEXT")
.HasColumnName("hotkey_");
b.Property<DateTime?>("LastRunTime")
.HasColumnType("TEXT")
.HasColumnName("last_run_time");
b.Property<DateTime?>("NextRunTime")
.HasColumnType("TEXT")
.HasColumnName("next_run_time");
b.Property<int>("OrderIndex")
.HasColumnType("INTEGER")
.HasColumnName("order_index");
b.Property<string>("ScheduleExpression")
.HasMaxLength(255)
.HasColumnType("TEXT")
.HasColumnName("schedule_expression");
b.Property<string>("ScheduleType")
.HasMaxLength(50)
.HasColumnType("TEXT")
.HasColumnName("schedule_type");
b.Property<string>("TaskName")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("TEXT")
.HasColumnName("task_name");
b.Property<string>("TaskParams")
.HasColumnType("TEXT")
.HasColumnName("task_params");
b.HasKey("Id");
b.HasIndex("OrderIndex")
.IsUnique();
b.ToTable("task_group");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BetterGenshinImpact.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "task_group",
columns: table => new
{
id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
order_index = table.Column<int>(type: "INTEGER", nullable: false),
task_name = table.Column<string>(type: "TEXT", maxLength: 255, nullable: false),
task_params = table.Column<string>(type: "TEXT", nullable: true),
schedule_expression = table.Column<string>(type: "TEXT", maxLength: 255, nullable: true),
schedule_type = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
next_run_time = table.Column<DateTime>(type: "TEXT", nullable: true),
last_run_time = table.Column<DateTime>(type: "TEXT", nullable: true),
hotkey = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
hotkey_ = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
category = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_task_group", x => x.id);
});
migrationBuilder.CreateIndex(
name: "IX_task_group_order_index",
table: "task_group",
column: "order_index",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "task_group");
}
}
}

View File

@@ -0,0 +1,84 @@
// <auto-generated />
using System;
using BetterGenshinImpact.Model.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace BetterGenshinImpact.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "8.0.3");
modelBuilder.Entity("BetterGenshinImpact.Model.Database.TaskGroup", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasColumnName("id");
b.Property<string>("Category")
.HasMaxLength(50)
.HasColumnType("TEXT")
.HasColumnName("category");
b.Property<string>("Hotkey")
.HasMaxLength(50)
.HasColumnType("TEXT")
.HasColumnName("hotkey");
b.Property<string>("Hotkey2")
.HasMaxLength(50)
.HasColumnType("TEXT")
.HasColumnName("hotkey_");
b.Property<DateTime?>("LastRunTime")
.HasColumnType("TEXT")
.HasColumnName("last_run_time");
b.Property<DateTime?>("NextRunTime")
.HasColumnType("TEXT")
.HasColumnName("next_run_time");
b.Property<int>("OrderIndex")
.HasColumnType("INTEGER")
.HasColumnName("order_index");
b.Property<string>("ScheduleExpression")
.HasMaxLength(255)
.HasColumnType("TEXT")
.HasColumnName("schedule_expression");
b.Property<string>("ScheduleType")
.HasMaxLength(50)
.HasColumnType("TEXT")
.HasColumnName("schedule_type");
b.Property<string>("TaskName")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("TEXT")
.HasColumnName("task_name");
b.Property<string>("TaskParams")
.HasColumnType("TEXT")
.HasColumnName("task_params");
b.HasKey("Id");
b.HasIndex("OrderIndex")
.IsUnique();
b.ToTable("task_group");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -2,24 +2,20 @@ using System.IO;
using BetterGenshinImpact.Core.Config;
using Microsoft.EntityFrameworkCore;
namespace BetterGenshinImpact.Model.Database
namespace BetterGenshinImpact.Model.Database;
public class ApplicationDbContext : DbContext
{
public class ApplicationDbContext : DbContext
public DbSet<TaskGroup> TaskGroups { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
public DbSet<TaskList> TaskLists { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var dbPath = Path.Combine(Global.Absolute("User\\db"), "Data", "bgi_user.db");
Directory.CreateDirectory(Path.GetDirectoryName(dbPath)!);
optionsBuilder.UseSqlite($"Data Source={dbPath}");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TaskList>()
.HasIndex(t => t.OrderIndex)
.IsUnique();
}
var dbPath = Path.Combine(Global.Absolute("User\\Db"), "bgi_user.db");
Directory.CreateDirectory(Path.GetDirectoryName(dbPath)!);
optionsBuilder.UseSqlite($"Data Source={dbPath}");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BetterGenshinImpact.Model.Database;
[Table("task_group")]
public class TaskGroup
{
[Key]
[Column("id")]
public int Id { get; set; }
[Column("order_index")]
public int OrderIndex { get; set; }
[Column("task_name")]
[Required]
[MaxLength(255)]
public string TaskName { get; set; } = string.Empty;
[Column("task_params")]
public string? TaskParams { get; set; }
[Column("schedule_expression")]
[MaxLength(255)]
public string? ScheduleExpression { get; set; }
[Column("schedule_type")]
[MaxLength(50)]
public string? ScheduleType { get; set; }
[Column("next_run_time")]
public DateTime? NextRunTime { get; set; }
[Column("last_run_time")]
public DateTime? LastRunTime { get; set; }
[Column("hotkey")]
[MaxLength(50)]
public string? Hotkey { get; set; }
[Column("hotkey_")]
[MaxLength(50)]
public string? Hotkey2 { get; set; }
[Column("category")]
[MaxLength(50)]
public string? Category { get; set; }
}

View File

@@ -1,51 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BetterGenshinImpact.Model.Database
{
[Table("task_list")]
public class TaskList
{
[Key]
[Column("id")]
public int Id { get; set; }
[Column("order_index")]
public int OrderIndex { get; set; }
[Column("task_name")]
[Required]
[MaxLength(255)]
public string TaskName { get; set; } = string.Empty;
[Column("task_params")]
public string? TaskParams { get; set; }
[Column("schedule_expression")]
[MaxLength(255)]
public string? ScheduleExpression { get; set; }
[Column("schedule_type")]
[MaxLength(50)]
public string? ScheduleType { get; set; }
[Column("next_run_time")]
public DateTime? NextRunTime { get; set; }
[Column("last_run_time")]
public DateTime? LastRunTime { get; set; }
[Column("hotkey")]
[MaxLength(50)]
public string? Hotkey { get; set; }
[Column("hotkey_")]
[MaxLength(50)]
public string? Hotkey2 { get; set; }
[Column("category")]
[MaxLength(50)]
public string? Category { get; set; }
}
}

View File

@@ -4,32 +4,37 @@ using BetterGenshinImpact.Model.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace BetterGenshinImpact.Service
namespace BetterGenshinImpact.Service;
public class DatabaseInitializer
{
public class DatabaseInitializer
private readonly ApplicationDbContext _context;
private readonly ILogger<DatabaseInitializer> _logger;
public DatabaseInitializer(ApplicationDbContext context, ILogger<DatabaseInitializer> logger)
{
private readonly ApplicationDbContext _context;
private readonly ILogger<DatabaseInitializer> _logger;
_context = context;
_logger = logger;
}
public DatabaseInitializer(ApplicationDbContext context, ILogger<DatabaseInitializer> logger)
public void Initialize()
{
try
{
_context = context;
_logger = logger;
_logger.LogInformation("正在初始化数据库...");
// 确保数据库已创建
_context.Database.EnsureCreated();
// 应用所有迁移
_context.Database.Migrate();
_logger.LogInformation("数据库初始化完成");
}
public void Initialize()
catch (Exception ex)
{
try
{
_logger.LogInformation("正在初始化数据库...");
_context.Database.Migrate();
_logger.LogInformation("数据库初始化完成");
}
catch (Exception ex)
{
_logger.LogError(ex, "数据库初始化失败");
throw;
}
_logger.LogError(ex, "数据库初始化失败");
throw;
}
}
}
}

View File

@@ -98,6 +98,13 @@
<ui:SymbolIcon Symbol="DeveloperBoard24" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem Content="调度器(新)"
NavigationCacheMode="Enabled"
TargetPageType="{x:Type pages:TaskGroupPage}">
<ui:NavigationViewItem.Icon>
<ui:SymbolIcon Symbol="DeveloperBoard24" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<!-- WebAsset24 | DocumentJs16 | Script16 -->
<ui:NavigationViewItem Content="JS 脚本"
NavigationCacheMode="Enabled"

View File

@@ -0,0 +1,94 @@
<UserControl x:Class="BetterGenshinImpact.View.Pages.TaskGroupPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:pages="clr-namespace:BetterGenshinImpact.View.Pages"
xmlns:viewModel="clr-namespace:BetterGenshinImpact.ViewModel.Pages"
d:DataContext="{d:DesignInstance Type=viewModel:TaskGroupPageViewModel}"
mc:Ignorable="d"
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
d:DesignHeight="450" d:DesignWidth="800" >
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/View/Controls/Style/ListViewEx.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 工具栏 -->
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,0,0,10">
<ui:Button Icon="Add24" Content="添加" Command="{Binding AddTaskGroupCommand}"/>
<ui:Button Icon="Edit24" Content="编辑" Command="{Binding EditTaskGroupCommand}" Margin="5,0,0,0"/>
<ui:Button Icon="Delete24" Content="删除" Command="{Binding DeleteTaskGroupCommand}" Margin="5,0,0,0"/>
<ui:Button Icon="ArrowUp24" Content="上移" Command="{Binding MoveUpCommand}" Margin="5,0,0,0"/>
<ui:Button Icon="ArrowDown24" Content="下移" Command="{Binding MoveDownCommand}" Margin="5,0,0,0"/>
</StackPanel>
<!-- 列表和编辑区域 -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="300"/>
</Grid.ColumnDefinitions>
<!-- 任务组列表 -->
<ui:ListView Grid.Column="0" ItemsSource="{Binding TaskGroups}" SelectedItem="{Binding SelectedTaskGroup}">
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource GridViewColumnHeaderDarkStyle}">
<GridViewColumn Header="序号" DisplayMemberBinding="{Binding OrderIndex}" Width="50"/>
<GridViewColumn Header="名称" DisplayMemberBinding="{Binding TaskName}" Width="150"/>
<GridViewColumn Header="类别" DisplayMemberBinding="{Binding Category}" Width="100"/>
<GridViewColumn Header="下次运行时间" DisplayMemberBinding="{Binding NextRunTime}" Width="150"/>
<GridViewColumn Header="上次运行时间" DisplayMemberBinding="{Binding LastRunTime}" Width="150"/>
</GridView>
</ListView.View>
</ui:ListView>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
<!-- 编辑区域 -->
<Grid Grid.Column="2" Margin="10,0,0,0" Visibility="{Binding IsEditing, Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="任务名称" Margin="0,0,0,5"/>
<ui:TextBox Grid.Row="1" Text="{Binding SelectedTaskGroup.TaskName}" Margin="0,0,0,10"/>
<TextBlock Grid.Row="2" Text="任务参数" Margin="0,0,0,5"/>
<ui:TextBox Grid.Row="3" Text="{Binding SelectedTaskGroup.TaskParams}" Margin="0,0,0,10"/>
<TextBlock Grid.Row="4" Text="调度表达式" Margin="0,0,0,5"/>
<ui:TextBox Grid.Row="5" Text="{Binding SelectedTaskGroup.ScheduleExpression}" Margin="0,0,0,10"/>
<TextBlock Grid.Row="6" Text="调度类型" Margin="0,0,0,5"/>
<ui:TextBox Grid.Row="7" Text="{Binding SelectedTaskGroup.ScheduleType}" Margin="0,0,0,10"/>
<StackPanel Grid.Row="9" Orientation="Horizontal" HorizontalAlignment="Right">
<ui:Button Content="保存" Command="{Binding SaveTaskGroupCommand}" Margin="0,0,5,0"/>
<ui:Button Content="取消" Command="{Binding CancelEditCommand}"/>
</StackPanel>
</Grid>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,12 @@
using BetterGenshinImpact.ViewModel.Pages;
namespace BetterGenshinImpact.View.Pages;
public partial class TaskGroupPage
{
public TaskGroupPage(TaskGroupPageViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}

View File

@@ -0,0 +1,130 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using BetterGenshinImpact.Model.Database;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
namespace BetterGenshinImpact.ViewModel.Pages;
public partial class TaskGroupPageViewModel : ViewModel
{
private readonly ApplicationDbContext _dbContext;
private readonly ILogger<TaskGroupPageViewModel> _logger;
[ObservableProperty] private ObservableCollection<TaskGroup> _taskGroups = new();
[ObservableProperty] private TaskGroup? _selectedTaskGroup;
[ObservableProperty] private bool _isEditing;
public TaskGroupPageViewModel(ApplicationDbContext dbContext, ILogger<TaskGroupPageViewModel> logger)
{
_dbContext = dbContext;
_logger = logger;
LoadTaskGroups();
}
private void LoadTaskGroups()
{
var groups = _dbContext.TaskGroups
.OrderBy(t => t.OrderIndex)
.ToList();
TaskGroups = new ObservableCollection<TaskGroup>(groups);
}
[RelayCommand]
private void AddTaskGroup()
{
var newGroup = new TaskGroup
{
OrderIndex = TaskGroups.Count + 1,
TaskName = "新任务组",
Category = "默认"
};
TaskGroups.Add(newGroup);
SelectedTaskGroup = newGroup;
IsEditing = true;
}
[RelayCommand]
private void EditTaskGroup()
{
if (SelectedTaskGroup != null)
{
IsEditing = true;
}
}
[RelayCommand]
private async Task SaveTaskGroup()
{
if (SelectedTaskGroup == null) return;
if (SelectedTaskGroup.Id == 0)
{
_dbContext.TaskGroups.Add(SelectedTaskGroup);
}
else
{
_dbContext.TaskGroups.Update(SelectedTaskGroup);
}
await _dbContext.SaveChangesAsync();
IsEditing = false;
LoadTaskGroups();
}
[RelayCommand]
private async Task DeleteTaskGroup()
{
if (SelectedTaskGroup == null) return;
_dbContext.TaskGroups.Remove(SelectedTaskGroup);
await _dbContext.SaveChangesAsync();
TaskGroups.Remove(SelectedTaskGroup);
SelectedTaskGroup = null;
}
[RelayCommand]
private void CancelEdit()
{
IsEditing = false;
LoadTaskGroups();
}
[RelayCommand]
private void MoveUp()
{
if (SelectedTaskGroup == null) return;
var currentIndex = TaskGroups.IndexOf(SelectedTaskGroup);
if (currentIndex > 0)
{
var previousGroup = TaskGroups[currentIndex - 1];
(SelectedTaskGroup.OrderIndex, previousGroup.OrderIndex) =
(previousGroup.OrderIndex, SelectedTaskGroup.OrderIndex);
TaskGroups.Move(currentIndex, currentIndex - 1);
_dbContext.SaveChanges();
}
}
[RelayCommand]
private void MoveDown()
{
if (SelectedTaskGroup == null) return;
var currentIndex = TaskGroups.IndexOf(SelectedTaskGroup);
if (currentIndex < TaskGroups.Count - 1)
{
var nextGroup = TaskGroups[currentIndex + 1];
(SelectedTaskGroup.OrderIndex, nextGroup.OrderIndex) = (nextGroup.OrderIndex, SelectedTaskGroup.OrderIndex);
TaskGroups.Move(currentIndex, currentIndex + 1);
_dbContext.SaveChanges();
}
}
}