You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
2.7 KiB
C#

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" });
}
}
}