using System.Collections.ObjectModel; using System.Linq; using System.Windows; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.Extensions.DependencyInjection; using PersonalToolBox.Helpers; using PersonalToolBox.Models; using PersonalToolBox.Services; using PersonalToolBox.Views; namespace PersonalToolBox.ViewModels; /// /// 主窗口 ViewModel,管理 UI 状态、数据绑定和用户交互逻辑 /// public partial class MainViewModel : ObservableObject { private readonly ILogService _logService; private readonly IDataService _dataService; private readonly IProcessExecutionService _processService; private readonly IServiceProvider _serviceProvider; private readonly HotKeyManager _hotKeyManager; /// /// 全部分类的虚拟对象 /// private static readonly Category AllCategory = new() { Id = "", Name = "全部" }; public MainViewModel( ILogService logService, IDataService dataService, IProcessExecutionService processService, IServiceProvider serviceProvider, HotKeyManager hotKeyManager) { _logService = logService; _dataService = dataService; _processService = processService; _serviceProvider = serviceProvider; _hotKeyManager = hotKeyManager; LoadData(); } // ───────────────────────────── 可观察属性 ───────────────────────────── [ObservableProperty] private string _searchText = string.Empty; [ObservableProperty] private Category? _selectedCategory; public ObservableCollection Logs => _logService.Logs; public ObservableCollection Categories { get; } = new(); public ObservableCollection Tools { get; } = new(); [ObservableProperty] private ObservableCollection _filteredTools = new(); [ObservableProperty] private string _currentTheme = "Dark"; [ObservableProperty] private bool _isAutoStart; // ───────────────────────────── 命令 ───────────────────────────── [RelayCommand] private void ClearLogs() => _logService.Clear(); [RelayCommand] private void ToggleTheme() { CurrentTheme = CurrentTheme == "Dark" ? "Light" : "Dark"; ThemeHelper.ApplyTheme(CurrentTheme); _dataService.Config.Theme = CurrentTheme; _dataService.Save(); _logService.Info($"已切换到{(CurrentTheme == "Dark" ? "暗黑" : "明亮")}主题"); } /// /// 切换开机自启动 /// [RelayCommand] private void ToggleAutoStart() { IsAutoStart = !IsAutoStart; AutoStartHelper.SetAutoStart(IsAutoStart); _dataService.Config.AutoStart = IsAutoStart; _dataService.Save(); _logService.Info(IsAutoStart ? "已启用开机自启动" : "已关闭开机自启动"); } /// /// 供 MainWindow 外部调用,用于输出提示信息 /// public void LogServiceMessage(string message) { _logService.Info(message); } /// /// 打开添加工具弹窗 /// [RelayCommand] private void AddTool() { var vm = _serviceProvider.GetRequiredService(); var window = new ToolEditWindow(vm); window.ShowDialog(); if (vm.Saved) { RefreshData(); } } /// /// 打开编辑工具弹窗 /// [RelayCommand] private void EditTool(ToolItem tool) { if (tool == null) return; // 创建编辑 ViewModel(需要新建实例,DI 容器无法区分参数) var dataService = _serviceProvider.GetRequiredService(); var logService = _serviceProvider.GetRequiredService(); var editVm = new ToolEditViewModel(dataService, logService, tool); var window = new ToolEditWindow(editVm); window.ShowDialog(); if (editVm.Saved) { RefreshData(); } } /// /// 执行工具(双击卡片或右键菜单) /// [RelayCommand] private async Task ExecuteTool(ToolItem? tool) { if (tool == null) return; await _processService.ExecuteAsync(tool); } // ───────────────────────────── 分类管理命令 ───────────────────────────── /// /// 添加分类 /// [RelayCommand] private void AddCategory() { var vm = _serviceProvider.GetRequiredService(); var window = new CategoryEditWindow(vm); window.ShowDialog(); if (vm.Saved) RefreshData(); } /// /// 编辑分类(右键菜单触发) /// [RelayCommand] private void EditCategory(Category? category) { if (category == null || string.IsNullOrEmpty(category.Id)) return; var dataService = _serviceProvider.GetRequiredService(); var logService = _serviceProvider.GetRequiredService(); var editVm = new CategoryEditViewModel(dataService, logService, category); var window = new CategoryEditWindow(editVm); window.ShowDialog(); if (editVm.Saved) RefreshData(); } /// /// 删除分类,其下所有工具移入"全部" /// [RelayCommand] private void DeleteCategory(Category? category) { if (category == null || string.IsNullOrEmpty(category.Id)) return; if (MessageBox.Show( $"确定删除分类 \"{category.Name}\" 吗?\n该分类下的所有工具将移入「全部」。", "确认删除", MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes) return; // 将属于该分类的工具设为"全部" foreach (var tool in _dataService.Config.Tools.Where(t => t.CategoryId == category.Id)) tool.CategoryId = string.Empty; // 从配置中移除分类 _dataService.Config.Categories.Remove(category); _dataService.Save(); _logService.Info($"已删除分类: {category.Name}"); RefreshData(); } // ───────────────────────────── 组合管理命令 ───────────────────────────── /// /// 添加组合 /// [RelayCommand] private void AddGroup() { var vm = _serviceProvider.GetRequiredService(); var window = new GroupEditWindow(vm); window.ShowDialog(); if (vm.Saved) RefreshData(); } /// /// 编辑组合 /// [RelayCommand] private void EditGroup(ToolItem tool) { if (tool == null || !tool.IsGroup) return; var dataService = _serviceProvider.GetRequiredService(); var logService = _serviceProvider.GetRequiredService(); var editVm = new GroupEditViewModel(dataService, logService, tool); var window = new GroupEditWindow(editVm); window.ShowDialog(); if (editVm.Saved) RefreshData(); } /// /// 删除工具或组合 /// [RelayCommand] private void DeleteTool(ToolItem? tool) { if (tool == null) return; var type = tool.IsGroup ? "组合" : "工具"; if (MessageBox.Show($"确定删除{type} \"{tool.Name}\" 吗?", "确认删除", MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes) return; _dataService.Config.Tools.Remove(tool); _dataService.Save(); _logService.Info($"已删除{type}: {tool.Name}"); RefreshData(); } // ───────────────────────────── 自动运行 ───────────────────────────── /// /// 启动时自动运行标记为 AutoRunOnStart 的工具和组合 /// public async Task ExecuteAutoRunToolsAsync() { var autoTools = _dataService.Config.Tools.Where(t => t.AutoRunOnStart).ToList(); if (autoTools.Count == 0) return; _logService.Info($"正在启动 {autoTools.Count} 个自启动工具..."); foreach (var tool in autoTools) { await _processService.ExecuteAsync(tool); await Task.Delay(500); } } // ───────────────────────────── 数据刷新 ───────────────────────────── /// /// 从配置重新加载数据并刷新 UI /// public void RefreshData() { var previousCategoryId = SelectedCategory?.Id; Categories.Clear(); Categories.Add(AllCategory); foreach (var cat in _dataService.Config.Categories) Categories.Add(cat); Tools.Clear(); foreach (var tool in _dataService.Config.Tools) Tools.Add(tool); // 恢复之前选中的分类(若仍存在),否则选中"全部" SelectedCategory = Categories.FirstOrDefault(c => c.Id == previousCategoryId) ?? AllCategory; ApplyFilter(); // 工具列表变更后重新注册快捷键 RegisterAllHotKeys(); } // ───────────────────────────── 快捷键 ───────────────────────────── /// /// 注册所有工具的全局快捷键(由 MainWindow.OnSourceInitialized 及数据变更后调用) /// public void RegisterAllHotKeys() { _hotKeyManager.RegisterAll(Tools); } private void LoadData() { RefreshData(); SelectedCategory = AllCategory; CurrentTheme = _dataService.Config.Theme; IsAutoStart = _dataService.Config.AutoStart; ThemeHelper.ApplyTheme(CurrentTheme); } // ───────────────────────────── 过滤逻辑 ───────────────────────────── partial void OnSearchTextChanged(string value) => ApplyFilter(); partial void OnSelectedCategoryChanged(Category? value) => ApplyFilter(); private void ApplyFilter() { var filtered = Tools.AsEnumerable(); if (SelectedCategory != null && !string.IsNullOrEmpty(SelectedCategory.Id)) filtered = filtered.Where(t => t.CategoryId == SelectedCategory.Id); if (!string.IsNullOrWhiteSpace(SearchText)) filtered = filtered.Where(t => t.Name.Contains(SearchText, System.StringComparison.OrdinalIgnoreCase)); FilteredTools = new ObservableCollection(filtered); } }