using System.Windows; using System.Windows.Controls; namespace SHH.CameraDashboard.Controls { public partial class DiagnosticControl : UserControl { public event EventHandler RequestCollapse; private ApiLogEntry _selectedItem; private bool _isInitialized = false; public DiagnosticControl() { InitializeComponent(); _isInitialized = true; } // 外部(MainWindow或BottomDock)调用此方法推送日志 public void PushLog(ApiLogEntry entry) { this.Dispatcher.Invoke(() => { // 确保 XAML 中的 ListView 名称是 LogList LogList.Items.Insert(0, entry); // 限制日志数量,防止内存溢出(可选) if (LogList.Items.Count > 100) LogList.Items.RemoveAt(100); }); } private void Close_Click(object sender, RoutedEventArgs e) { RequestCollapse?.Invoke(this, EventArgs.Empty); } private void LogList_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!_isInitialized) return; _selectedItem = LogList.SelectedItem as ApiLogEntry; UpdateDetailView(); } private void Tab_Checked(object sender, RoutedEventArgs e) { if (!_isInitialized) return; UpdateDetailView(); } private void UpdateDetailView() { // 防御性编程:检查所有可能为 null 的 UI 元素 if (TxtEmpty == null || TxtContent == null || BtnReq == null) return; if (_selectedItem == null) { TxtEmpty.Visibility = Visibility.Visible; TxtContent.Visibility = Visibility.Collapsed; // 隐藏编辑框更美观 TxtContent.Text = string.Empty; return; } TxtEmpty.Visibility = Visibility.Collapsed; TxtContent.Visibility = Visibility.Visible; // 根据切换按钮显示对应内容 TxtContent.Text = (BtnReq.IsChecked == true) ? _selectedItem.RequestBody : _selectedItem.ResponseBody; } private void Clear_Click(object sender, RoutedEventArgs e) { // 具体的清空逻辑 LogList.Items.Clear(); _selectedItem = null; UpdateDetailView(); } private void Copy_Click(object sender, RoutedEventArgs e) { // 如果没选中或内容本身为空,不执行复制 if (_selectedItem == null || TxtContent == null || string.IsNullOrEmpty(TxtContent.Text)) return; // 使用之前定义的带重试机制的 Helper ClipboardHelper.SetText(TxtContent.Text); } // 右键菜单复制逻辑 private void CopySummary_Click(object sender, RoutedEventArgs e) { if (LogList.SelectedItem is ApiLogEntry item) ClipboardHelper.SetText($"[{item.Time}] {item.Url} - {item.StatusCode}"); } private void CopyRequest_Click(object sender, RoutedEventArgs e) { if (LogList.SelectedItem is ApiLogEntry item) ClipboardHelper.SetText(item.RequestBody ?? ""); } private void CopyResponse_Click(object sender, RoutedEventArgs e) { if (LogList.SelectedItem is ApiLogEntry item) ClipboardHelper.SetText(item.ResponseBody ?? ""); } } }