feat: Better-Seewo v2.0.0 - 希沃白板功能增强插件
- Fluent Design 风格 UI,深色/浅色主题切换 - 平滑过渡动画(页面切换、按钮交互、状态变化) - 五大核心功能:安装管理、墨迹管理、格式转换、触摸设置、激活管理 - 基于 dotnetCampus.EasiPlugin.Sdk v2.1.1-alpha.3 插件框架 - WPF 安装向导(欢迎页 -> 安装页 -> 完成页)
This commit is contained in:
345
Installer/Pages/InstallPage.xaml.cs
Normal file
345
Installer/Pages/InstallPage.xaml.cs
Normal file
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// InstallPage 的交互逻辑 - 安装向导安装页面
|
||||
/// </summary>
|
||||
public partial class InstallPage : Page
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前安装进度(0-100)
|
||||
/// </summary>
|
||||
private int _currentProgress;
|
||||
|
||||
/// <summary>
|
||||
/// 标记安装是否已启动
|
||||
/// </summary>
|
||||
private bool _isStarted;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,初始化页面组件
|
||||
/// </summary>
|
||||
public InstallPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// 设置默认安装路径
|
||||
TxtInstallPath.Text = App.InstallPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 浏览按钮点击 - 选择安装路径
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始安装过程(由主窗口调用)
|
||||
/// 模拟三个安装步骤:检测EN5 -> 复制文件 -> 注册插件
|
||||
/// </summary>
|
||||
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 ===== 辅助方法 =====
|
||||
|
||||
/// <summary>
|
||||
/// 获取 EasiNote5 的安装路径
|
||||
/// 检查常见的 EN5 安装目录
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置安装步骤的状态图标
|
||||
/// </summary>
|
||||
/// <param name="step">步骤编号(1-3)</param>
|
||||
/// <param name="status">状态:running/success/warning/error</param>
|
||||
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")
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新进度条和百分比文字
|
||||
/// </summary>
|
||||
/// <param name="progress">进度值(0-100)</param>
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向日志文本框追加一行日志
|
||||
/// </summary>
|
||||
/// <param name="message">日志消息</param>
|
||||
private void AppendLog(string message)
|
||||
{
|
||||
// 确保在 UI 线程执行
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
TxtLog.Text += message + Environment.NewLine;
|
||||
|
||||
// 自动滚动到底部
|
||||
LogScrollViewer.ScrollToEnd();
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user