using BetterGenshinImpact.Core.Config; using BetterGenshinImpact.Core.Recorder; using BetterGenshinImpact.Core.Script; using BetterGenshinImpact.GameTask; using BetterGenshinImpact.GameTask.Model.Enum; using BetterGenshinImpact.Model; using BetterGenshinImpact.Service.Interface; using BetterGenshinImpact.View.Windows; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows; using BetterGenshinImpact.Helpers; using Wpf.Ui; using Wpf.Ui.Controls; using Wpf.Ui.Violeta.Controls; using MessageBoxButton = Wpf.Ui.Controls.MessageBoxButton; namespace BetterGenshinImpact.ViewModel.Pages; public partial class KeyMouseRecordPageViewModel : ObservableObject, INavigationAware, IViewModel { private readonly ILogger _logger = App.GetLogger(); private readonly string scriptPath = Global.Absolute(@"User\KeyMouseScript"); [ObservableProperty] private ObservableCollection _scriptItems = []; [ObservableProperty] private bool _isRecording = false; private readonly ISnackbarService _snackbarService; public AllConfig Config { get; set; } string fileName = $"{DateTime.Now:yyyyMMddHH_mmssffff}"; public KeyMouseRecordPageViewModel(ISnackbarService snackbarService, IConfigService configService) { _snackbarService = snackbarService; Config = configService.Get(); } private void InitScriptListViewData() { _scriptItems.Clear(); var fileInfos = LoadScriptFiles(scriptPath) .OrderByDescending(f => f.CreationTime) .ToList(); foreach (var f in fileInfos) { _scriptItems.Add(new KeyMouseScriptItem { Name = f.Name, Path = f.FullName, CreateTime = f.CreationTime, CreateTimeStr = f.CreationTime.ToString("yyyy-MM-dd HH:mm:ss") }); } } private List LoadScriptFiles(string folder) { if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } var files = Directory.GetFiles(folder, "*.json", SearchOption.AllDirectories); return files.Select(file => new FileInfo(file)).ToList(); } public void OnNavigatedTo() { InitScriptListViewData(); } public void OnNavigatedFrom() { } [RelayCommand] public async Task OnStartRecord() { if (!TaskContext.Instance().IsInitialized) { Toast.Warning("请先在启动页,启动截图器再使用本功能"); return; } if (!File.Exists(Global.Absolute(@"User\not_check"))) { try { if (EnvironmentUtil.IsProcessRunning("QQ") || EnvironmentUtil.IsProcessRunning("WeChat") || EnvironmentUtil.IsProcessRunning("dingtalk") || EnvironmentUtil.IsProcessRunning("Feishu")) { throw new Exception("请关闭 QQ、微信、飞书等聊天软件再进行录制"); } if (EnvironmentUtil.GetMasterVolume() <= 0) { throw new Exception("请保持系统音量大于0再进行录制"); } } catch (Exception e) { await MessageBox.ShowAsync(e.Message, "校验错误", System.Windows.MessageBoxButton.OK, MessageBoxImage.Error); return; } } if (!IsRecording) { IsRecording = true; fileName = $"{DateTime.Now:yyyy_MM_dd_HH_mm_ss}"; await GlobalKeyMouseRecord.Instance.StartRecord(fileName); } } [RelayCommand] public void OnStopRecord() { if (IsRecording) { try { GlobalKeyMouseRecord.Instance.StopRecord(); // Genshin Copilot Macro // File.WriteAllText(Path.Combine(scriptPath, $"{fileName}/{fileName}.json"), macro); // 刷新ListView InitScriptListViewData(); IsRecording = false; } catch (Exception e) { _logger.LogDebug(e, "停止录制时发生异常"); _logger.LogWarning(e.Message); } } } [RelayCommand] public async Task OnStartPlay(string path) { var file = new FileInfo(path); var name = file.Name; _logger.LogInformation("重放开始:{Name}", name); try { await new TaskRunner(DispatcherTimerOperationEnum.UseSelfCaptureImage) .RunAsync(async () => await KeyMouseMacroPlayerJsonLine.PlayMacro(path, CancellationContext.Instance.Cts.Token)); } catch (Exception e) { _logger.LogError(e, "重放脚本时发生异常"); } finally { _logger.LogInformation("重放结束:{Name}", name); } } [RelayCommand] public void OnOpenScriptFolder() { Process.Start("explorer.exe", scriptPath); } [RelayCommand] public void OnEditScript(KeyMouseScriptItem? item) { if (item == null) { return; } try { var str = PromptDialog.Prompt("请输入要修改为的名称(实际就是文件名)", "修改名称"); if (!string.IsNullOrEmpty(str)) { // 检查原始文件是否存在 var originalFilePath = Path.Combine(scriptPath, item.Name); if (File.Exists(originalFilePath)) { // 重命名文件 File.Move(originalFilePath, Path.Combine(scriptPath, str + ".json")); _snackbarService.Show( "修改名称成功", $"脚本名称 {item.Name} 修改为 {str}", ControlAppearance.Success, null, TimeSpan.FromSeconds(2) ); } } } catch (Exception) { _snackbarService.Show( "修改失败", $"{item.Name} 修改失败", ControlAppearance.Danger, null, TimeSpan.FromSeconds(3) ); } finally { InitScriptListViewData(); } } [RelayCommand] public void OnDeleteScript(KeyMouseScriptItem? item) { if (item == null) { return; } try { var path = new FileInfo(item.Path).Directory!.FullName; // 校验文件夹是否在 scriptPath 下 if (!path.StartsWith(scriptPath)) { _snackbarService.Show( "删除失败", $"{path} 删除失败,不在脚本目录下", ControlAppearance.Danger, null, TimeSpan.FromSeconds(3) ); return; } // 删除目录 Directory.Delete(path, true); _snackbarService.Show( "删除成功", $"{item.Name} 已经被删除", ControlAppearance.Success, null, TimeSpan.FromSeconds(2) ); } catch (Exception) { _snackbarService.Show( "删除失败", $"{item.Name} 删除失败", ControlAppearance.Danger, null, TimeSpan.FromSeconds(3) ); } finally { InitScriptListViewData(); } } [RelayCommand] public void OnGoToKmScriptUrl() { Process.Start(new ProcessStartInfo("https://bgi.huiyadan.com/feats/autos/kmscript.html") { UseShellExecute = true }); } [RelayCommand] public void OnOpenLocalScriptRepo() { Config.ScriptConfig.ScriptRepoHintDotVisible = false; ScriptRepoUpdater.Instance.OpenLocalRepoInWebView(); } }