using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Input; using System.Windows.Threading; namespace SHH.CameraDashboard; public class ServiceNodesViewModel : INotifyPropertyChanged, IOverlayClosable, IDisposable { // 接口要求的关闭事件 public event Action? RequestClose; // 日志数据集合 public ObservableCollection Logs { get; } = new ObservableCollection(); private LogWebApiModel _selectedLog; public LogWebApiModel SelectedLog { get => _selectedLog; set { _selectedLog = value; OnPropertyChanged(); UpdateDisplayContent(); // 选中项改变时更新右侧文本 } } private string _displayContent; public string DisplayContent { get => _displayContent; set { _displayContent = value; OnPropertyChanged(); } } private int _currentTabIndex = 0; // 0: Request, 1: Response // ========================================================= // [新增] 1. 过滤开关属性 (绑定到界面 CheckBox) // ========================================================= private bool _isFilterAutoLogs; public bool IsFilterAutoLogs { get => _isFilterAutoLogs; set { _isFilterAutoLogs = value; OnPropertyChanged(); // 可选:切换时是否要清空现有日志?根据需求决定 // if (value) Logs.Clear(); } } public ICommand ClearCommand { get; } public ICommand CloseCommand { get; } public ICommand SwitchTabCommand { get; } public ServiceNodesViewModel() { // 【关键步骤】订阅全局 API 服务的日志事件 WebApiService.Instance.OnRequestCompleted += OnNewLogReceived; // 初始化指令 ClearCommand = new RelayCommand(_ => Logs.Clear()); CloseCommand = new RelayCommand(_ => RequestClose?.Invoke()); SwitchTabCommand = new RelayCommand(index => { _currentTabIndex = int.Parse(index); UpdateDisplayContent(); }); } /// /// 当 WebApiService 产生新日志时的回调 /// private void OnNewLogReceived(LogWebApiModel log) { // 检查程序是否正在退出 if (Application.Current == null) return; if (IsFilterAutoLogs && CheckIsAutoLog(log)) { return; // 如果是自动日志且开启了过滤,直接丢弃,不进入 UI 线程 } // 【线程安全】必须将操作封送回 UI 线程 Application.Current.Dispatcher.InvokeAsync(() => { // 1. 将最新日志插入顶部 Logs.Insert(0, log); // 2. 限制日志数量 (例如只保留最近 500 条),防止内存溢出 if (Logs.Count > 500) { Logs.RemoveAt(Logs.Count - 1); } // 3. (可选) 如果你想让列表自动滚动,可以在 View 的 CodeBehind 里做,或者在这里处理选中项逻辑 }, DispatcherPriority.Background); } private bool CheckIsAutoLog(LogWebApiModel log) { if (log.IsAutoPost) return true; return false; } private void UpdateDisplayContent() { if (SelectedLog == null) { DisplayContent = string.Empty; return; } // 根据当前选中的 Tab 显示请求或响应内容 DisplayContent = _currentTabIndex == 0 ? SelectedLog.RequestData : SelectedLog.ResponseData; } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string name = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); public void Dispose() { WebApiService.Instance.OnRequestCompleted -= OnNewLogReceived; } }