using BetterGenshinImpact.Core.Config; using BetterGenshinImpact.Core.Script.Group; using BetterGenshinImpact.Core.Script.Project; 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.Collections.Specialized; using System.Diagnostics; using System.IO; using System.Linq; using System.Windows.Controls; using Wpf.Ui; using Wpf.Ui.Controls; namespace BetterGenshinImpact.ViewModel.Pages; public partial class ScriptControlViewModel : ObservableObject, INavigationAware, IViewModel { private readonly ISnackbarService _snackbarService; private readonly ILogger _logger = App.GetLogger(); /// /// 脚本组配置 /// [ObservableProperty] private ObservableCollection _scriptGroups = []; /// /// 当前选中的脚本组 /// [ObservableProperty] private ScriptGroup? _selectedScriptGroup; public readonly string ScriptGroupPath = Global.Absolute(@"User\ScriptGroup"); public void OnNavigatedFrom() { } public void OnNavigatedTo() { ReadScriptGroup(); } public ScriptControlViewModel(ISnackbarService snackbarService) { _snackbarService = snackbarService; ScriptGroups.CollectionChanged += ScriptGroupsCollectionChanged; } [RelayCommand] private void OnAddScriptGroup() { var str = PromptDialog.Prompt("请输入脚本组名称", "新增脚本组"); if (!string.IsNullOrEmpty(str)) { // 检查是否已存在 if (ScriptGroups.Any(x => x.Name == str)) { _snackbarService.Show( "脚本组已存在", $"脚本组 {str} 已经存在,请勿重复添加", ControlAppearance.Caution, null, TimeSpan.FromSeconds(2) ); } else { ScriptGroups.Add(new ScriptGroup { Name = str }); } } } [RelayCommand] public void OnDeleteScriptGroup(ScriptGroup? item) { if (item == null) { return; } try { ScriptGroups.Remove(item); File.Delete(Path.Combine(ScriptGroupPath, $"{item.Name}.json")); _snackbarService.Show( "脚本组删除成功", $"脚本组 {item.Name} 已经被删除", ControlAppearance.Success, null, TimeSpan.FromSeconds(2) ); } catch (Exception e) { _logger.LogDebug(e, "删除脚本组配置时失败"); _snackbarService.Show( "删除脚本组配置失败", $"脚本组 {item.Name} 删除失败!", ControlAppearance.Danger, null, TimeSpan.FromSeconds(3) ); } } [RelayCommand] private void OnAddScript() { var list = LoadAllScriptProjects(); var combobox = new ComboBox(); foreach (var scriptProject in list) { combobox.Items.Add(scriptProject.FolderName + " - " + scriptProject.Manifest.Name); } var str = PromptDialog.Prompt("请选择需要添加的脚本", "请选择需要添加的脚本", combobox); if (!string.IsNullOrEmpty(str)) { var folderName = str.Split(" - ")[0]; SelectedScriptGroup?.Projects.Add(new ScriptGroupProject(new ScriptProject(folderName))); } } private List LoadAllScriptProjects() { var path = Global.ScriptPath(); // 获取所有脚本项目 var projects = Directory.GetDirectories(path) .Select(x => new ScriptProject(Path.GetFileName(x))) .ToList(); return projects; } [RelayCommand] public void OnDeleteScript(ScriptGroupProject? item) { if (item == null) { return; } SelectedScriptGroup?.Projects.Remove(item); _snackbarService.Show( "脚本配置移除成功", $"{item.Name} 的关联配置已经移除", ControlAppearance.Success, null, TimeSpan.FromSeconds(2) ); } private void ScriptGroupsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (ScriptGroup newItem in e.NewItems) { newItem.Projects.CollectionChanged += ScriptProjectsCollectionChanged; } } if (e.OldItems != null) { foreach (ScriptGroup oldItem in e.OldItems) { oldItem.Projects.CollectionChanged -= ScriptProjectsCollectionChanged; } } // 补充排序字段 var i = 1; foreach (var group in ScriptGroups) { group.Index = i++; } // 保存脚本组配置 foreach (var group in ScriptGroups) { WriteScriptGroup(group); } } private void ScriptProjectsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { // 补充排序字段 if (SelectedScriptGroup is { Projects.Count: > 0 }) { var i = 1; foreach (var project in SelectedScriptGroup.Projects) { project.Index = i++; } } // 保存脚本组配置 if (SelectedScriptGroup != null) { WriteScriptGroup(SelectedScriptGroup); } } private void WriteScriptGroup(ScriptGroup scriptGroup) { try { if (!Directory.Exists(ScriptGroupPath)) { Directory.CreateDirectory(ScriptGroupPath); } var file = Path.Combine(ScriptGroupPath, $"{scriptGroup.Name}.json"); File.WriteAllText(file, scriptGroup.ToJson()); } catch (Exception e) { _logger.LogDebug(e, "保存脚本组配置时失败"); _snackbarService.Show( "保存脚本组配置失败", $"{scriptGroup.Name} 保存失败!", ControlAppearance.Danger, null, TimeSpan.FromSeconds(3) ); } } private void ReadScriptGroup() { try { if (!Directory.Exists(ScriptGroupPath)) { Directory.CreateDirectory(ScriptGroupPath); } ScriptGroups.Clear(); var files = Directory.GetFiles(ScriptGroupPath, "*.json"); List groups = new(); foreach (var file in files) { try { var json = File.ReadAllText(file); var group = ScriptGroup.FromJson(json); groups.Add(group); } catch (Exception e) { _logger.LogDebug(e, "读取单个脚本组配置时失败"); _snackbarService.Show( "读取脚本组配置失败", "读取脚本组配置失败:" + e.Message, ControlAppearance.Danger, null, TimeSpan.FromSeconds(3) ); } } // 按index排序 groups.Sort((a, b) => a.Index.CompareTo(b.Index)); foreach (var group in groups) { ScriptGroups.Add(group); } } catch (Exception e) { _logger.LogDebug(e, "读取脚本组配置时失败"); _snackbarService.Show( "读取脚本组配置失败", "读取脚本组配置失败!", ControlAppearance.Danger, null, TimeSpan.FromSeconds(3) ); } } [RelayCommand] public void OnGoToScriptGroupUrl() { Process.Start(new ProcessStartInfo("https://bgi.huiyadan.com/") { UseShellExecute = true }); } [RelayCommand] public void OnGoToScriptProjectUrl() { Process.Start(new ProcessStartInfo("https://bgi.huiyadan.com/") { UseShellExecute = true }); } [RelayCommand] public void OnImportScriptGroup(string scriptGroupExample) { ScriptGroup group = new(); if ("AutoCrystalflyExampleGroup" == scriptGroupExample) { group.Name = "晶蝶示例组"; group.Projects.Add(new ScriptGroupProject(new ScriptProject("AutoCrystalfly"))); } if (ScriptGroups.Any(x => x.Name == group.Name)) { _snackbarService.Show( "脚本组已存在", $"脚本组 {group.Name} 已经存在,请勿重复添加", ControlAppearance.Caution, null, TimeSpan.FromSeconds(2) ); return; } ScriptGroups.Add(group); } }