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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml.Controls;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Services;

namespace XFEEDToolBox.ViewModels;

public partial class ToolboxViewModel
{
    [ObservableProperty] public partial string MarketCacheUsageText { get; set; }="正在读取缓存占用…";
    [ObservableProperty] public partial string MarketCacheLegacyNotice { get; set; }="已有缓存保留到你点击清理。";
    [ObservableProperty,NotifyPropertyChangedFor(nameof(HasMarketCacheStatus))]
    public partial string MarketCacheStatus { get; set; }="";
    [ObservableProperty] public partial InfoBarSeverity MarketCacheStatusSeverity { get; set; }=InfoBarSeverity.Informational;
    [ObservableProperty] public partial bool MarketCacheBusy { get; set; }
    public bool HasMarketCacheStatus=>MarketCacheStatus.Length>0;
    public bool MarketCacheClearAvailable=>!MarketCacheBusy&&MarketCacheBlockReason.Length==0;
    public bool MarketCacheRefreshAvailable=>!MarketCacheBusy;
    public string MarketCacheBlockReason
    {
        get
        {
            if(RunActive||NavigationActive||SystemFlightActive||NavigationRouteBusy)return "请先停止自动跑商或导航,再清理行情缓存。";
            if(SessionBusy)return "请等待会话操作完成,再清理行情缓存。";
            if(TradeRegionBusy)return "请等待行情范围保存完成,再清理缓存。";
            if(ImportSystemCommand.IsRunning||ImportSpanshCommand.IsRunning||ImportCaptureCommand.IsRunning)
                return "请先完成或取消数据导入,再清理行情缓存。";
            if(IsBusy&&!MarketCacheBusy)return "数据操作进行中,请稍后清理行情缓存。";
            return "";
        }
    }

    private void InitializeMarketCacheSettings()
    {
        runtime.ClearMarketCacheBlockReason=()=>MarketCacheBlockReason is {Length:>0} reason?reason:null;
        PropertyChanged+=OnMarketCacheSettingsStateChanged;
        foreach(var command in new IAsyncRelayCommand[]{ImportSystemCommand,ImportSpanshCommand,ImportCaptureCommand})
            command.PropertyChanged+=OnMarketCacheImportStateChanged;
    }
    private void OnMarketCacheSettingsStateChanged(object? sender,PropertyChangedEventArgs args)
    {
        if(args.PropertyName is nameof(RunActive) or nameof(NavigationActive) or nameof(SystemFlightActive)
            or nameof(NavigationRouteBusy) or nameof(SessionBusy) or nameof(IsBusy) or nameof(MarketCacheBusy))
            RefreshMarketCacheSettingsAvailability();
    }
    private void OnMarketCacheImportStateChanged(object? sender,PropertyChangedEventArgs args)
    {if(args.PropertyName==nameof(IAsyncRelayCommand.IsRunning))RefreshMarketCacheSettingsAvailability();}
    private void RefreshMarketCacheSettingsAvailability()
    {
        if(!dispatcher.HasThreadAccess){dispatcher.TryEnqueue(RefreshMarketCacheSettingsAvailability);return;}
        OnPropertyChanged(nameof(MarketCacheClearAvailable));OnPropertyChanged(nameof(MarketCacheRefreshAvailable));OnPropertyChanged(nameof(MarketCacheBlockReason));
        ClearMarketCacheCommand.NotifyCanExecuteChanged();RefreshMarketCacheUsageCommand.NotifyCanExecuteChanged();
    }
    private static string MarketCacheSize(long bytes)
    {
        var amount=(double)Math.Max(0,bytes);var units=new[]{"B","KiB","MiB","GiB","TiB"};var unit=0;
        while(amount>=1024&&unit<units.Length-1){amount/=1024;unit++;}
        return unit==0?$"{amount:N0} B":$"{amount:N2} {units[unit]}";
    }
    private void ApplyMarketCacheUsage(MarketCacheUsage usage)
    {
        MarketCacheUsageText=$"已占用 {MarketCacheSize(usage.Bytes)} · {usage.Files:N0} 个文件";
        MarketCacheLegacyNotice=usage.HasLegacyFullCache?"包含旧的全量行情,点击清理后才会移除。":"已有行情缓存会保留到你点击清理。";
    }
    [RelayCommand(CanExecute=nameof(MarketCacheRefreshAvailable))]
    private async Task RefreshMarketCacheUsageAsync()
    {
        if(MarketCacheBusy)return;
        MarketCacheBusy=true;
        try{ApplyMarketCacheUsage(await runtime.GetMarketCacheUsageAsync(lifetime.Token));}
        catch(OperationCanceledException)when(lifetime.IsCancellationRequested){}
        catch(Exception error)
        {
            MarketCacheUsageText="缓存占用暂时无法读取";MarketCacheStatus="读取缓存占用失败,请查看日志详情。";MarketCacheStatusSeverity=InfoBarSeverity.Warning;
            runtime.ReportDiagnostic("market.cache.settings.usage","行情缓存",error,ActivitySeverity.Warning,"读取缓存占用失败,请查看日志详情。");
        }
        finally{MarketCacheBusy=false;}
    }
    [RelayCommand(CanExecute=nameof(MarketCacheClearAvailable))]
    private async Task ClearMarketCacheAsync()
    {
        if(!MarketCacheClearAvailable)return;
        MarketCacheBusy=true;IsBusy=true;MarketCacheStatus="正在清理行情缓存…";MarketCacheStatusSeverity=InfoBarSeverity.Informational;
        CancelMarketRead();Interlocked.Increment(ref marketRequest);
        try
        {
            var result=await runtime.ClearMarketCacheAsync(lifetime.Token);ApplyMarketCacheUsage(result.Usage);
            if(result.Succeeded)
            {
                var retained=result.Usage.HasLegacyFullCache||result.Message.Contains("隔离文件",StringComparison.Ordinal);
                MarketCacheStatus=retained?$"已释放 {MarketCacheSize(result.FreedBytes)};部分缓存仍被占用,可稍后重试。":$"已释放 {MarketCacheSize(result.FreedBytes)},后续按周边范围重新累积行情。";
                MarketCacheStatusSeverity=retained?InfoBarSeverity.Warning:InfoBarSeverity.Success;
                runtime.Log("行情缓存",MarketCacheStatus+" "+result.Message);OnDataChanged(RuntimeChange.Markets);
            }
            else
            {
                var detail=result.Message??"行情缓存清理被拒绝。";
                MarketCacheStatus=detail.Length is >0 and <=90&&!detail.Contains(":\\",StringComparison.Ordinal)&&!detail.Contains('\n')
                    ?detail:"缓存未清理,请停止占用行情数据的操作后重试。";
                MarketCacheStatusSeverity=InfoBarSeverity.Warning;
                runtime.ReportDiagnostic("market.cache.settings.clear","行情缓存",new IOException(detail),ActivitySeverity.Warning,MarketCacheStatus);
            }
        }
        catch(OperationCanceledException)when(lifetime.IsCancellationRequested){}
        catch(Exception error)
        {
            MarketCacheStatus="缓存清理未完成,请查看日志详情。";MarketCacheStatusSeverity=InfoBarSeverity.Error;
            runtime.ReportDiagnostic("market.cache.settings.clear","行情缓存",error,ActivitySeverity.Error,"缓存清理未完成,请查看日志详情。");
        }
        finally{IsBusy=false;MarketCacheBusy=false;}
    }
}