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