From f3414089d4f35fe41b7f08c5a84fd26f605fe610 Mon Sep 17 00:00:00 2001 From: denglihong2007 <98096191+denglihong2007@users.noreply.github.com> Date: Sat, 18 Oct 2025 20:51:41 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Api=20?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CRSim.Core/Abstractions/IApi.cs | 9 ++++++ CRSim.Core/Abstractions/IApiFactory.cs | 15 ++++++++++ CRSim.Core/Models/Settings.cs | 7 +++-- CRSim.Core/Services/ApiFactory.cs | 34 ++++++++++++++++++++++ CRSim.Core/Services/PluginService.cs | 19 +++++------- CRSim.Core/Services/SettingsService.cs | 5 ++-- CRSim/ViewModels/DashboardPageViewModel.cs | 11 ++----- CRSim/ViewModels/SettingsPageViewModel.cs | 18 +++++------- CRSim/Views/SettingsPage.xaml | 4 +-- 9 files changed, 83 insertions(+), 39 deletions(-) create mode 100644 CRSim.Core/Abstractions/IApi.cs create mode 100644 CRSim.Core/Abstractions/IApiFactory.cs create mode 100644 CRSim.Core/Services/ApiFactory.cs diff --git a/CRSim.Core/Abstractions/IApi.cs b/CRSim.Core/Abstractions/IApi.cs new file mode 100644 index 0000000..cf43460 --- /dev/null +++ b/CRSim.Core/Abstractions/IApi.cs @@ -0,0 +1,9 @@ +namespace CRSim.Core.Abstractions +{ + public interface IApi + { + string Name { get; } + string BaseApi { get; } + string UpdateApi { get; } + } +} diff --git a/CRSim.Core/Abstractions/IApiFactory.cs b/CRSim.Core/Abstractions/IApiFactory.cs new file mode 100644 index 0000000..2917389 --- /dev/null +++ b/CRSim.Core/Abstractions/IApiFactory.cs @@ -0,0 +1,15 @@ +namespace CRSim.Core.Abstractions +{ + /// + /// 定义 API 客户端工厂的合约,用于创建 IApi 实例。 + /// + public interface IApiFactory + { + /// + /// 根据客户端类型名称和基础 URL 创建 IApi 实例。 + /// + /// 客户端的唯一名称。 + /// 返回具体的 IApi 实现。 + IApi CreateApi(string clientName); + } +} diff --git a/CRSim.Core/Models/Settings.cs b/CRSim.Core/Models/Settings.cs index 4b4b8ef..d91500c 100644 --- a/CRSim.Core/Models/Settings.cs +++ b/CRSim.Core/Models/Settings.cs @@ -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 /// 直到终到后多久停止显示 /// 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; } = ""; diff --git a/CRSim.Core/Services/ApiFactory.cs b/CRSim.Core/Services/ApiFactory.cs new file mode 100644 index 0000000..c41ea78 --- /dev/null +++ b/CRSim.Core/Services/ApiFactory.cs @@ -0,0 +1,34 @@ +using CRSim.Core.Abstractions; + +namespace CRSim.Core.Services +{ + /// + /// IApiFactory 的具体实现,负责根据配置实例化正确的 IApi 客户端。 + /// + 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"; + } +} diff --git a/CRSim.Core/Services/PluginService.cs b/CRSim.Core/Services/PluginService.cs index 15e834c..c0f1e60 100644 --- a/CRSim.Core/Services/PluginService.cs +++ b/CRSim.Core/Services/PluginService.cs @@ -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}"); diff --git a/CRSim.Core/Services/SettingsService.cs b/CRSim.Core/Services/SettingsService.cs index 385ff77..d08dae6 100644 --- a/CRSim.Core/Services/SettingsService.cs +++ b/CRSim.Core/Services/SettingsService.cs @@ -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")); diff --git a/CRSim/ViewModels/DashboardPageViewModel.cs b/CRSim/ViewModels/DashboardPageViewModel.cs index 5410ba3..bb46e97 100644 --- a/CRSim/ViewModels/DashboardPageViewModel.cs +++ b/CRSim/ViewModels/DashboardPageViewModel.cs @@ -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} 可用,请前往“设置”下载安装更新!"; diff --git a/CRSim/ViewModels/SettingsPageViewModel.cs b/CRSim/ViewModels/SettingsPageViewModel.cs index 1700494..98a51b9 100644 --- a/CRSim/ViewModels/SettingsPageViewModel.cs +++ b/CRSim/ViewModels/SettingsPageViewModel.cs @@ -13,10 +13,10 @@ namespace CRSim.ViewModels [ObservableProperty] public partial string AppVersion { get; set; } = ""; - public ObservableCollection Apis { get; } = + public ObservableCollection 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 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 diff --git a/CRSim/Views/SettingsPage.xaml b/CRSim/Views/SettingsPage.xaml index 631ef77..58cfdc3 100644 --- a/CRSim/Views/SettingsPage.xaml +++ b/CRSim/Views/SettingsPage.xaml @@ -43,8 +43,8 @@ - +