feat: 优化 Api 管理

This commit is contained in:
denglihong2007
2025-10-18 20:51:41 +08:00
parent b3bd44bdd1
commit f3414089d4
9 changed files with 83 additions and 39 deletions

View File

@@ -0,0 +1,9 @@
namespace CRSim.Core.Abstractions
{
public interface IApi
{
string Name { get; }
string BaseApi { get; }
string UpdateApi { get; }
}
}

View File

@@ -0,0 +1,15 @@
namespace CRSim.Core.Abstractions
{
/// <summary>
/// 定义 API 客户端工厂的合约,用于创建 IApi 实例。
/// </summary>
public interface IApiFactory
{
/// <summary>
/// 根据客户端类型名称和基础 URL 创建 IApi 实例。
/// </summary>
/// <param name="clientName">客户端的唯一名称。</param>
/// <returns>返回具体的 IApi 实现。</returns>
IApi CreateApi(string clientName);
}
}

View File

@@ -1,5 +1,5 @@
using CRSim.Core.Converters;
using System.Text.Json.Serialization;
using CRSim.Core.Abstractions;
using CRSim.Core.Services;
namespace CRSim.Core.Models
{
@@ -18,8 +18,9 @@ namespace CRSim.Core.Models
/// 直到终到后多久停止显示
/// </summary>
public TimeSpan StopDisplayFromArrivalDuration { get; set; } = TimeSpan.FromMinutes(10);
public TimeSpan StopCheckInAdvanceDuration { get; set; } = TimeSpan.FromMinutes(2);
public string ApiUri { get; set; } = "http://47.122.74.193:25565";
public IApi Api { get; set; } = new ApiFactory().CreateApi("官方站");
public int MaxPages { get; set; } = 3;
public int SwitchPageSeconds { get; set; } = 20;
public string UserKey { get; set; } = "";

View File

@@ -0,0 +1,34 @@
using CRSim.Core.Abstractions;
namespace CRSim.Core.Services
{
/// <summary>
/// IApiFactory 的具体实现,负责根据配置实例化正确的 IApi 客户端。
/// </summary>
public class ApiFactory : IApiFactory
{
public IApi CreateApi(string clientName)
{
clientName ??= string.Empty;
return clientName switch
{
"镜像站" => new MirrorApi(),
"官方站" => new OfficialApi(),
_ => new OfficialApi()
};
}
}
public class OfficialApi : IApi
{
public string Name => "官方站";
public string BaseApi => "https://47.122.74.193:25565/";
public string UpdateApi => "https://api.github.com/repos/denglihong2007/CRSim/releases/latest";
}
public class MirrorApi : IApi
{
public string Name => "镜像站";
public string BaseApi => "https://crsim.com.cn/api";
public string UpdateApi => "https://crsim.com.cn/api/version";
}
}

View File

@@ -13,12 +13,12 @@ using Downloader;
namespace CRSim.Core.Services;
public class PluginService : IPluginService
public class PluginService(INetworkService networkService, ISettingsService settingsService) : IPluginService
{
public static readonly string PluginManifestFileName = "manifest.json";
public static readonly string StyleInfoFileName = "style.json";
private string IndexUrl => $"{_settings.ApiUri}/GetFile?fileName=plugins.json";
private string IndexUrl => $"{_settings.Api.BaseApi}/GetFile?fileName=plugins.json";
public static void InitializePlugins(HostBuilderContext context, IServiceCollection services,string externalPluginPath)
{
@@ -121,16 +121,11 @@ public class PluginService : IPluginService
}
}
}
private readonly Models.Settings _settings;
private readonly INetworkService _networkService;
public PluginService(INetworkService networkService,ISettingsService settingsService)
{
_networkService = networkService;
_settings = settingsService.GetSettings();
}
private readonly Settings _settings = settingsService.GetSettings();
public async Task LoadOnlinePluginsAsync()
{
var pluginManifests = await _networkService.GetOnlinePluginsAsync(IndexUrl);
var pluginManifests = await networkService.GetOnlinePluginsAsync(IndexUrl);
IPluginService.OnlinePluginsInternal.Clear();
foreach (var Manifest in pluginManifests ?? [])
{
@@ -138,7 +133,7 @@ public class PluginService : IPluginService
var info = new PluginInfo
{
Manifest = Manifest,
RealIconPath = $"{_settings.ApiUri}/GetFile?fileName=icons/{Manifest.Id}.png",
RealIconPath = $"{_settings.Api.BaseApi}/GetFile?fileName=icons/{Manifest.Id}.png",
LoadStatus = localInfo?.LoadStatus ?? PluginLoadStatus.NotLoaded,
PluginFolderPath = localInfo?.PluginFolderPath ?? string.Empty,
};
@@ -150,7 +145,7 @@ public class PluginService : IPluginService
public async Task InstallPluginOnlineAsync(PluginInfo plugin)
{
var id = plugin.Manifest.Id;
var packageUrl = $"{_settings.ApiUri}/GetFile?fileName=plugins/{id}{IPluginService.PluginPackageExtension}";
var packageUrl = $"{_settings.Api.BaseApi}/GetFile?fileName=plugins/{id}{IPluginService.PluginPackageExtension}";
var tempDir = Path.Combine(AppPaths.TempPath, "Plugins", Guid.NewGuid().ToString());
Directory.CreateDirectory(tempDir);
var packagePath = Path.Combine(tempDir, $"{id}{IPluginService.PluginPackageExtension}");

View File

@@ -1,7 +1,6 @@
using CRSim.Core.Abstractions;
using CRSim.Core.Models;
using Microsoft.Win32;
using System.Text.Json;
namespace CRSim.Core.Services
{
@@ -12,7 +11,7 @@ namespace CRSim.Core.Services
public void SaveSettings()
{
_key.SetValue("SwitchPageSeconds", _settings.SwitchPageSeconds);
_key.SetValue("ApiUri", _settings.ApiUri);
_key.SetValue("Api", _settings.Api.Name);
_key.SetValue("MaxPages", _settings.MaxPages);
_key.SetValue("StopCheckInAdvanceDuration", (int)_settings.StopCheckInAdvanceDuration.TotalMinutes);
_key.SetValue("StopDisplayUntilDepartureDuration", (int)_settings.StopDisplayUntilDepartureDuration.TotalMinutes);
@@ -36,7 +35,7 @@ namespace CRSim.Core.Services
{
_settings = new Settings();
if (_key.GetValue("SwitchPageSeconds") != null) _settings.SwitchPageSeconds = (int)_key.GetValue("SwitchPageSeconds");
if (_key.GetValue("ApiUri") != null) _settings.ApiUri = (string)_key.GetValue("ApiUri");
_settings.Api = new ApiFactory().CreateApi((string)_key.GetValue("Api"));
if (_key.GetValue("MaxPages") != null) _settings.MaxPages = (int)_key.GetValue("MaxPages");
if (_key.GetValue("StopCheckInAdvanceDuration") != null) _settings.StopCheckInAdvanceDuration = TimeSpan.FromMinutes((int)_key.GetValue("StopCheckInAdvanceDuration"));
if (_key.GetValue("StopDisplayUntilDepartureDuration") != null) _settings.StopDisplayUntilDepartureDuration = TimeSpan.FromMinutes((int)_key.GetValue("StopDisplayUntilDepartureDuration"));

View File

@@ -1,6 +1,4 @@
using System.Windows;
namespace CRSim.ViewModels;
namespace CRSim.ViewModels;
public partial class DashboardPageViewModel : ObservableObject
{
[ObservableProperty]
@@ -17,12 +15,7 @@ public partial class DashboardPageViewModel : ObservableObject
}
private async void InitializeAsync()
{
var url = _settingsService.GetSettings().ApiUri.Contains("47")
? "https://api.github.com/repos/denglihong2007/CRSim/releases/latest"
: "https://crsim.com.cn/api/version";
var updateInfo = await _networkService.GetUpdateAsync(url);
var updateInfo = await _networkService.GetUpdateAsync(_settingsService.GetSettings().Api.UpdateApi);
if (updateInfo is not null && updateInfo.Name != Assembly.GetExecutingAssembly().GetName().Version.ToString())
{
UpdateMessage = $"有新版本 {updateInfo.Name} 可用,请前往“设置”下载安装更新!";

View File

@@ -13,10 +13,10 @@ namespace CRSim.ViewModels
[ObservableProperty]
public partial string AppVersion { get; set; } = "";
public ObservableCollection<InfoItem> Apis { get; } =
public ObservableCollection<IApi> Apis { get; } =
[
new InfoItem { Title = "官方源", Detail = "http://47.122.74.193:25565" },
new InfoItem { Title = "镜像站源", Detail = "https://crsim.com.cn/api" },
new ApiFactory().CreateApi("官方站"),
new ApiFactory().CreateApi("镜像站"),
];
private Settings _settings;
private readonly ISettingsService _settingsService;
@@ -50,7 +50,7 @@ namespace CRSim.ViewModels
public partial string SwitchPageSeconds { get; set; }
[ObservableProperty]
public partial InfoItem ApiUri { get; set; }
public partial IApi Api { get; set; }
[ObservableProperty]
public partial string UserKey { get; set; }
@@ -81,7 +81,7 @@ namespace CRSim.ViewModels
StopDisplayUntilDepartureDuration = _settings.StopDisplayUntilDepartureDuration.TotalMinutes.ToString();
StopDisplayFromArrivalDuration = _settings.StopDisplayFromArrivalDuration.TotalMinutes.ToString();
StopCheckInAdvanceDuration = _settings.StopCheckInAdvanceDuration.TotalMinutes.ToString();
ApiUri = Apis.Where(x => x.Detail == _settings.ApiUri).FirstOrDefault();
Api = Apis.First(x => x.Name == _settings.Api.Name);
MaxPages = _settings.MaxPages.ToString();
SwitchPageSeconds = _settings.SwitchPageSeconds.ToString();
UserKey = _settings.UserKey;
@@ -102,7 +102,7 @@ namespace CRSim.ViewModels
_settings.UserKey = UserKey;
_settings.LoadTodayOnly = LoadTodayOnly;
_settings.ReopenUnclosedScreensOnLoad = ReopenUnclosedScreensOnLoad;
_settings.ApiUri = ApiUri.Detail;
_settings.Api = Api;
_settingsService.SaveSettings();
}
private static void UpdateSettings(string input, bool allowNegative, Action<int> updateAction)
@@ -123,9 +123,7 @@ namespace CRSim.ViewModels
[RelayCommand]
public async Task CheckUpdate()
{
var update = ApiUri.Title == "官方源" ?
await _networkService.GetUpdateAsync("https://api.github.com/repos/denglihong2007/CRSim/releases/latest") :
await _networkService.GetUpdateAsync("https://crsim.com.cn/api/version");
var update = await _networkService.GetUpdateAsync(Api.UpdateApi);
if (update is null)
{
await _dialogService.ShowMessageAsync("错误", "检查更新失败。");
@@ -169,7 +167,7 @@ namespace CRSim.ViewModels
}
var programDirectory = AppDomain.CurrentDomain.BaseDirectory;
var appExePath = Process.GetCurrentProcess().MainModule.FileName;
var appExePath = Environment.ProcessPath;
var appName = Path.GetFileName(appExePath);
string batchScript = $@"
@echo off

View File

@@ -43,8 +43,8 @@
<TextBox Width="168" Text="{x:Bind ViewModel.UserKey, Mode=TwoWay}"/>
</controls:SettingsCard>
<controls:SettingsCard Header="API 地址" Description="适用于插件市场与软件更新" HeaderIcon="{winui:FontIcon Glyph=&#xE943;}">
<ComboBox ItemsSource="{x:Bind ViewModel.Apis}" SelectedItem="{x:Bind ViewModel.ApiUri,Mode=TwoWay}"
DisplayMemberPath="Title" Width="168"/>
<ComboBox ItemsSource="{x:Bind ViewModel.Apis}" SelectedItem="{x:Bind ViewModel.Api,Mode=TwoWay}"
DisplayMemberPath="Name" Width="168"/>
</controls:SettingsCard>
<controls:SettingsCard Header="应用更新" Description="检查软件更新" HeaderIcon="{winui:FontIcon Glyph=&#xECC5;}">
<Button Style="{StaticResource AccentButtonStyle}" Content="检查更新" Command="{x:Bind ViewModel.CheckUpdateCommand}" />