XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEToolBox

【WPF】XFE工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using XFEToolBox.Client.Models.Server;
using XFEToolBox.Client.Utilities.Server;

namespace XFEToolBox.Client.Views.Pages.Admin;

public partial class ServerOverviewPage : Page
{
    public static ServerOverviewPage Current { get; } = new();
    private readonly DispatcherTimer refreshTimer;
    private bool isRefreshing;
    private bool hasSnapshot;

    public ServerOverviewPage()
    {
        InitializeComponent();
        refreshTimer = new DispatcherTimer(DispatcherPriority.Background, Dispatcher)
        {
            Interval = TimeSpan.FromSeconds(2)
        };
        refreshTimer.Tick += RefreshTimer_Tick;
    }

    private async void Page_Loaded(object sender, RoutedEventArgs e)
    {
        refreshTimer.Start();
        await RefreshAsync();
    }

    private void Page_Unloaded(object sender, RoutedEventArgs e) => refreshTimer.Stop();

    private async void RefreshTimer_Tick(object? sender, EventArgs e) => await RefreshAsync();

    private async Task RefreshAsync()
    {
        if (isRefreshing || !ClientSession.IsAdministrator) return;
        isRefreshing = true;
        ErrorText.Text = string.Empty;
        try
        {
            var response = await ClientSession.Requester.Request<AdminOverview>("adminOverview");
            if (response.StatusCode != HttpStatusCode.OK || response.Result is null)
            {
                ErrorText.Text = response.Message;
                if (!hasSnapshot) StatusValue.Text = "不可用";
                LiveIndicator.Fill = new SolidColorBrush(Color.FromRgb(239, 112, 112));
                return;
            }

            var overview = response.Result;
            StatusValue.Text = overview.Status == "running" ? "运行中" : overview.Status;
            UptimeValue.Text = $"已持续运行 {FormatDuration(overview.UptimeSeconds)}";
            UsersValue.Text = $"{overview.UserCount} / {overview.ActiveSessionCount}";
            UsersDetailValue.Text = $"{overview.UserCount} 个注册用户 · {overview.ActiveSessionCount} 个有效会话";
            PackagesValue.Text = $"{overview.PublishedPackageCount} 工具 · {overview.PublishedSoftwareCount} 软件";
            PackagesDetailValue.Text = $"共 {overview.PackageCount} 个工具版本 · {overview.SoftwareCount} 个软件";
            StorageValue.Text = FormatBytes(overview.StorageBytes);
            StorageDetailValue.Text = $"软件文件 {FormatBytes(overview.SoftwareStorageBytes)} · 其余为工具包";
            CpuValue.Text = $"{overview.CpuUsagePercent:F1}%";
            CpuUsageBar.Value = overview.CpuUsagePercent;
            CpuDetailValue.Text = $"{overview.ProcessorCount} 个逻辑核心 · 操作系统整体实时采样";
            MemoryValue.Text = $"{overview.MemoryUsagePercent:F1}%";
            MemoryUsageBar.Value = overview.MemoryUsagePercent;
            MemoryDetailValue.Text = $"已用 {FormatBytes(overview.UsedMemoryBytes)} / {FormatBytes(overview.TotalMemoryBytes)}\n可用 {FormatBytes(overview.AvailableMemoryBytes)}";
            ProcessMemoryValue.Text = $"服务器进程:{FormatBytes(overview.WorkingSetBytes)}";
            ServerNameValue.Text = overview.ServerName;
            UpdatedValue.Text = $"最后更新:{overview.Utc.ToLocalTime():yyyy-MM-dd HH:mm:ss}";
            LiveIndicator.Fill = new SolidColorBrush(Color.FromRgb(113, 238, 162));
            hasSnapshot = true;
        }
        catch (Exception exception)
        {
            ErrorText.Text = $"读取服务器状态失败:{exception.Message}";
            if (!hasSnapshot) StatusValue.Text = "不可用";
            LiveIndicator.Fill = new SolidColorBrush(Color.FromRgb(239, 112, 112));
        }
        finally { isRefreshing = false; }
    }

    private static string FormatDuration(double seconds)
    {
        var value = TimeSpan.FromSeconds(Math.Max(0, seconds));
        if (value.TotalDays >= 1) return $"{(int)value.TotalDays} 天 {value.Hours} 小时";
        if (value.TotalHours >= 1) return $"{value.Hours} 小时 {value.Minutes} 分";
        return $"{value.Minutes} 分 {value.Seconds} 秒";
    }

    private static string FormatBytes(long bytes) => bytes switch
    {
        >= 1024L * 1024 * 1024 => $"{bytes / (1024d * 1024 * 1024):F2} GB",
        >= 1024L * 1024 => $"{bytes / (1024d * 1024):F2} MB",
        >= 1024L => $"{bytes / 1024d:F2} KB",
        _ => $"{bytes} B"
    };
}