change - 添加控制台日志输出
parent
ab609394e4
commit
15edaebf44
@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels;
|
||||
|
||||
public partial class SystemMonitorViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<LogEntry> _logs = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private int _logCount;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _filterText = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _autoScroll = true;
|
||||
|
||||
private const int MaxLogs = 5000;
|
||||
|
||||
public SystemMonitorViewModel()
|
||||
{
|
||||
// 安装控制台输出拦截器
|
||||
var original = Console.Out;
|
||||
var writer = new LogTextWriter(original, entry =>
|
||||
{
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Logs.Add(entry);
|
||||
if (Logs.Count > MaxLogs) Logs.RemoveAt(0);
|
||||
LogCount = Logs.Count;
|
||||
});
|
||||
});
|
||||
Console.SetOut(writer);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Clear()
|
||||
{
|
||||
Logs.Clear();
|
||||
LogCount = 0;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ToggleAutoScroll()
|
||||
{
|
||||
AutoScroll = !AutoScroll;
|
||||
}
|
||||
}
|
||||
|
||||
public class LogEntry
|
||||
{
|
||||
public DateTime Time { get; set; }
|
||||
public string TimeText => Time.ToString("HH:mm:ss.fff");
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public string Level { get; set; } = "INFO";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拦截 Console.WriteLine 输出,同时写入原始输出和 ObservableCollection
|
||||
/// </summary>
|
||||
internal class LogTextWriter : TextWriter
|
||||
{
|
||||
private readonly TextWriter _original;
|
||||
private readonly Action<LogEntry> _onWrite;
|
||||
private readonly StringBuilder _buffer = new();
|
||||
|
||||
public LogTextWriter(TextWriter original, Action<LogEntry> onWrite)
|
||||
{
|
||||
_original = original;
|
||||
_onWrite = onWrite;
|
||||
}
|
||||
|
||||
public override Encoding Encoding => Encoding.UTF8;
|
||||
|
||||
public override void Write(char value)
|
||||
{
|
||||
_original.Write(value);
|
||||
if (value == '\n')
|
||||
{
|
||||
FlushBuffer();
|
||||
}
|
||||
else if (value != '\r')
|
||||
{
|
||||
_buffer.Append(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(string? message)
|
||||
{
|
||||
_original.WriteLine(message);
|
||||
if (message != null)
|
||||
{
|
||||
_onWrite(new LogEntry { Time = DateTime.Now, Message = message, Level = "INFO" });
|
||||
}
|
||||
}
|
||||
|
||||
private void FlushBuffer()
|
||||
{
|
||||
var msg = _buffer.ToString();
|
||||
_buffer.Clear();
|
||||
if (msg.Length > 0)
|
||||
{
|
||||
_onWrite(new LogEntry { Time = DateTime.Now, Message = msg, Level = "INFO" });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.SystemMonitorView">
|
||||
<Grid RowDefinitions="Auto,*" Margin="20,14,20,14" VerticalAlignment="Stretch">
|
||||
<!-- Toolbar -->
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto" Margin="0,0,0,8">
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="6">
|
||||
<Ellipse Width="8" Height="8" Fill="#00E676" VerticalAlignment="Center" />
|
||||
<TextBlock Text="系统监控" FontSize="15" FontWeight="SemiBold" Foreground="#DDE4F0" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="6" Margin="0,0,10,0">
|
||||
<TextBlock Text="{Binding LogCount, StringFormat='共 {0} 条'}" FontSize="12" Foreground="#6B8CB5" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<Button Grid.Column="3" Content="清空" Command="{Binding ClearCommand}"
|
||||
Background="#0F1F38" Foreground="#8B9BB5" Padding="12,5" FontSize="12" Margin="0,0,6,0" />
|
||||
<Button Grid.Column="4" Content="{Binding AutoScroll, StringFormat={}{0} auto?}" Command="{Binding ToggleAutoScrollCommand}"
|
||||
Background="#0F1F38" Foreground="#8B9BB5" Padding="12,5" FontSize="12" />
|
||||
</Grid>
|
||||
|
||||
<!-- Log List -->
|
||||
<Border Grid.Row="1" Background="#0C1622" CornerRadius="6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<ListBox x:Name="LogList" ItemsSource="{Binding Logs}"
|
||||
Background="Transparent" Foreground="#BCC8D6" BorderThickness="0"
|
||||
>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="10,3" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<TextBlock Text="{Binding TimeText}"
|
||||
FontSize="11" Foreground="#4B5E7A" FontFamily="Menlo,Consolas,monospace"
|
||||
VerticalAlignment="Center" Width="100" />
|
||||
<TextBlock Text="{Binding Message}"
|
||||
FontSize="11" Foreground="#8B9BB5" FontFamily="Menlo,Consolas,monospace"
|
||||
TextWrapping="Wrap" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,17 @@
|
||||
using Avalonia.Controls;
|
||||
using Sln.Wcs.UI.ViewModels;
|
||||
|
||||
namespace Sln.Wcs.UI.Views;
|
||||
|
||||
public partial class SystemMonitorView : UserControl
|
||||
{
|
||||
public SystemMonitorView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public SystemMonitorView(SystemMonitorViewModel vm) : this()
|
||||
{
|
||||
DataContext = vm;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue