using System.Reflection; using Serilog; namespace YZWater.Core.Services; /// /// 在线升级服务(借鉴 AutoFMA UpdateService,委托注入模式) /// /// 设计原则: /// 1. Core 层只负责版本管理和更新触发,不依赖具体 UI 框架 /// 2. 实际的更新检查/下载/安装逻辑由 UI 层通过 SetTriggerAction 注入 /// 3. config.json 配置 Update.Enabled / CheckOnStartup / CheckIntervalHours /// /// Avalonia 无 AutoUpdater.NET 官方支持,UI 层可接入 Squirrel 或自研下载器后注入。 /// public static class UpdateService { private static DateTime? _lastCheckTime; private static Action? _triggerAction; private static System.Threading.Timer? _checkTimer; /// /// 更新配置 /// public class UpdateConfig { /// 是否启用在线更新 public bool Enabled { get; set; } /// 更新清单地址(appcast URL) public string AppcastUrl { get; set; } = string.Empty; /// 启动时是否检查更新 public bool CheckOnStartup { get; set; } = true; /// 检查间隔(小时,默认 24) public int CheckIntervalHours { get; set; } = 24; } /// /// 当前程序版本(Major.Minor.Build) /// public static string GetCurrentVersion() { var version = Assembly.GetEntryAssembly()?.GetName().Version; return version != null ? $"{version.Major}.{version.Minor}.{version.Build}" : "0.0.0"; } /// 上次检查时间 public static DateTime? LastCheckTime => _lastCheckTime; /// 更新触发器是否已注入 public static bool IsTriggerRegistered => _triggerAction != null; /// /// 注入实际更新触发逻辑(由 UI 层调用,如 Squirrel 下载安装流程) /// public static void SetTriggerAction(Action triggerAction) { _triggerAction = triggerAction; Log.Information("在线更新触发器已注入"); } /// /// 触发在线更新 /// public static bool TriggerUpdate() { if (_triggerAction == null) { Log.Warning("更新触发器未注入,无法执行在线更新"); return false; } Log.Information("触发在线更新,当前版本: {Version}", GetCurrentVersion()); _lastCheckTime = DateTime.Now; try { _triggerAction(); return true; } catch (Exception ex) { Log.Error(ex, "触发在线更新失败"); return false; } } /// /// 启动定期检查(启动时检查一次 + 按 CheckIntervalHours 定时) /// public static void StartPeriodicCheck(Action onCheckDue) { var config = ConfigService.GetConfig()?.Update; if (config is not { Enabled: true }) { Log.Debug("在线更新未启用,跳过定期检查"); return; } var interval = TimeSpan.FromHours(Math.Max(1, config.CheckIntervalHours)); // 启动时检查一次 if (config.CheckOnStartup) { Task.Run(() => { try { _lastCheckTime = DateTime.Now; onCheckDue(); } catch (Exception ex) { Log.Error(ex, "启动时检查更新失败"); } }); } // 定时检查 _checkTimer ??= new System.Threading.Timer(_ => { try { _lastCheckTime = DateTime.Now; onCheckDue(); } catch (Exception ex) { Log.Error(ex, "定时检查更新失败"); } }, null, interval, interval); Log.Information("在线更新定期检查已启动,间隔 {Hours} 小时", config.CheckIntervalHours); } /// /// 停止定期检查 /// public static void StopPeriodicCheck() { _checkTimer?.Dispose(); _checkTimer = null; } }