/* * InstallPage.xaml.cs - Better-Seewo 安装向导安装页面逻辑 * 负责模拟安装过程、更新进度条和日志、管理安装步骤状态 * 作者:雾启工作室 */ using System; using System.IO; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Animation; namespace Better_Seewo.Installer.Pages { /// /// InstallPage 的交互逻辑 - 安装向导安装页面 /// public partial class InstallPage : Page { /// /// 当前安装进度(0-100) /// private int _currentProgress; /// /// 标记安装是否已启动 /// private bool _isStarted; /// /// 构造函数,初始化页面组件 /// public InstallPage() { InitializeComponent(); // 设置默认安装路径 TxtInstallPath.Text = App.InstallPath; } /// /// 浏览按钮点击 - 选择安装路径 /// private void BtnBrowse_Click(object sender, RoutedEventArgs e) { // 如果安装已开始则不允许更改路径 if (_isStarted) return; // 使用文件夹浏览对话框选择安装路径 var dialog = new System.Windows.Forms.FolderBrowserDialog { Description = "选择 Better-Seewo 安装路径", ShowNewFolderButton = true, SelectedPath = TxtInstallPath.Text }; if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { TxtInstallPath.Text = dialog.SelectedPath; App.InstallPath = dialog.SelectedPath; } } /// /// 开始安装过程(由主窗口调用) /// 模拟三个安装步骤:检测EN5 -> 复制文件 -> 注册插件 /// public async void StartInstallation() { if (_isStarted) return; _isStarted = true; try { // 禁用路径输入和浏览按钮 TxtInstallPath.IsReadOnly = true; // 更新安装路径 App.InstallPath = TxtInstallPath.Text; // ===== 步骤 1:检测 EN5 安装状态 ===== SetStepStatus(1, "running"); AppendLog($"[{DateTime.Now:HH:mm:ss}] 正在检测 EasiNote5 安装状态..."); await Task.Delay(800); // 检查 EN5 安装目录是否存在 string en5Path = GetEn5InstallPath(); bool en5Exists = !string.IsNullOrEmpty(en5Path) && Directory.Exists(en5Path); if (en5Exists) { AppendLog($"[{DateTime.Now:HH:mm:ss}] 已检测到 EasiNote5 安装路径: {en5Path}"); SetStepStatus(1, "success"); } else { AppendLog($"[{DateTime.Now:HH:mm:ss}] 未检测到 EasiNote5 安装,将继续安装到指定路径"); SetStepStatus(1, "warning"); } UpdateProgress(25); await Task.Delay(300); // ===== 步骤 2:复制插件文件 ===== SetStepStatus(2, "running"); AppendLog($"[{DateTime.Now:HH:mm:ss}] 正在复制插件文件..."); await Task.Delay(600); // 创建目标目录 string installDir = App.InstallPath; try { if (!Directory.Exists(installDir)) { Directory.CreateDirectory(installDir); AppendLog($"[{DateTime.Now:HH:mm:ss}] 已创建安装目录: {installDir}"); } // TODO: 实际安装时,将插件文件从安装包复制到目标目录 // 以下为模拟文件复制过程 string[] mockFiles = { "Better-EN5.dll", "Better-EN5.pdb", "Newtonsoft.Json.dll", "config.json" }; foreach (var file in mockFiles) { await Task.Delay(200); AppendLog($"[{DateTime.Now:HH:mm:ss}] 正在复制: {file}"); UpdateProgress(25 + (Array.IndexOf(mockFiles, file) + 1) * 10); } AppendLog($"[{DateTime.Now:HH:mm:ss}] 插件文件复制完成"); SetStepStatus(2, "success"); } catch (Exception ex) { AppendLog($"[{DateTime.Now:HH:mm:ss}] 复制文件失败: {ex.Message}"); SetStepStatus(2, "error"); throw; } await Task.Delay(300); // ===== 步骤 3:注册插件 ===== SetStepStatus(3, "running"); AppendLog($"[{DateTime.Now:HH:mm:ss}] 正在注册插件..."); await Task.Delay(500); try { // TODO: 实际安装时,写入注册表或配置文件完成插件注册 await Task.Delay(400); AppendLog($"[{DateTime.Now:HH:mm:ss}] 正在写入插件配置..."); UpdateProgress(80); await Task.Delay(300); AppendLog($"[{DateTime.Now:HH:mm:ss}] 正在注册 EasiNote5 插件组件..."); UpdateProgress(90); await Task.Delay(300); AppendLog($"[{DateTime.Now:HH:mm:ss}] 插件注册完成"); SetStepStatus(3, "success"); } catch (Exception ex) { AppendLog($"[{DateTime.Now:HH:mm:ss}] 注册插件失败: {ex.Message}"); SetStepStatus(3, "error"); throw; } // ===== 安装完成 ===== UpdateProgress(100); AppendLog($"[{DateTime.Now:HH:mm:ss}] ========================================"); AppendLog($"[{DateTime.Now:HH:mm:ss}] 安装完成!Better-Seewo v{App.AppVersion} 已成功安装"); AppendLog($"[{DateTime.Now:HH:mm:ss}] 安装路径: {App.InstallPath}"); // 延迟后自动切换到完成页 await Task.Delay(1000); // 通知主窗口安装完成 if (Window.GetWindow(this) is MainWindow mainWindow) { mainWindow.OnInstallCompleted(); } } catch (Exception ex) { AppendLog($"[{DateTime.Now:HH:mm:ss}] 安装过程中发生错误: {ex.Message}"); MessageBox.Show( $"安装失败:{ex.Message}", "Better-Seewo 安装程序", MessageBoxButton.OK, MessageBoxImage.Error ); // 恢复按钮状态,允许重试 if (Window.GetWindow(this) is MainWindow mainWindow) { mainWindow.BtnInstall.IsEnabled = true; mainWindow.BtnInstall.Content = "重试安装 \uE74E;"; mainWindow.BtnBack.IsEnabled = true; } App.IsInstalling = false; _isStarted = false; } } #region ===== 辅助方法 ===== /// /// 获取 EasiNote5 的安装路径 /// 检查常见的 EN5 安装目录 /// private static string GetEn5InstallPath() { // 常见的 EasiNote5 安装路径 string[] possiblePaths = { @"C:\Program Files (x86)\Seewo\EasiNote5", @"C:\Program Files\Seewo\EasiNote5", @"D:\Program Files (x86)\Seewo\EasiNote5", @"D:\Program Files\Seewo\EasiNote5" }; foreach (var path in possiblePaths) { if (Directory.Exists(path)) { return path; } } return null; } /// /// 设置安装步骤的状态图标 /// /// 步骤编号(1-3) /// 状态:running/success/warning/error private void SetStepStatus(int step, string status) { // 确保在 UI 线程执行 Dispatcher.Invoke(() => { var icon = step switch { 1 => Step1Icon, 2 => Step2Icon, 3 => Step3Icon, _ => Step1Icon }; if (icon == null) return; // 根据状态设置图标和颜色 icon.Text = status switch { "running" => "⏳", "success" => "✓", "warning" => "⚠", "error" => "✗", _ => "⏳" }; icon.Foreground = status switch { "running" => (System.Windows.Media.Brush)FindResource("WarningBrush"), "success" => (System.Windows.Media.Brush)FindResource("SuccessBrush"), "warning" => (System.Windows.Media.Brush)FindResource("WarningBrush"), "error" => (System.Windows.Media.Brush)FindResource("ErrorBrush"), _ => (System.Windows.Media.Brush)FindResource("TextSecondaryBrush") }; }); } /// /// 更新进度条和百分比文字 /// /// 进度值(0-100) private void UpdateProgress(int progress) { _currentProgress = Math.Clamp(progress, 0, 100); // 确保在 UI 线程执行 Dispatcher.Invoke(() => { // 更新百分比文字 TxtProgress.Text = $"{_currentProgress}%"; // 更新进度条宽度(使用动画) var widthAnimation = new DoubleAnimation { From = (ProgressFill.ActualWidth > 0 ? ProgressFill.ActualWidth : 0), To = (_currentProgress / 100.0) * ProgressFill.Parent.ActualWidth, Duration = TimeSpan.FromMilliseconds(300), EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut } }; // 如果父容器尚未布局完成,直接设置宽度 if (ProgressFill.Parent.ActualWidth == 0) { // 等待布局完成后设置 ProgressFill.Loaded += (s, e) => { var loadedAnimation = new DoubleAnimation { From = 0, To = (_currentProgress / 100.0) * ProgressFill.Parent.ActualWidth, Duration = TimeSpan.FromMilliseconds(300), EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut } }; ProgressFill.BeginAnimation(WidthProperty, loadedAnimation); }; } else { ProgressFill.BeginAnimation(WidthProperty, widthAnimation); } }); } /// /// 向日志文本框追加一行日志 /// /// 日志消息 private void AppendLog(string message) { // 确保在 UI 线程执行 Dispatcher.Invoke(() => { TxtLog.Text += message + Environment.NewLine; // 自动滚动到底部 LogScrollViewer.ScrollToEnd(); }); } #endregion } }