feat: Better-Seewo v2.0.0 - 希沃白板功能增强插件

- Fluent Design 风格 UI,深色/浅色主题切换
- 平滑过渡动画(页面切换、按钮交互、状态变化)
- 五大核心功能:安装管理、墨迹管理、格式转换、触摸设置、激活管理
- 基于 dotnetCampus.EasiPlugin.Sdk v2.1.1-alpha.3 插件框架
- WPF 安装向导(欢迎页 -> 安装页 -> 完成页)
This commit is contained in:
miao-moe
2026-06-28 06:51:35 +00:00
commit 8dd1eed519
40 changed files with 8966 additions and 0 deletions

View File

@@ -0,0 +1,281 @@
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace Better_Seewo.Manager.Pages
{
/// <summary>
/// InstallPage.xaml 的交互逻辑
/// 安装管理页面 - 管理 Better-Seewo 插件的安装与配置
/// </summary>
public partial class InstallPage : Page
{
// ===== 默认检测路径 =====
private const string DefaultEn5Path = @"C:\Program Files (x86)\Seewo\EasiNote5\EasiNote5_5.2.4.9855\Main";
private const string PluginDirName = "Plugins/Better-EN5";
private const string ManagerExeName = "Manager.exe";
// ===== 检测结果 =====
private string _en5Path = string.Empty;
private bool _en5Installed;
private bool _pluginInstalled;
private bool _managerInstalled;
public InstallPage()
{
InitializeComponent();
Loaded += InstallPage_Loaded;
}
/// <summary>
/// 页面加载完成时执行入场动画和状态检测
/// </summary>
private async void InstallPage_Loaded(object sender, RoutedEventArgs e)
{
// 播放入场动画交错延迟100ms
PlayCardEntranceAnimation();
// 异步检测所有状态
await RefreshStatusAsync();
}
/// <summary>
/// 播放卡片的交错入场动画SlideIn + 100ms间隔
/// </summary>
private void PlayCardEntranceAnimation()
{
var cards = new[] { Card1, Card2, Card3, Card4 };
for (int i = 0; i < cards.Length; i++)
{
var card = cards[i];
var transform = (TranslateTransform)card.RenderTransform;
int delay = i * 100; // 每张卡片间隔100ms
// 延迟执行动画
var timer = new System.Windows.Threading.DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(delay)
};
timer.Tick += (s, e) =>
{
timer.Stop();
var slideIn = new DoubleAnimation
{
From = 30,
To = 0,
Duration = TimeSpan.FromMilliseconds(400),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }
};
var fadeIn = new DoubleAnimation
{
From = 0,
To = 1,
Duration = TimeSpan.FromMilliseconds(400),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }
};
transform.BeginAnimation(TranslateTransform.YProperty, slideIn);
transform.BeginAnimation(TranslateTransform.OpacityProperty, fadeIn);
};
timer.Start();
}
}
/// <summary>
/// 异步刷新所有安装状态检测
/// 使用 Dispatcher 确保UI更新不卡顿
/// </summary>
public async Task RefreshStatusAsync()
{
await Task.Run(() =>
{
// 在后台线程执行路径检测
CheckEn5Status();
CheckPluginStatus();
CheckManagerStatus();
});
// 回到UI线程更新界面
Dispatcher.Invoke(() =>
{
UpdateCardStatus();
});
}
/// <summary>
/// 检测EN5安装状态
/// </summary>
private void CheckEn5Status()
{
if (Directory.Exists(DefaultEn5Path))
{
_en5Installed = true;
_en5Path = DefaultEn5Path;
}
else
{
_en5Installed = false;
_en5Path = string.Empty;
}
}
/// <summary>
/// 检测插件安装状态
/// </summary>
private void CheckPluginStatus()
{
if (!string.IsNullOrEmpty(_en5Path))
{
var pluginPath = Path.Combine(_en5Path, PluginDirName);
_pluginInstalled = Directory.Exists(pluginPath);
}
else
{
_pluginInstalled = false;
}
}
/// <summary>
/// 检测管理器安装状态
/// </summary>
private void CheckManagerStatus()
{
if (!string.IsNullOrEmpty(_en5Path))
{
var managerPath = Path.Combine(_en5Path, ManagerExeName);
_managerInstalled = File.Exists(managerPath);
}
else
{
_managerInstalled = false;
}
}
/// <summary>
/// 更新所有卡片的状态显示
/// </summary>
private void UpdateCardStatus()
{
// 更新EN5状态卡片
UpdateStatusIcon(En5StatusIcon, _en5Installed);
En5StatusText.Text = _en5Installed ? "已安装" : "未安装";
En5VersionText.Text = _en5Installed ? "5.2.4.9855" : "-";
En5PathText.Text = $"路径:{_en5Path}";
// 更新插件状态卡片
UpdateStatusIcon(PluginStatusIcon, _pluginInstalled);
PluginStatusText.Text = _pluginInstalled ? "已安装" : "未安装";
PluginPathText.Text = $"路径:{Path.Combine(_en5Path, PluginDirName)}";
// 更新管理器状态卡片
UpdateStatusIcon(ManagerStatusIcon, _managerInstalled);
ManagerStatusText.Text = _managerInstalled ? "已安装" : "未安装";
ManagerPathText.Text = $"路径:{Path.Combine(_en5Path, ManagerExeName)}";
// 更新安装路径卡片
UpdateStatusIcon(PathStatusIcon, _en5Installed);
InstallPathText.Text = string.IsNullOrEmpty(_en5Path) ? "未检测到" : _en5Path;
InstallPathValidText.Text = _en5Installed ? "路径有效" : "路径无效或不存在";
}
/// <summary>
/// 更新状态图标(绿色勾/红色叉)
/// </summary>
private void UpdateStatusIcon(FrameworkElement icon, bool isInstalled)
{
if (icon is Ellipse ellipse)
{
ellipse.Fill = new SolidColorBrush(isInstalled ?
Color.FromRgb(0x4C, 0xAF, 0x50) : Color.FromRgb(0xF4, 0x43, 0x36));
}
}
/// <summary>
/// 向日志区域追加一条消息
/// </summary>
private void AppendLog(string message)
{
var timestamp = DateTime.Now.ToString("HH:mm:ss");
LogText.Text += $"\n[{timestamp}] {message}";
}
// ===== 按钮点击事件处理 =====
/// <summary>
/// 安装插件按钮点击事件
/// </summary>
private async void BtnInstallPlugin_Click(object sender, RoutedEventArgs e)
{
AppendLog("开始安装插件...");
await Task.Run(() =>
{
// TODO: 实际安装逻辑 - 复制插件文件到EN5的Plugins目录
// 当前为开发占位实现
System.Threading.Thread.Sleep(1000);
});
AppendLog("插件安装完成(开发中,暂为占位实现)");
await RefreshStatusAsync();
}
/// <summary>
/// 卸载插件按钮点击事件
/// </summary>
private async void BtnUninstallPlugin_Click(object sender, RoutedEventArgs e)
{
AppendLog("开始卸载插件...");
await Task.Run(() =>
{
// TODO: 实际卸载逻辑 - 删除Plugins/Better-EN5目录
// 当前为开发占位实现
System.Threading.Thread.Sleep(1000);
});
AppendLog("插件卸载完成(开发中,暂为占位实现)");
await RefreshStatusAsync();
}
/// <summary>
/// 安装管理器按钮点击事件
/// </summary>
private async void BtnInstallManager_Click(object sender, RoutedEventArgs e)
{
AppendLog("开始安装管理器...");
await Task.Run(() =>
{
// TODO: 实际安装逻辑 - 复制Manager.exe到EN5目录
// 当前为开发占位实现
System.Threading.Thread.Sleep(1000);
});
AppendLog("管理器安装完成(开发中,暂为占位实现)");
await RefreshStatusAsync();
}
/// <summary>
/// 卸载管理器按钮点击事件
/// </summary>
private async void BtnUninstallManager_Click(object sender, RoutedEventArgs e)
{
AppendLog("开始卸载管理器...");
await Task.Run(() =>
{
// TODO: 实际卸载逻辑 - 删除Manager.exe
// 当前为开发占位实现
System.Threading.Thread.Sleep(1000);
});
AppendLog("管理器卸载完成(开发中,暂为占位实现)");
await RefreshStatusAsync();
}
/// <summary>
/// 刷新状态按钮点击事件
/// </summary>
private async void BtnRefresh_Click(object sender, RoutedEventArgs e)
{
AppendLog("正在刷新状态...");
await RefreshStatusAsync();
AppendLog("状态刷新完成");
}
}
}