using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Text; using BITKit; using Godot; using Microsoft.EntityFrameworkCore; using Cysharp.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace BITFactory; public interface ISearchEntry { string Key { get; } string Value { get; } } [Serializable] public class SearchResult:ISearchEntry { [Key] public Guid Guid { get; set; }= Guid.NewGuid(); public string Key { get; set; } public string Value { get; set; } public string Display { get; set; } public string Id { get; set; } public string RegistryRecord { get; set; } public DateTime UpdateDate { get; set; } public DateTime CreateDate { get; set; }=DateTime.Now; public string Correlation { get; set; } } public interface ISearchEngine { SearchResult[] GetSearchResults(string key); void SaveChanges(); void Add(SearchResult result); void Remove(string key, string id); } public partial class SearchEngine:Node,ISearchEngine { private static SqlLiteContext Context; [Export] private Node nodeContainer; [Export] private PackedScene searchEntry; [Export] private LineEdit searchInput; [Export] private Button searchButton; [Export] private MenuButton quickSearchButton; [Export] private ProgressBar searchProgressBar; [Export] private RichTextLabel searchLogLabel; private readonly StringBuilder _logBuilder=new StringBuilder(); private SearchResult[] _currentSearchResults; public override async void _Ready() { BITApp.ServiceCollection.AddSingleton(this); DI.Register(this); try { QueueContainerFree(); await UniTask.SwitchToTaskPool(); Context = new SqlLiteContext(); await Context.Database.EnsureCreatedAsync(); } catch (Exception e) { BIT4Log.LogException(e); } searchButton.Pressed+= Search; searchInput.TextSubmitted += Search; quickSearchButton.Pressed+= QuickSearch; quickSearchButton.GetPopup().AllowSearch = true; quickSearchButton.GetPopup().IdPressed += OnPressedIndex; searchProgressBar.Hide(); } private void Search() { Search(searchInput.Text); } private async void Search(string key) { _logBuilder.AppendLine("正在释放"); QueueContainerFree(); searchProgressBar.Show(); var list = await Context.context.ToListAsync(); var result = (string.IsNullOrEmpty(key) ? list : list.Where(x => x.Key.Contains(key))).ToArray(); //Fallback if (result.Any() is false) { result = list.Where(x => x.Display.Contains(key!)).ToArray(); } if (result.Any() is false) { result = list.Where(x => x.Id.Contains(key!)).ToArray(); } Spawn(result); _logBuilder.AppendLine($"已获取到集合"); _logBuilder.AppendLine($"{string.Join("\n",list)}"); searchProgressBar.Hide(); } private void QuickSearch() { quickSearchButton.GetPopup().Clear(); var enumerable = Context.context.Distinct((x,y)=>x.Key == y.Key); var searchResults = enumerable as SearchResult[] ?? enumerable.ToArray(); _currentSearchResults = searchResults; for (var i = 0; i < searchResults.Length; i++) { var index = i; var element = searchResults[i]; quickSearchButton.GetPopup().AddItem(element.Key); } } private void OnPressedIndex(long index) { var entry = _currentSearchResults[index]; searchInput.Text = entry.Key; Search(entry.Key); } private void Spawn(IEnumerable entries) { foreach (var entry in entries) { var instance = searchEntry.Instantiate(); nodeContainer.AddChild(instance); instance.titleLabel.Text = entry.Display ?? entry.Id ?? entry.Key; instance.Text = entry.Value; instance.updateTimeLabel.Text = entry.UpdateDate.ToString(CultureInfo.InvariantCulture); instance.createTimeLabel.Text = entry.CreateDate.ToString(CultureInfo.InvariantCulture); instance.headerLabel.Text = entry.Key; } } private void QueueContainerFree() { foreach (var x in nodeContainer.GetChildren()) { x.QueueFree(); } } public SearchResult[] GetSearchResults(string key)=>Context.context.Where(x=>x.Key.Contains(key)).ToArray(); public void SaveChanges() => Context.SaveChanges(); public void Add(SearchResult result) { Context.context.Add(result); Context.SaveChanges(); } public void Remove(string key, string id) { throw new NotImplementedException(); } }