From 3d4e1872f10563d06c93165bfe9378a44da91c2c Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sun, 28 Dec 2025 10:40:13 +0800 Subject: [PATCH] =?UTF-8?q?add:=E6=96=B0=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加搜索功能 --- Ink Canvas/InkCanvasForClass.csproj | 1 + .../SettingsViews/SearchPanel.xaml | 140 ++++++ .../SettingsViews/SearchPanel.xaml.cs | 418 ++++++++++++++++++ .../Windows/SettingsViews/SettingsWindow.xaml | 5 + .../SettingsViews/SettingsWindow.xaml.cs | 42 +- 5 files changed, 605 insertions(+), 1 deletion(-) create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsViews/SearchPanel.xaml create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsViews/SearchPanel.xaml.cs diff --git a/Ink Canvas/InkCanvasForClass.csproj b/Ink Canvas/InkCanvasForClass.csproj index 4d5ed9d1..3cb49b7e 100644 --- a/Ink Canvas/InkCanvasForClass.csproj +++ b/Ink Canvas/InkCanvasForClass.csproj @@ -154,6 +154,7 @@ + diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/SearchPanel.xaml b/Ink Canvas/Windows/SettingsViews/SettingsViews/SearchPanel.xaml new file mode 100644 index 00000000..d36e7f85 --- /dev/null +++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/SearchPanel.xaml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/SearchPanel.xaml.cs b/Ink Canvas/Windows/SettingsViews/SettingsViews/SearchPanel.xaml.cs new file mode 100644 index 00000000..bb551de6 --- /dev/null +++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/SearchPanel.xaml.cs @@ -0,0 +1,418 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using Microsoft.International.Converters.PinYinConverter; + +namespace Ink_Canvas.Windows.SettingsViews +{ + /// + /// SearchPanel.xaml 的交互逻辑 + /// + public partial class SearchPanel : UserControl + { + public event EventHandler NavigateToItem; + public event EventHandler CloseSearch; + + private ObservableCollection _exactMatches = new ObservableCollection(); + private ObservableCollection _fuzzyMatches = new ObservableCollection(); + private ObservableCollection _relatedItems = new ObservableCollection(); + + private List _allSettings = new List(); + + public SearchPanel() + { + InitializeComponent(); + InitializeSettings(); + ExactMatchItemsControl.ItemsSource = _exactMatches; + FuzzyMatchItemsControl.ItemsSource = _fuzzyMatches; + RelatedItemsControl.ItemsSource = _relatedItems; + } + + private void InitializeSettings() + { + // 初始化所有设置项数据 + _allSettings = new List + { + // 启动时行为 + new SettingItem { Title = "启动时行为", Category = "启动时行为", ItemName = "StartupItem", Type = SettingItemType.Category }, + + // 画板和墨迹 + new SettingItem { Title = "画板和墨迹", Category = "画板和墨迹", ItemName = "CanvasAndInkItem", Type = SettingItemType.Category }, + + // 手势操作 + new SettingItem { Title = "手势操作", Category = "手势操作", ItemName = "GesturesItem", Type = SettingItemType.Category }, + + // 墨迹纠正 + new SettingItem { Title = "墨迹纠正", Category = "墨迹纠正", ItemName = "InkRecognitionItem", Type = SettingItemType.Category }, + + // 个性化设置 + new SettingItem { Title = "个性化设置", Category = "个性化设置", ItemName = "ThemeItem", Type = SettingItemType.Category }, + + // 快捷键设置 + new SettingItem { Title = "快捷键设置", Category = "快捷键设置", ItemName = "ShortcutsItem", Type = SettingItemType.Category }, + + // 崩溃处理 + new SettingItem { Title = "崩溃处理", Category = "崩溃处理", ItemName = "CrashActionItem", Type = SettingItemType.Category }, + + // PowerPoint 支持 + new SettingItem { Title = "PowerPoint 支持", Category = "PowerPoint 支持", ItemName = "PowerPointItem", Type = SettingItemType.Category }, + + // 自动化行为 + new SettingItem { Title = "自动化行为", Category = "自动化行为", ItemName = "AutomationItem", Type = SettingItemType.Category }, + + // 随机点名 + new SettingItem { Title = "随机点名", Category = "随机点名", ItemName = "LuckyRandomItem", Type = SettingItemType.Category }, + + // 存储空间 + new SettingItem { Title = "存储空间", Category = "存储空间", ItemName = "StorageItem", Type = SettingItemType.Category }, + + // 截图和屏幕捕捉 + new SettingItem { Title = "截图和屏幕捕捉", Category = "截图和屏幕捕捉", ItemName = "SnapshotItem", Type = SettingItemType.Category }, + + // 高级选项 + new SettingItem { Title = "高级选项", Category = "高级选项", ItemName = "AdvancedItem", Type = SettingItemType.Category }, + + // 关于 + new SettingItem { Title = "关于 InkCanvasForClass", Category = "关于", ItemName = "AboutItem", Type = SettingItemType.Category }, + }; + } + + public void PerformSearch(string searchText) + { + if (string.IsNullOrWhiteSpace(searchText)) + { + ClearResults(); + return; + } + + _exactMatches.Clear(); + _fuzzyMatches.Clear(); + _relatedItems.Clear(); + + var searchLower = searchText.ToLower(); + var exactMatchSet = new HashSet(); + var fuzzyMatchSet = new HashSet(); + + // 精准匹配和拼音匹配 + foreach (var setting in _allSettings) + { + var titleLower = setting.Title.ToLower(); + var categoryLower = setting.Category.ToLower(); + + // 精准匹配 + if (titleLower.Contains(searchLower) || categoryLower.Contains(searchLower)) + { + if (!exactMatchSet.Contains(setting.ItemName)) + { + _exactMatches.Add(new SearchResultItem + { + Title = setting.Title, + Category = setting.Category, + ItemName = setting.ItemName, + Type = setting.Type, + MatchType = MatchType.Exact + }); + exactMatchSet.Add(setting.ItemName); + } + } + // 拼音匹配 + else if (ContainsPinyinMatch(setting.Title, searchText) || ContainsPinyinMatch(setting.Category, searchText)) + { + if (!exactMatchSet.Contains(setting.ItemName)) + { + _exactMatches.Add(new SearchResultItem + { + Title = setting.Title, + Category = setting.Category, + ItemName = setting.ItemName, + Type = setting.Type, + MatchType = MatchType.Pinyin + }); + exactMatchSet.Add(setting.ItemName); + } + } + } + + // 模糊匹配 + foreach (var setting in _allSettings) + { + if (exactMatchSet.Contains(setting.ItemName)) + continue; + + var searchableText = $"{setting.Title} {setting.Category} {setting.Description}".ToLower(); + if (FuzzyMatch(searchableText, searchLower)) + { + if (!fuzzyMatchSet.Contains(setting.ItemName)) + { + _fuzzyMatches.Add(new SearchResultItem + { + Title = setting.Title, + Category = setting.Category, + ItemName = setting.ItemName, + Type = setting.Type, + MatchType = MatchType.Fuzzy + }); + fuzzyMatchSet.Add(setting.ItemName); + } + } + } + + // 相关项 + var allMatched = new HashSet(exactMatchSet.Concat(fuzzyMatchSet)); + foreach (var setting in _allSettings) + { + if (!allMatched.Contains(setting.ItemName)) + { + // 简单的相关性判断 + if (IsRelated(setting, searchText)) + { + _relatedItems.Add(new SearchResultItem + { + Title = setting.Title, + Category = setting.Category, + ItemName = setting.ItemName, + Type = setting.Type, + MatchType = MatchType.Related + }); + } + } + } + + UpdateResultsVisibility(); + } + + private bool ContainsPinyinMatch(string text, string search) + { + if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(search)) + return false; + + try + { + // 将搜索词转换为小写 + var searchLower = search.ToLower(); + + // 获取文本的拼音首字母和全拼 + var pinyinInitials = GetPinyinInitials(text); + var pinyinFull = GetPinyinFull(text); + + // 检查搜索词是否匹配拼音首字母或全拼 + if (pinyinInitials.ToLower().Contains(searchLower) || + pinyinFull.ToLower().Contains(searchLower)) + { + return true; + } + } + catch + { + // 如果拼音转换失败,返回false + return false; + } + + return false; + } + + private string GetPinyinInitials(string text) + { + var sb = new StringBuilder(); + foreach (char c in text) + { + if (IsChinese(c)) + { + try + { + var chineseChar = new ChineseChar(c); + if (chineseChar.PinyinCount > 0) + { + var pinyin = chineseChar.Pinyins[0]; + if (!string.IsNullOrEmpty(pinyin) && pinyin.Length > 0) + { + // 获取首字母(移除音调数字后取第一个字母) + var firstChar = Regex.Replace(pinyin, @"\d", "")[0]; + sb.Append(firstChar); + } + } + } + catch + { + sb.Append(c); + } + } + else + { + sb.Append(c); + } + } + return sb.ToString(); + } + + private string GetPinyinFull(string text) + { + var sb = new StringBuilder(); + foreach (char c in text) + { + if (IsChinese(c)) + { + try + { + var chineseChar = new ChineseChar(c); + if (chineseChar.PinyinCount > 0) + { + var pinyin = chineseChar.Pinyins[0]; + // 移除音调数字 + pinyin = Regex.Replace(pinyin, @"\d", ""); + sb.Append(pinyin); + } + } + catch + { + sb.Append(c); + } + } + else + { + sb.Append(c); + } + } + return sb.ToString(); + } + + private bool IsChinese(char c) + { + return c >= 0x4e00 && c <= 0x9fbb; + } + + private bool FuzzyMatch(string text, string search) + { + if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(search)) + return false; + + // 简单的模糊匹配:检查搜索词的字符是否按顺序出现在文本中 + int searchIndex = 0; + foreach (char c in text) + { + if (searchIndex < search.Length && c == search[searchIndex]) + { + searchIndex++; + if (searchIndex == search.Length) + return true; + } + } + return false; + } + + private bool IsRelated(SettingItem setting, string search) + { + // 简单的相关性判断,可以根据需要改进 + // 例如:检查是否有共同的关键词等 + return false; // 暂时禁用相关项功能 + } + + private void UpdateResultsVisibility() + { + ExactMatchPanel.Visibility = _exactMatches.Count > 0 ? Visibility.Visible : Visibility.Collapsed; + FuzzyMatchPanel.Visibility = _fuzzyMatches.Count > 0 ? Visibility.Visible : Visibility.Collapsed; + RelatedItemsPanel.Visibility = _relatedItems.Count > 0 ? Visibility.Visible : Visibility.Collapsed; + + bool hasResults = _exactMatches.Count > 0 || _fuzzyMatches.Count > 0 || _relatedItems.Count > 0; + NoResultsText.Visibility = hasResults ? Visibility.Collapsed : Visibility.Visible; + } + + private void ClearResults() + { + _exactMatches.Clear(); + _fuzzyMatches.Clear(); + _relatedItems.Clear(); + UpdateResultsVisibility(); + } + + private void SearchTextBox_KeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Escape) + { + CloseSearch?.Invoke(this, EventArgs.Empty); + } + } + + private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e) + { + var textBox = sender as TextBox; + if (textBox != null) + { + PerformSearch(textBox.Text); + } + } + + private void SearchTextBox_GotFocus(object sender, RoutedEventArgs e) + { + var textBox = sender as TextBox; + textBox?.SelectAll(); + } + + private void CloseSearchButton_Click(object sender, MouseButtonEventArgs e) + { + CloseSearch?.Invoke(this, EventArgs.Empty); + } + + private void SearchResultItem_Click(object sender, MouseButtonEventArgs e) + { + var border = sender as Border; + if (border?.Tag is SearchResultItem item) + { + NavigateToItem?.Invoke(this, item.ItemName); + } + } + + public void FocusSearchBox() + { + SearchTextBox.Focus(); + } + + public void SetSearchText(string text) + { + SearchTextBox.Text = text; + PerformSearch(text); + } + } + + public class SettingItem + { + public string Title { get; set; } + public string Category { get; set; } + public string ItemName { get; set; } + public string Description { get; set; } = ""; + public SettingItemType Type { get; set; } + } + + public class SearchResultItem + { + public string Title { get; set; } + public string Category { get; set; } + public string ItemName { get; set; } + public SettingItemType Type { get; set; } + public MatchType MatchType { get; set; } + public string Description { get; set; } = ""; + } + + public enum SettingItemType + { + Category, + Setting + } + + public enum MatchType + { + Exact, + Pinyin, + Fuzzy, + Related + } +} + diff --git a/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml b/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml index 08a33133..1a6aba6b 100644 --- a/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml +++ b/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml @@ -622,6 +622,11 @@ + + + + + diff --git a/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs b/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs index b6a99a59..514bf164 100644 --- a/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs +++ b/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs @@ -18,6 +18,10 @@ namespace Ink_Canvas.Windows public SettingsWindow() { InitializeComponent(); + + // 初始化搜索面板事件 + SearchPanelControl.NavigateToItem += SearchPanel_NavigateToItem; + SearchPanelControl.CloseSearch += SearchPanel_CloseSearch; // 初始化侧边栏项目 SidebarItemsControl.ItemsSource = SidebarItems; @@ -445,7 +449,43 @@ namespace Ink_Canvas.Windows private void SearchButton_Click(object sender, MouseButtonEventArgs e) { - // 搜索功能 - 可以显示搜索框或搜索对话框 + // 显示搜索界面 + SearchPane.Visibility = Visibility.Visible; + SearchPanelControl.FocusSearchBox(); + } + + private void SearchPanel_NavigateToItem(object sender, string itemName) + { + // 隐藏搜索界面 + SearchPane.Visibility = Visibility.Collapsed; + + // 导航到对应的设置项 + NavigateToSidebarItem(itemName); + } + + private void SearchPanel_CloseSearch(object sender, EventArgs e) + { + // 隐藏搜索界面 + SearchPane.Visibility = Visibility.Collapsed; + } + + private void NavigateToSidebarItem(string itemName) + { + // 查找对应的侧边栏项并选中 + foreach (var item in SidebarItems) + { + if (item.Name == itemName) + { + SelectSidebarItem(item); + break; + } + } + } + + private void SelectSidebarItem(SidebarItem item) + { + _selectedSidebarItemName = item.Name; + UpdateSidebarItemsSelection(); } private void MenuButton_Click(object sender, MouseButtonEventArgs e)