diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj
index 3e49bb439..35f307fe7 100644
--- a/src/BiliLite.UWP/BiliLite.UWP.csproj
+++ b/src/BiliLite.UWP/BiliLite.UWP.csproj
@@ -262,16 +262,35 @@
+
+
+
+
+
+
+
+
MarkdownViewerPage.xaml
+
+
+
+
+
+
+
+
+
+
+
@@ -785,7 +804,7 @@
-
+
@@ -940,7 +959,7 @@
-
+
diff --git a/src/BiliLite.UWP/Controls/DataTemplateSelectors/SearchDataTemplateSelector.cs b/src/BiliLite.UWP/Controls/DataTemplateSelectors/SearchDataTemplateSelector.cs
new file mode 100644
index 000000000..0c5f4a49f
--- /dev/null
+++ b/src/BiliLite.UWP/Controls/DataTemplateSelectors/SearchDataTemplateSelector.cs
@@ -0,0 +1,44 @@
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using BiliLite.Models.Common;
+using BiliLite.ViewModels.Search;
+
+namespace BiliLite.Controls.DataTemplateSelectors
+{
+ public class SearchDataTemplateSelector : DataTemplateSelector
+ {
+ public DataTemplate VideoTemplate { get; set; }
+ public DataTemplate AnimeTemplate { get; set; }
+ public DataTemplate TestTemplate { get; set; }
+ public DataTemplate LiveRoomTemplate { get; set; }
+ public DataTemplate UserTemplate { get; set; }
+ public DataTemplate ArticTemplate { get; set; }
+ public DataTemplate TopicTemplate { get; set; }
+ protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
+ {
+ var data = item as ISearchPivotViewModel;
+ switch (data.SearchType)
+ {
+ case SearchType.Video:
+ return VideoTemplate;
+ case SearchType.Anime:
+ case SearchType.Movie:
+ return AnimeTemplate;
+ case SearchType.User:
+ return UserTemplate;
+ case SearchType.Live:
+ return LiveRoomTemplate;
+ case SearchType.Article:
+ return ArticTemplate;
+ case SearchType.Topic:
+ return TopicTemplate;
+ case SearchType.Anchor:
+ return TestTemplate;
+ default:
+ return TestTemplate;
+ }
+
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Extensions/StringHttpExtensions.cs b/src/BiliLite.UWP/Extensions/StringHttpExtensions.cs
index 13af63e53..1fd07da4e 100644
--- a/src/BiliLite.UWP/Extensions/StringHttpExtensions.cs
+++ b/src/BiliLite.UWP/Extensions/StringHttpExtensions.cs
@@ -102,7 +102,7 @@ public static async Task GetHttpResultsWithWebCookie(this string ur
{
foreach (var kvp in extraCookies.ToList())
{
- cookies.Add(kvp.Key, kvp.Value);
+ cookies[kvp.Key] = kvp.Value;
}
}
diff --git a/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs b/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs
index 8cd58aa53..9447e40cf 100644
--- a/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs
+++ b/src/BiliLite.UWP/Extensions/ViewModelExtensions.cs
@@ -5,6 +5,7 @@
using BiliLite.ViewModels.Home;
using BiliLite.ViewModels.Live;
using BiliLite.ViewModels.Rank;
+using BiliLite.ViewModels.Search;
using BiliLite.ViewModels.Settings;
using BiliLite.ViewModels.User;
using BiliLite.ViewModels.User.SendDynamic;
@@ -53,6 +54,7 @@ public static IServiceCollection AddViewModels(this IServiceCollection services)
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
return services;
}
}
diff --git a/src/BiliLite.UWP/Models/Common/Enumerates.cs b/src/BiliLite.UWP/Models/Common/Enumerates.cs
index 5619ef65e..3030c7f0c 100644
--- a/src/BiliLite.UWP/Models/Common/Enumerates.cs
+++ b/src/BiliLite.UWP/Models/Common/Enumerates.cs
@@ -525,4 +525,40 @@ public enum FilterContentType
User,
Desc,
}
+
+ public enum SearchType
+ {
+ ///
+ /// 视频
+ ///
+ Video = 0,
+ ///
+ /// 番剧
+ ///
+ Anime = 1,
+ ///
+ /// 直播
+ ///
+ Live = 2,
+ ///
+ /// 主播
+ ///
+ Anchor = 3,
+ ///
+ /// 用户
+ ///
+ User = 4,
+ ///
+ /// 影视
+ ///
+ Movie = 5,
+ ///
+ /// 专栏
+ ///
+ Article = 6,
+ ///
+ /// 话题
+ ///
+ Topic = 7
+ }
}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Models/Common/Search/SearchAnimeItem.cs b/src/BiliLite.UWP/Models/Common/Search/SearchAnimeItem.cs
new file mode 100644
index 000000000..7cb11725a
--- /dev/null
+++ b/src/BiliLite.UWP/Models/Common/Search/SearchAnimeItem.cs
@@ -0,0 +1,42 @@
+namespace BiliLite.Models.Common.Search
+{
+ public class SearchAnimeItem
+ {
+ public string type { get; set; }
+ public string season_id { get; set; }
+ public string media_id { get; set; }
+ private string _title;
+
+ public string title
+ {
+ get { return _title; }
+ set
+ {
+
+ _title = System.Web.HttpUtility.HtmlDecode(value.Replace("", "").Replace("", ""));
+ }
+ }
+ public string areas { get; set; }
+ public string cv { get; set; }
+ public string styles { get; set; }
+ public string desc { get; set; }
+ public long pubtime { get; set; }
+ public string season_type_name { get; set; }
+
+ private string _pic;
+ public string cover
+ {
+ get { return _pic; }
+ set { _pic = value; }
+ }
+
+ public string angle_title { get; set; }
+ public bool showBadge
+ {
+ get
+ {
+ return !string.IsNullOrEmpty(angle_title);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Models/Common/Search/SearchArea.cs b/src/BiliLite.UWP/Models/Common/Search/SearchArea.cs
new file mode 100644
index 000000000..346ce3f45
--- /dev/null
+++ b/src/BiliLite.UWP/Models/Common/Search/SearchArea.cs
@@ -0,0 +1,13 @@
+namespace BiliLite.Models.Common.Search
+{
+ public class SearchArea
+ {
+ public SearchArea(string name, string area)
+ {
+ this.name = name;
+ this.area = area;
+ }
+ public string name { get; set; }
+ public string area { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Models/Common/Search/SearchArticleItem.cs b/src/BiliLite.UWP/Models/Common/Search/SearchArticleItem.cs
new file mode 100644
index 000000000..572c081d4
--- /dev/null
+++ b/src/BiliLite.UWP/Models/Common/Search/SearchArticleItem.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+
+namespace BiliLite.Models.Common.Search
+{
+ public class SearchArticleItem
+ {
+
+ public string mid { get; set; }
+
+ private string _title;
+
+ public string title
+ {
+ get { return _title; }
+ set
+ {
+ _title = System.Web.HttpUtility.HtmlDecode(value.Replace("", "").Replace("", ""));
+ }
+ }
+ public string category_name { get; set; }
+ public string type { get; set; }
+ public string desc { get; set; }
+ public long like { get; set; }
+ public long view { get; set; }
+ public long reply { get; set; }
+ public string id { get; set; }
+ public List image_urls { get; set; }
+ public string cover
+ {
+ get
+ {
+ if (image_urls != null && image_urls.Count != 0)
+ {
+ return "https:" + image_urls[0];
+ }
+ return null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Models/Common/Search/SearchFilterItem.cs b/src/BiliLite.UWP/Models/Common/Search/SearchFilterItem.cs
new file mode 100644
index 000000000..fca676d54
--- /dev/null
+++ b/src/BiliLite.UWP/Models/Common/Search/SearchFilterItem.cs
@@ -0,0 +1,13 @@
+namespace BiliLite.Models.Common.Search
+{
+ public class SearchFilterItem
+ {
+ public SearchFilterItem(string name, string value)
+ {
+ this.name = name;
+ this.value = value;
+ }
+ public string name { get; set; }
+ public string value { get; set; }
+ }
+}
diff --git a/src/BiliLite.UWP/Models/Common/Search/SearchLiveRoomItem.cs b/src/BiliLite.UWP/Models/Common/Search/SearchLiveRoomItem.cs
new file mode 100644
index 000000000..cbb55f4ef
--- /dev/null
+++ b/src/BiliLite.UWP/Models/Common/Search/SearchLiveRoomItem.cs
@@ -0,0 +1,45 @@
+namespace BiliLite.Models.Common.Search
+{
+ public class SearchLiveRoomItem
+ {
+
+ public string roomid { get; set; }
+
+ private string _title;
+
+ public string title
+ {
+ get { return _title; }
+ set
+ {
+
+ _title = System.Web.HttpUtility.HtmlDecode(value.Replace("", "").Replace("", ""));
+ }
+ }
+ public string uname { get; set; }
+ public string tags { get; set; }
+ public string cate_name { get; set; }
+ public int online { get; set; }
+
+
+ private string _user_cover;
+ public string user_cover
+ {
+ get { return _user_cover; }
+ set { _user_cover = "https:" + value; }
+ }
+ private string _uface;
+ public string uface
+ {
+ get { return _uface; }
+ set { _uface = "https:" + value; }
+ }
+ private string _cover;
+ public string cover
+ {
+ get { return _cover; }
+ set { _cover = "https:" + value; }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Models/Common/Search/SearchParameter.cs b/src/BiliLite.UWP/Models/Common/Search/SearchParameter.cs
new file mode 100644
index 000000000..ddc6eff21
--- /dev/null
+++ b/src/BiliLite.UWP/Models/Common/Search/SearchParameter.cs
@@ -0,0 +1,9 @@
+namespace BiliLite.Models.Common.Search
+{
+ public class SearchParameter
+ {
+ public string Keyword { get; set; }
+
+ public SearchType SearchType { get; set; } = SearchType.Video;
+ }
+}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Models/Common/Search/SearchTopicItem.cs b/src/BiliLite.UWP/Models/Common/Search/SearchTopicItem.cs
new file mode 100644
index 000000000..65ced9217
--- /dev/null
+++ b/src/BiliLite.UWP/Models/Common/Search/SearchTopicItem.cs
@@ -0,0 +1,42 @@
+namespace BiliLite.Models.Common.Search
+{
+ public class SearchTopicItem
+ {
+ public string arcurl { get; set; }
+
+ private string _title;
+
+ public string title
+ {
+ get { return _title; }
+ set
+ {
+ _title = System.Web.HttpUtility.HtmlDecode(value.Replace("", "").Replace("", ""));
+ }
+ }
+
+ private string _description;
+
+ public string description
+ {
+ get { return _description; }
+ set
+ {
+ _description = value.Replace("", "").Replace("", "");
+ }
+ }
+
+
+ public long pubdate { get; set; }
+
+
+ private string _pic;
+ public string cover
+ {
+ get { return _pic; }
+ set { _pic = "https:" + value; }
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Models/Common/Search/SearchUserItem.cs b/src/BiliLite.UWP/Models/Common/Search/SearchUserItem.cs
new file mode 100644
index 000000000..7149e4662
--- /dev/null
+++ b/src/BiliLite.UWP/Models/Common/Search/SearchUserItem.cs
@@ -0,0 +1,58 @@
+namespace BiliLite.Models.Common.Search
+{
+ public class SearchUserItem
+ {
+ public string mid { get; set; }
+ public string uname { get; set; }
+ private string _pic;
+ public string upic
+ {
+ get { return _pic; }
+ set { _pic = "https:" + value; }
+ }
+
+ public int level { get; set; }
+ public int videos { get; set; }
+ public int fans { get; set; }
+ public int is_upuser { get; set; }
+ public string lv
+ {
+ get
+ {
+ return $"ms-appx:///Assets/Icon/lv{level}.png";
+ }
+ }
+ public SearchUserOfficialVerifyItem official_verify { get; set; }
+ public string Verify
+ {
+ get
+ {
+ if (official_verify == null)
+ {
+ return "";
+ }
+ switch (official_verify.type)
+ {
+ case 0:
+ return Constants.App.VERIFY_PERSONAL_IMAGE;
+ case 1:
+ return Constants.App.VERIFY_OGANIZATION_IMAGE;
+ default:
+ return Constants.App.TRANSPARENT_IMAGE;
+ }
+ }
+ }
+ public string usign { get; set; }
+ public string sign
+ {
+ get
+ {
+ if (official_verify != null && !string.IsNullOrEmpty(official_verify.desc))
+ {
+ return official_verify.desc;
+ }
+ return usign;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Models/Common/Search/SearchUserOfficialVerifyItem.cs b/src/BiliLite.UWP/Models/Common/Search/SearchUserOfficialVerifyItem.cs
new file mode 100644
index 000000000..01887fb76
--- /dev/null
+++ b/src/BiliLite.UWP/Models/Common/Search/SearchUserOfficialVerifyItem.cs
@@ -0,0 +1,8 @@
+namespace BiliLite.Models.Common.Search
+{
+ public class SearchUserOfficialVerifyItem
+ {
+ public string desc { get; set; }
+ public int type { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Models/Common/Search/SearchVideoItem.cs b/src/BiliLite.UWP/Models/Common/Search/SearchVideoItem.cs
new file mode 100644
index 000000000..366f8431b
--- /dev/null
+++ b/src/BiliLite.UWP/Models/Common/Search/SearchVideoItem.cs
@@ -0,0 +1,36 @@
+namespace BiliLite.Models.Common.Search
+{
+ public class SearchVideoItem
+ {
+ public string type { get; set; }
+ public string typename { get; set; }
+ public string author { get; set; }
+ public string id { get; set; }
+ public string aid { get; set; }
+ private string _title;
+
+ public string title
+ {
+ get { return _title; }
+ set
+ {
+
+ _title = System.Web.HttpUtility.HtmlDecode(value.Replace("", "").Replace("", ""));
+ }
+ }
+ public string tag { get; set; }
+ public int play { get; set; }
+ public int video_review { get; set; }
+ public int review { get; set; }
+ public int favorites { get; set; }
+ public string duration { get; set; }
+ private string _pic;
+ public string pic
+ {
+ get { return _pic; }
+ set { _pic = "https:" + value; }
+ }
+
+ public string Description { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Modules/SearchVM.cs b/src/BiliLite.UWP/Modules/SearchVM.cs
deleted file mode 100644
index 085e58a35..000000000
--- a/src/BiliLite.UWP/Modules/SearchVM.cs
+++ /dev/null
@@ -1,1073 +0,0 @@
-using BiliLite.Models;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows.Input;
-using BiliLite.Extensions;
-using BiliLite.Models.Common;
-using BiliLite.Models.Exceptions;
-using Newtonsoft.Json;
-using BiliLite.Pages;
-using BiliLite.Models.Requests.Api;
-using BiliLite.Services;
-using Microsoft.Extensions.DependencyInjection;
-
-namespace BiliLite.Modules
-{
- public class ISearchVM : IModules
- {
- public SearchType SearchType { get; set; }
- public SearchAPI searchAPI;
- public ISearchVM()
- {
- searchAPI = new SearchAPI();
- RefreshCommand = new RelayCommand(Refresh);
- LoadMoreCommand = new RelayCommand(LoadMore);
- }
- public string Title { get; set; }
-
- private string _keyword;
- public string Keyword
- {
- get { return _keyword; }
- set { _keyword = value; }
- }
- public ICommand LoadMoreCommand { get; private set; }
- public ICommand RefreshCommand { get; private set; }
-
- public string Area { get; set; } = "";
-
- public int Page { get; set; } = 1;
- private bool _loading = false;
-
- public bool Loading
- {
- get { return _loading; }
- set { _loading = value; DoPropertyChanged("Loading"); }
- }
- private bool _Nothing = false;
- public bool Nothing
- {
- get { return _Nothing; }
- set { _Nothing = value; DoPropertyChanged("Nothing"); }
- }
-
- private bool _ShowLoadMore = false;
- public bool ShowLoadMore
- {
- get { return _ShowLoadMore; }
- set { _ShowLoadMore = value; DoPropertyChanged("ShowLoadMore"); }
- }
-
- public async virtual void Refresh()
- {
- HasData = false;
- Page = 1;
- await LoadData();
- }
- public async virtual void LoadMore()
- {
- await LoadData();
- }
- public bool HasData { get; set; } = false;
-
- public virtual Task LoadData()
- {
- throw new NotImplementedException();
- }
- }
-
- public class SearchVM : IModules
- {
- ///
- /// 搜索请求需要cookie
- ///
- public static string cookie = "";
- public SearchVM()
- {
- Area = Areas[0];
- SearchItems = new ObservableCollection() {
- new SearchVideoVM()
- {
- Title="视频",
- SearchType= SearchType.Video,
- Area= Area.area
- },
- new SearchAnimeVM()
- {
- Title="番剧",
- SearchType= SearchType.Anime,
- Area= Area.area
- },
- new SearchLiveRoomVM()
- {
- Title="直播",
- SearchType= SearchType.Live,
- Area= Area.area
- },
- //new SearchLiveRoomVM()
- //{
- // Title="主播",
- // SearchType= SearchType.Anchor
- //},
- new SearchUserVM()
- {
- Title="用户",
- SearchType= SearchType.User,
- Area= Area.area
- },
- new SearchAnimeVM()
- {
- Title="影视",
- SearchType= SearchType.Movie,
- Area= Area.area
- },
- new SearchArticleVM()
- {
- Title="专栏",
- SearchType= SearchType.Article,
- Area= Area.area
- },
- new SearchTopicVM()
- {
- Title="话题",
- SearchType= SearchType.Topic,
- Area= Area.area
- }
- };
- SelectItem = SearchItems[0];
-
- }
- private ObservableCollection _items;
- public ObservableCollection SearchItems
- {
- get { return _items; }
- set { _items = value; DoPropertyChanged("SearchItems"); }
- }
-
- public List Areas { get; set; } = new List()
- {
- new SearchArea("默认地区",""),
- new SearchArea("大陆地区","cn"),
- new SearchArea("香港地区","hk"),
- new SearchArea("台湾地区","tw"),
- };
- public SearchArea Area { get; set; }
-
- private ISearchVM _SelectItem;
- public ISearchVM SelectItem
- {
- get { return _SelectItem; }
- set { _SelectItem = value; }
- }
-
- private ObservableCollection m_suggestSearchContents;
-
- public ObservableCollection SuggestSearchContents
- {
- get => m_suggestSearchContents;
- set
- {
- m_suggestSearchContents = value;
- DoPropertyChanged("SuggestSearchContents");
- }
- }
- }
- public class SearchVideoVM : ISearchVM
- {
- ILogger _logger = GlobalLogger.FromCurrentType();
- private readonly ContentFilterService m_contentFilterService;
-
- public SearchVideoVM()
- {
- m_contentFilterService = App.ServiceProvider.GetRequiredService();
- OrderFilters = new List() {
- new SearchFilterItem("综合排序",""),
- new SearchFilterItem("最多点击","click"),
- new SearchFilterItem("最新发布","pubdate"),
- new SearchFilterItem("最多弹幕","dm"),
- new SearchFilterItem("最多收藏","stow")
- };
- SelectOrder = OrderFilters[0];
- DurationFilters = new List() {
- new SearchFilterItem("全部时长",""),
- new SearchFilterItem("10分钟以下","1"),
- new SearchFilterItem("10-30分钟","2"),
- new SearchFilterItem("30-60分钟","3"),
- new SearchFilterItem("60分钟以上","4")
- };
- SelectDuration = DurationFilters[0];
- RegionFilters = new List() {
- new SearchFilterItem("全部分区","0"),
- };
- foreach (var item in AppHelper.Regions.Where(x => x.children != null && x.children.Count != 0))
- {
- RegionFilters.Add(new SearchFilterItem(item.name, item.tid.ToString()));
- }
- SelectRegion = RegionFilters[0];
- }
- public List OrderFilters { get; set; }
-
- private SearchFilterItem _SelectOrder;
- public SearchFilterItem SelectOrder
- {
- get { return _SelectOrder; }
- set { _SelectOrder = value; }
- }
-
- public List DurationFilters { get; set; }
-
- private SearchFilterItem _SelectDuration;
- public SearchFilterItem SelectDuration
- {
- get { return _SelectDuration; }
- set { _SelectDuration = value; }
- }
- public List RegionFilters { get; set; }
- private SearchFilterItem _SelectRegion;
- public SearchFilterItem SelectRegion
- {
- get { return _SelectRegion; }
- set { _SelectRegion = value; }
- }
-
-
- private ObservableCollection _videos;
- public ObservableCollection Videos
- {
- get { return _videos; }
- set { _videos = value; DoPropertyChanged("Videos"); }
- }
-
- public async override Task LoadData()
- {
- try
- {
- if (Loading)
- {
- return;
- }
- ShowLoadMore = false;
- Loading = true;
- Nothing = false;
- var results = await searchAPI.WebSearchVideo(Keyword, Page, SelectOrder.value, SelectDuration.value, SelectRegion.value, Area).Request();
- if (!results.status)
- {
- throw new CustomizedErrorException(results.message);
- }
- var data = await results.GetJson>();
- if (!data.success)
- {
- throw new CustomizedErrorException(data.message);
- }
- var searchVideoItems = JsonConvert.DeserializeObject>(data.data["result"]?.ToString() ?? "[]");
- searchVideoItems = m_contentFilterService.FilterSearchItems(searchVideoItems);
- var result = new ObservableCollection(searchVideoItems);
-
- if (Page == 1)
- {
- if (result == null || result.Count == 0)
- {
- Nothing = true;
- Videos?.Clear();
- return;
- }
- Videos = result;
- }
- else if (data.data != null)
- {
- foreach (var item in result)
- {
- Videos.Add(item);
- }
- }
- if (Page < data.data["numPages"].ToInt32())
- {
- ShowLoadMore = true;
- Page++;
- }
- HasData = true;
-
- }
- catch (Exception ex)
- {
- if (ex is CustomizedErrorException customizedErrorException)
- {
- Notify.ShowMessageToast(ex.Message);
- _logger.Error("搜索失败", ex);
- }
-
- var handel = HandelError(ex);
- Notify.ShowMessageToast(handel.message);
- }
- finally
- {
- Loading = false;
- }
- }
- }
-
- public class SearchArticleVM : ISearchVM
- {
- public SearchArticleVM()
- {
- OrderFilters = new List() {
- new SearchFilterItem("默认排序","totalrank"),
- new SearchFilterItem("最多阅读","click"),
- new SearchFilterItem("最新发布","pubdate"),
- new SearchFilterItem("最多喜欢","attention"),
- new SearchFilterItem("最多评论","scores")
- };
- SelectOrder = OrderFilters[0];
-
- RegionFilters = new List() {
- new SearchFilterItem("全部分区","0"),
- new SearchFilterItem("动画","2"),
- new SearchFilterItem("游戏","1"),
- new SearchFilterItem("影视","28"),
- new SearchFilterItem("生活","3"),
- new SearchFilterItem("兴趣","29"),
- new SearchFilterItem("轻小说","16"),
- new SearchFilterItem("科技","17"),
- };
-
- SelectRegion = RegionFilters[0];
- }
- public List OrderFilters { get; set; }
-
- private SearchFilterItem _SelectOrder;
- public SearchFilterItem SelectOrder
- {
- get { return _SelectOrder; }
- set { _SelectOrder = value; }
- }
-
- public List DurationFilters { get; set; }
-
-
- public List RegionFilters { get; set; }
- private SearchFilterItem _SelectRegion;
- public SearchFilterItem SelectRegion
- {
- get { return _SelectRegion; }
- set { _SelectRegion = value; }
- }
-
-
- private ObservableCollection _Articles;
- public ObservableCollection Articles
- {
- get { return _Articles; }
- set { _Articles = value; DoPropertyChanged("Articles"); }
- }
-
- public async override Task LoadData()
- {
- try
- {
- if (Loading)
- {
- return;
- }
- ShowLoadMore = false;
- Loading = true;
- Nothing = false;
- var results = await searchAPI.WebSearchArticle(Keyword, Page, SelectOrder.value, SelectRegion.value, Area).Request();
- if (results.status)
- {
- var data = await results.GetJson>();
- if (data.success)
- {
- var result = JsonConvert.DeserializeObject>(data.data["result"]?.ToString() ?? "[]");
- if (Page == 1)
- {
- if (result == null || result.Count == 0)
- {
- Nothing = true;
- Articles?.Clear();
- return;
- }
- Articles = result;
- }
- else
- {
- if (data.data != null)
- {
- foreach (var item in result)
- {
- Articles.Add(item);
- }
- }
- }
- if (Page < data.data["numPages"].ToInt32())
- {
- ShowLoadMore = true;
- Page++;
- }
- HasData = true;
- }
- else
- {
- Notify.ShowMessageToast(data.message);
- }
- }
- else
- {
- Notify.ShowMessageToast(results.message);
- }
- }
- catch (Exception ex)
- {
- var handel = HandelError(ex);
- Notify.ShowMessageToast(handel.message);
- }
- finally
- {
- Loading = false;
- }
- }
-
-
- }
- public class SearchAnimeVM : ISearchVM
- {
- public SearchAnimeVM()
- {
- }
-
- private ObservableCollection _Animes;
- public ObservableCollection Animes
- {
- get { return _Animes; }
- set { _Animes = value; DoPropertyChanged("Animes"); }
- }
-
- public async override Task LoadData()
- {
- try
- {
- if (Loading)
- {
- return;
- }
- ShowLoadMore = false;
- Loading = true;
- Nothing = false;
- var api = searchAPI.WebSearchAnime(Keyword, Page, Area);
- if (this.SearchType == SearchType.Movie)
- {
- api = searchAPI.WebSearchMovie(Keyword, Page, Area);
- }
- var results = await api.Request();
- if (results.status)
- {
- var data = await results.GetJson>();
- if (data.success)
- {
-
- var result = JsonConvert.DeserializeObject>(data.data["result"]?.ToString() ?? "[]");
- if (Page == 1)
- {
- if (result == null || result.Count == 0)
- {
- Nothing = true;
- Animes?.Clear();
- return;
- }
- Animes = result;
- }
- else
- {
- if (data.data != null)
- {
- foreach (var item in result)
- {
- Animes.Add(item);
- }
- }
- }
- if (Page < data.data["numPages"].ToInt32())
- {
- ShowLoadMore = true;
- Page++;
- }
- HasData = true;
- }
- else
- {
- Notify.ShowMessageToast(data.message);
- }
- }
- else
- {
- Notify.ShowMessageToast(results.message);
- }
- }
- catch (Exception ex)
- {
- var handel = HandelError(ex);
- Notify.ShowMessageToast(handel.message);
- }
- finally
- {
- Loading = false;
- }
- }
-
-
- }
- public class SearchUserVM : ISearchVM
- {
- public SearchUserVM()
- {
- OrderFilters = new List() {
- new SearchFilterItem("默认排序","&order=&order_sort="),
- new SearchFilterItem("粉丝数由高到低","&order=fans&order_sort=0"),
- new SearchFilterItem("粉丝数由低到高","&order=fans&order_sort=1"),
- new SearchFilterItem("LV等级由高到低","&order=level&order_sort=0"),
- new SearchFilterItem("LV等级由低到高","&order=level&order_sort=1"),
- };
- SelectOrder = OrderFilters[0];
- TypeFilters = new List() {
- new SearchFilterItem("全部用户","&user_type=0"),
- new SearchFilterItem("UP主","&user_type=1"),
- new SearchFilterItem("普通用户","&user_type=2"),
- new SearchFilterItem("认证用户","&user_type=3")
- };
- SelectType = TypeFilters[0];
-
- }
- public List OrderFilters { get; set; }
-
- private SearchFilterItem _SelectOrder;
- public SearchFilterItem SelectOrder
- {
- get { return _SelectOrder; }
- set { _SelectOrder = value; }
- }
-
- public List TypeFilters { get; set; }
-
- private SearchFilterItem _SelectType;
- public SearchFilterItem SelectType
- {
- get { return _SelectType; }
- set { _SelectType = value; }
- }
-
-
- private ObservableCollection _users;
- public ObservableCollection Users
- {
- get { return _users; }
- set { _users = value; DoPropertyChanged("Users"); }
- }
-
- public async override Task LoadData()
- {
- try
- {
- if (Loading)
- {
- return;
- }
- ShowLoadMore = false;
- Loading = true;
- Nothing = false;
- var results = await searchAPI.WebSearchUser(Keyword, Page, SelectOrder.value, SelectType.value, Area).Request();
- if (results.status)
- {
- var data = await results.GetJson>();
- if (data.success)
- {
- var result = JsonConvert.DeserializeObject>(data.data["result"]?.ToString() ?? "[]");
- if (Page == 1)
- {
- if (result == null || result.Count == 0)
- {
- Nothing = true;
- Users?.Clear();
- return;
- }
- Users = result;
- }
- else
- {
- if (data.data != null)
- {
- foreach (var item in result)
- {
- Users.Add(item);
- }
- }
- }
- if (Page < data.data["numPages"].ToInt32())
- {
- ShowLoadMore = true;
- Page++;
- }
- HasData = true;
- }
- else
- {
- Notify.ShowMessageToast(data.message);
- }
- }
- else
- {
- Notify.ShowMessageToast(results.message);
- }
- }
- catch (Exception ex)
- {
- var handel = HandelError(ex);
- Notify.ShowMessageToast(handel.message);
- }
- finally
- {
- Loading = false;
- }
- }
-
-
- }
- public class SearchLiveRoomVM : ISearchVM
- {
- public SearchLiveRoomVM()
- {
- }
-
- private ObservableCollection _Rooms;
- public ObservableCollection Rooms
- {
- get { return _Rooms; }
- set { _Rooms = value; DoPropertyChanged("Rooms"); }
- }
-
- public async override Task LoadData()
- {
- try
- {
- if (Loading)
- {
- return;
- }
- ShowLoadMore = false;
- Loading = true;
- Nothing = false;
-
- var results = await searchAPI.WebSearchLive(Keyword, Page, Area).Request();
- if (results.status)
- {
- var data = await results.GetJson>();
- if (data.success)
- {
-
- var result = JsonConvert.DeserializeObject>(data.data["result"]["live_room"]?.ToString() ?? "[]");
- if (Page == 1)
- {
- if (result == null || result.Count == 0)
- {
- Nothing = true;
- Rooms?.Clear();
- return;
- }
- Rooms = result;
- }
- else
- {
- if (data.data != null)
- {
- foreach (var item in result)
- {
- Rooms.Add(item);
- }
- }
- }
- if (Page < data.data["pageinfo"]["live_room"]["numPages"].ToInt32())
- {
- ShowLoadMore = true;
- Page++;
- }
- HasData = true;
- }
- else
- {
- Notify.ShowMessageToast(data.message);
- }
- }
- else
- {
- Notify.ShowMessageToast(results.message);
- }
- }
- catch (Exception ex)
- {
- var handel = HandelError(ex);
- Notify.ShowMessageToast(handel.message);
- }
- finally
- {
- Loading = false;
- }
- }
-
-
- }
- public class SearchTopicVM : ISearchVM
- {
- public SearchTopicVM()
- {
- }
-
- private ObservableCollection _Topics;
- public ObservableCollection Topics
- {
- get { return _Topics; }
- set { _Topics = value; DoPropertyChanged("Topics"); }
- }
-
- public async override Task LoadData()
- {
- try
- {
- if (Loading)
- {
- return;
- }
- ShowLoadMore = false;
- Loading = true;
- Nothing = false;
- var results = await searchAPI.WebSearchTopic(Keyword, Page, Area).Request();
- if (results.status)
- {
- var data = await results.GetJson>();
- if (data.success)
- {
-
- var result = JsonConvert.DeserializeObject>(data.data["result"]?.ToString() ?? "[]");
- if (Page == 1)
- {
- if (result == null || result.Count == 0)
- {
- Nothing = true;
- Topics?.Clear();
- return;
- }
- Topics = result;
- }
- else
- {
- if (data.data != null)
- {
- foreach (var item in result)
- {
- Topics.Add(item);
- }
- }
- }
- if (Page < data.data["numPages"].ToInt32())
- {
- ShowLoadMore = true;
- Page++;
- }
- HasData = true;
- }
- else
- {
- Notify.ShowMessageToast(data.message);
- }
- }
- else
- {
- Notify.ShowMessageToast(results.message);
- }
- }
- catch (Exception ex)
- {
- var handel = HandelError(ex);
- Notify.ShowMessageToast(handel.message);
- }
- finally
- {
- Loading = false;
- }
- }
-
-
- }
-
- public class SearchFilterItem
- {
- public SearchFilterItem(string name, string value)
- {
- this.name = name;
- this.value = value;
- }
- public string name { get; set; }
- public string value { get; set; }
- }
-
- public class SearchArea
- {
- public SearchArea(string name, string area)
- {
- this.name = name;
- this.area = area;
- }
- public string name { get; set; }
- public string area { get; set; }
- }
- public class SearchVideoItem
- {
- public string type { get; set; }
- public string typename { get; set; }
- public string author { get; set; }
- public string id { get; set; }
- public string aid { get; set; }
- private string _title;
-
- public string title
- {
- get { return _title; }
- set
- {
-
- _title = System.Web.HttpUtility.HtmlDecode(value.Replace("", "").Replace("", ""));
- }
- }
- public string tag { get; set; }
- public int play { get; set; }
- public int video_review { get; set; }
- public int review { get; set; }
- public int favorites { get; set; }
- public string duration { get; set; }
- private string _pic;
- public string pic
- {
- get { return _pic; }
- set { _pic = "https:" + value; }
- }
-
- public string Description { get; set; }
- }
- public class SearchAnimeItem
- {
- public string type { get; set; }
- public string season_id { get; set; }
- public string media_id { get; set; }
- private string _title;
-
- public string title
- {
- get { return _title; }
- set
- {
-
- _title = System.Web.HttpUtility.HtmlDecode(value.Replace("", "").Replace("", ""));
- }
- }
- public string areas { get; set; }
- public string cv { get; set; }
- public string styles { get; set; }
- public string desc { get; set; }
- public long pubtime { get; set; }
- public string season_type_name { get; set; }
-
- private string _pic;
- public string cover
- {
- get { return _pic; }
- set { _pic = value; }
- }
-
- public string angle_title { get; set; }
- public bool showBadge
- {
- get
- {
- return !string.IsNullOrEmpty(angle_title);
- }
- }
- }
-
- public class SearchUserItem
- {
- public string mid { get; set; }
- public string uname { get; set; }
- private string _pic;
- public string upic
- {
- get { return _pic; }
- set { _pic = "https:" + value; }
- }
-
- public int level { get; set; }
- public int videos { get; set; }
- public int fans { get; set; }
- public int is_upuser { get; set; }
- public string lv
- {
- get
- {
- return $"ms-appx:///Assets/Icon/lv{level}.png";
- }
- }
- public SearchUserOfficialVerifyItem official_verify { get; set; }
- public string Verify
- {
- get
- {
- if (official_verify == null)
- {
- return "";
- }
- switch (official_verify.type)
- {
- case 0:
- return Constants.App.VERIFY_PERSONAL_IMAGE;
- case 1:
- return Constants.App.VERIFY_OGANIZATION_IMAGE;
- default:
- return Constants.App.TRANSPARENT_IMAGE;
- }
- }
- }
- public string usign { get; set; }
- public string sign
- {
- get
- {
- if (official_verify != null && !string.IsNullOrEmpty(official_verify.desc))
- {
- return official_verify.desc;
- }
- return usign;
- }
- }
- }
- public class SearchLiveRoomItem
- {
-
- public string roomid { get; set; }
-
- private string _title;
-
- public string title
- {
- get { return _title; }
- set
- {
-
- _title = System.Web.HttpUtility.HtmlDecode(value.Replace("", "").Replace("", ""));
- }
- }
- public string uname { get; set; }
- public string tags { get; set; }
- public string cate_name { get; set; }
- public int online { get; set; }
-
-
- private string _user_cover;
- public string user_cover
- {
- get { return _user_cover; }
- set { _user_cover = "https:" + value; }
- }
- private string _uface;
- public string uface
- {
- get { return _uface; }
- set { _uface = "https:" + value; }
- }
- private string _cover;
- public string cover
- {
- get { return _cover; }
- set { _cover = "https:" + value; }
- }
-
- }
- public class SearchUserOfficialVerifyItem
- {
- public string desc { get; set; }
- public int type { get; set; }
- }
- public class SearchArticleItem
- {
-
- public string mid { get; set; }
-
- private string _title;
-
- public string title
- {
- get { return _title; }
- set
- {
- _title = System.Web.HttpUtility.HtmlDecode(value.Replace("", "").Replace("", ""));
- }
- }
- public string category_name { get; set; }
- public string type { get; set; }
- public string desc { get; set; }
- public long like { get; set; }
- public long view { get; set; }
- public long reply { get; set; }
- public string id { get; set; }
- public List image_urls { get; set; }
- public string cover
- {
- get
- {
- if (image_urls != null && image_urls.Count != 0)
- {
- return "https:" + image_urls[0];
- }
- return null;
- }
- }
- }
- public class SearchTopicItem
- {
- public string arcurl { get; set; }
-
- private string _title;
-
- public string title
- {
- get { return _title; }
- set
- {
- _title = System.Web.HttpUtility.HtmlDecode(value.Replace("", "").Replace("", ""));
- }
- }
-
- private string _description;
-
- public string description
- {
- get { return _description; }
- set
- {
- _description = value.Replace("", "").Replace("", "");
- }
- }
-
-
- public long pubdate { get; set; }
-
-
- private string _pic;
- public string cover
- {
- get { return _pic; }
- set { _pic = "https:" + value; }
- }
-
-
- }
-}
diff --git a/src/BiliLite.UWP/Pages/HomePage.xaml.cs b/src/BiliLite.UWP/Pages/HomePage.xaml.cs
index 34068a7af..175b54ce9 100644
--- a/src/BiliLite.UWP/Pages/HomePage.xaml.cs
+++ b/src/BiliLite.UWP/Pages/HomePage.xaml.cs
@@ -8,6 +8,8 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
+using BiliLite.Models.Common.Search;
+using BiliLite.Services.Biz;
using BiliLite.ViewModels.Download;
using BiliLite.ViewModels.Home;
using Microsoft.Extensions.DependencyInjection;
@@ -24,6 +26,8 @@ public sealed partial class HomePage : BasePage, IRefreshablePage, IScrollRecove
private static readonly ILogger logger = GlobalLogger.FromCurrentType();
private readonly DownloadPageViewModel m_downloadPageViewModel;
+
+ private readonly SearchService m_searchService;
// private readonly CookieService m_cookieService;
private readonly HomeViewModel m_viewModel;
readonly Account account;
@@ -36,6 +40,7 @@ public HomePage()
m_viewModel = new HomeViewModel();
account = new Account();
m_downloadPageViewModel = App.ServiceProvider.GetRequiredService();
+ m_searchService = App.ServiceProvider.GetRequiredService();
// m_cookieService = App.ServiceProvider.GetRequiredService();
this.DataContext = m_viewModel;
}
@@ -188,8 +193,8 @@ private async void SearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBo
title = "搜索:" + args.QueryText,
parameters = new SearchParameter()
{
- keyword = args.QueryText,
- searchType = SearchType.Video
+ Keyword = args.QueryText,
+ SearchType = SearchType.Video
}
});
}
@@ -332,7 +337,7 @@ private async void SearchBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTe
var text = sender.Text;
text = text.TrimEnd();
if (string.IsNullOrWhiteSpace(text)) return;
- var suggestSearchContents = await new SearchService().GetSearchSuggestContents(text);
+ var suggestSearchContents = await m_searchService.GetSearchSuggestContents(text);
if (m_viewModel.SuggestSearchContents == null)
{
m_viewModel.SuggestSearchContents = new System.Collections.ObjectModel.ObservableCollection(suggestSearchContents);
diff --git a/src/BiliLite.UWP/Pages/NewPage.xaml.cs b/src/BiliLite.UWP/Pages/NewPage.xaml.cs
index 52ced345d..229ebb3db 100644
--- a/src/BiliLite.UWP/Pages/NewPage.xaml.cs
+++ b/src/BiliLite.UWP/Pages/NewPage.xaml.cs
@@ -1,7 +1,6 @@
using BiliLite.Pages.Bangumi;
using Microsoft.UI.Xaml.Controls;
using System;
-using System.IO;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
@@ -11,6 +10,7 @@
using BiliLite.Models.Common;
using BiliLite.Services;
using BiliLite.Extensions;
+using BiliLite.Models.Common.Search;
using NavigationView = Microsoft.UI.Xaml.Controls.NavigationView;
// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板
@@ -100,8 +100,8 @@ private async void SearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBo
title = "搜索:" + SearchBox.Text,
parameters = new SearchParameter()
{
- keyword = SearchBox.Text,
- searchType = SearchType.Video
+ Keyword = SearchBox.Text,
+ SearchType = SearchType.Video
}
});
}
diff --git a/src/BiliLite.UWP/Pages/SearchPage.xaml b/src/BiliLite.UWP/Pages/SearchPage.xaml
index 51ee5b10d..3567d82a2 100644
--- a/src/BiliLite.UWP/Pages/SearchPage.xaml
+++ b/src/BiliLite.UWP/Pages/SearchPage.xaml
@@ -2,114 +2,233 @@
x:Class="BiliLite.Pages.SearchPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="using:BiliLite.Pages"
+ xmlns:control="using:BiliLite.Controls"
+ xmlns:convert="using:BiliLite.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d"
xmlns:fa="using:FontAwesome5"
- xmlns:toolkit="using:Microsoft.Toolkit.Uwp.UI.Controls"
- xmlns:convert="using:BiliLite.Converters"
+ xmlns:local="using:BiliLite.Pages"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:modules="using:BiliLite.Modules"
- xmlns:control="using:BiliLite.Controls"
+ xmlns:toolkit="using:Microsoft.Toolkit.Uwp.UI.Controls"
+ xmlns:dataTemplateSelectors="using:BiliLite.Controls.DataTemplateSelectors"
+ xmlns:viewModel="using:BiliLite.ViewModels.Search"
+ xmlns:model="using:BiliLite.Models.Common.Search"
Background="Transparent"
- Loaded="SearchPage_Loaded">
+ SizeChanged="SearchPage_OnSizeChanged"
+ mc:Ignorable="d">
-
-
-
-
+
+
+
+
-
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
- UP:
- 播放: 弹幕:
+
+
+
+ UP:
+
+ 播放:
+ 弹幕:
-
+
加载更多
-
+
- 什么都没有找到呢~
-
-
+
+ 什么都没有找到呢~
+
+
+
-
+
-
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
- 类型:
- 地区:
- 风格:
- 开播时间:
+
+
+
+ 类型:
+
+ 地区:
+
+ 风格:
+
+ 开播时间:
@@ -117,62 +236,121 @@
-
+
加载更多
-
+
- 什么都没有找到呢~
-
-
+
+ 什么都没有找到呢~
+
+
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
-
- 稿件: 粉丝:
-
+
+
+
+ 稿件:
+ 粉丝:
+
@@ -181,250 +359,441 @@
-
+
加载更多
-
+
- 什么都没有找到呢~
-
-
+
+ 什么都没有找到呢~
+
+
+
-
+
-
+
-
+
-
+
-
-
-
+
+
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
- 人气:
+
+
+ 人气:
-
+
加载更多
-
+
- 什么都没有找到呢~
-
-
+
+ 什么都没有找到呢~
+
+
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
-
+
+
-
+
-
-
- 阅读: 评论: 喜欢:
- 分区:
+
+
+
+ 阅读:
+ 评论:
+ 喜欢:
+
+ 分区:
-
+
加载更多
-
+
- 什么都没有找到呢~
-
-
+
+ 什么都没有找到呢~
+
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
-
-
- 时间:
+
+
+
+
+ 时间:
-
+
加载更多
-
+
- 什么都没有找到呢~
-
-
+
+ 什么都没有找到呢~
+
+
+
还没写好
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
默认地区
大陆地区
香港地区
台湾地区
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/BiliLite.UWP/Pages/SearchPage.xaml.cs b/src/BiliLite.UWP/Pages/SearchPage.xaml.cs
index 8a454819f..f78b00b7f 100644
--- a/src/BiliLite.UWP/Pages/SearchPage.xaml.cs
+++ b/src/BiliLite.UWP/Pages/SearchPage.xaml.cs
@@ -7,66 +7,39 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
+using BiliLite.Models.Common.Search;
+using BiliLite.Services.Biz;
+using BiliLite.ViewModels.Search;
+using Microsoft.Extensions.DependencyInjection;
+using System.Linq;
+using Windows.UI.Xaml.Controls.Primitives;
// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板
namespace BiliLite.Pages
{
- public enum SearchType
- {
- ///
- /// 视频
- ///
- Video = 0,
- ///
- /// 番剧
- ///
- Anime = 1,
- ///
- /// 直播
- ///
- Live = 2,
- ///
- /// 主播
- ///
- Anchor = 3,
- ///
- /// 用户
- ///
- User = 4,
- ///
- /// 影视
- ///
- Movie = 5,
- ///
- /// 专栏
- ///
- Article = 6,
- ///
- /// 话题
- ///
- Topic = 7
- }
- public class SearchParameter
- {
- public string keyword { get; set; }
- public SearchType searchType { get; set; } = SearchType.Video;
- }
///
/// 可用于自身或导航至 Frame 内部的空白页。
///
public sealed partial class SearchPage : BasePage, IRefreshablePage
{
- SearchVM searchVM;
+ private readonly SearchService m_searchService;
+ private readonly SearchPageViewModel m_viewModel;
+
public SearchPage()
{
+ NavigationCacheMode = NavigationCacheMode.Required;
+ m_searchService = App.ServiceProvider.GetRequiredService();
+ m_viewModel = App.ServiceProvider.GetRequiredService();
+ m_viewModel.Init(m_searchService.PivotIndexCache = 0, m_searchService.ComboIndexCache = 0);
this.InitializeComponent();
- Title = "搜索";
- searchVM = new SearchVM();
}
+
protected override void OnNavigatedTo(NavigationEventArgs e)
{
+ CompositionTarget.Rendered += CompositionTarget_Rendered; // 订阅页面加载后事件
base.OnNavigatedTo(e);
SearchParameter par = new SearchParameter();
if (e.Parameter is SearchParameter)
@@ -75,18 +48,22 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
}
else
{
- par.keyword = e.Parameter.ToString();
+ par.Keyword = e.Parameter.ToString();
}
- par.keyword = par.keyword.TrimStart('@');
- txtKeyword.Text = par.keyword;
- foreach (var item in searchVM.SearchItems)
+ par.Keyword = par.Keyword.TrimStart('@');
+ txtKeyword.Text = par.Keyword;
+ foreach (var item in m_viewModel.SearchItems)
{
- item.Keyword = par.keyword;
- item.Area = searchVM.Area.area;
+ item.Keyword = par.Keyword;
+ item.Area = m_viewModel.Area.area;
}
- pivot.SelectedIndex = (int)par.searchType;
}
-
+ private void CompositionTarget_Rendered(object sender, RenderedEventArgs e)
+ {
+ txtKeyword.Focus(FocusState.Keyboard);
+ Title = "搜索";
+ CompositionTarget.Rendered -= CompositionTarget_Rendered;
+ }
private async void txtKeyword_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
var queryText = args.QueryText;
@@ -101,14 +78,14 @@ private async void txtKeyword_QuerySubmitted(AutoSuggestBox sender, AutoSuggestB
return;
}
queryText = queryText.TrimStart('@');
- foreach (var item in searchVM.SearchItems)
+ foreach (var item in m_viewModel.SearchItems)
{
item.Keyword = queryText;
- item.Area = searchVM.Area.area;
+ item.Area = m_viewModel.Area.area;
item.Page = 1;
item.HasData = false;
}
- searchVM.SelectItem.Refresh();
+ m_viewModel.SelectItem.Refresh();
ChangeTitle("搜索:" + queryText);
}
@@ -130,7 +107,8 @@ private async void pivot_SelectionChanged(object sender, SelectionChangedEventAr
{
if (pivot.SelectedItem != null)
{
- var item = pivot.SelectedItem as ISearchVM;
+ m_searchService.PivotIndexCache = pivot.SelectedIndex;
+ var item = pivot.SelectedItem as ISearchPivotViewModel;
if (!item.HasData && !item.Loading)
{
await item.LoadData();
@@ -141,7 +119,7 @@ private async void pivot_SelectionChanged(object sender, SelectionChangedEventAr
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
- var data = (sender as ComboBox).DataContext as ISearchVM;
+ var data = (sender as ComboBox).DataContext as ISearchPivotViewModel;
if (data.HasData && !data.Loading)
{
data.Refresh();
@@ -246,13 +224,14 @@ private void cbArea_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (cbArea.SelectedItem != null)
{
- foreach (var item in searchVM.SearchItems)
+ m_searchService.ComboIndexCache = cbArea.SelectedIndex;
+ foreach (var item in m_viewModel.SearchItems)
{
- item.Area = searchVM.Area.area;
+ item.Area = m_viewModel.Area.area;
item.Page = 1;
item.HasData = false;
}
- searchVM.SelectItem.Refresh();
+ m_viewModel.SelectItem.Refresh();
}
}
@@ -262,62 +241,33 @@ private async void txtKeyword_TextChanged(AutoSuggestBox sender, AutoSuggestBoxT
var text = sender.Text;
text = text.TrimEnd();
if (string.IsNullOrWhiteSpace(text)) return;
- var suggestSearchContents = await new SearchService().GetSearchSuggestContents(text);
- if (searchVM.SuggestSearchContents == null)
+ var suggestSearchContents = await m_searchService.GetSearchSuggestContents(text);
+ if (m_viewModel.SuggestSearchContents == null)
{
- searchVM.SuggestSearchContents = new System.Collections.ObjectModel.ObservableCollection(suggestSearchContents);
+ m_viewModel.SuggestSearchContents = new System.Collections.ObjectModel.ObservableCollection(suggestSearchContents);
}
else
{
- searchVM.SuggestSearchContents.ReplaceRange(suggestSearchContents);
+ m_viewModel.SuggestSearchContents.ReplaceRange(suggestSearchContents);
}
}
public async Task Refresh()
{
- if (!(pivot.SelectedItem is ISearchVM searchVm)) return;
+ if (!(pivot.SelectedItem is ISearchPivotViewModel searchVm)) return;
searchVm.Refresh();
}
- private void SearchPage_Loaded(object sender, RoutedEventArgs e)
+ private void UpdateSize()
{
- txtKeyword.Focus(FocusState.Keyboard);
+ m_viewModel.PageWidth = ActualWidth;
+ m_viewModel.PivotHeaderWidth =
+ pivot.FindChildrenByType().Select(x=>x.ActualWidth).Sum();
}
- }
- public class SearchDataTemplateSelector : DataTemplateSelector
- {
- public DataTemplate VideoTemplate { get; set; }
- public DataTemplate AnimeTemplate { get; set; }
- public DataTemplate TestTemplate { get; set; }
- public DataTemplate LiveRoomTemplate { get; set; }
- public DataTemplate UserTemplate { get; set; }
- public DataTemplate ArticTemplate { get; set; }
- public DataTemplate TopicTemplate { get; set; }
- protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
- {
- var data = item as ISearchVM;
- switch (data.SearchType)
- {
- case SearchType.Video:
- return VideoTemplate;
- case SearchType.Anime:
- case SearchType.Movie:
- return AnimeTemplate;
- case SearchType.User:
- return UserTemplate;
- case SearchType.Live:
- return LiveRoomTemplate;
- case SearchType.Article:
- return ArticTemplate;
- case SearchType.Topic:
- return TopicTemplate;
- case SearchType.Anchor:
- return TestTemplate;
- default:
- return TestTemplate;
- }
-
+ private void SearchPage_OnSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ UpdateSize();
}
}
}
diff --git a/src/BiliLite.UWP/Services/SearchService.cs b/src/BiliLite.UWP/Services/Biz/SearchService.cs
similarity index 80%
rename from src/BiliLite.UWP/Services/SearchService.cs
rename to src/BiliLite.UWP/Services/Biz/SearchService.cs
index 67ad099d5..9b3c6d2c5 100644
--- a/src/BiliLite.UWP/Services/SearchService.cs
+++ b/src/BiliLite.UWP/Services/Biz/SearchService.cs
@@ -1,14 +1,18 @@
-using BiliLite.Extensions;
-using BiliLite.Models.Requests.Api;
-using BiliLite.Models.Responses;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using BiliLite.Extensions;
+using BiliLite.Models.Requests.Api;
+using BiliLite.Models.Responses;
-namespace BiliLite.Services
+namespace BiliLite.Services.Biz
{
public class SearchService
{
+ public int PivotIndexCache { get; set; }
+
+ public int ComboIndexCache { get; set; }
+
public async Task> GetSearchSuggestContents(string text)
{
if (string.IsNullOrWhiteSpace(text)) return null;
diff --git a/src/BiliLite.UWP/Services/ContentFilterService.cs b/src/BiliLite.UWP/Services/ContentFilterService.cs
index 1d0c009e7..6061e8a4e 100644
--- a/src/BiliLite.UWP/Services/ContentFilterService.cs
+++ b/src/BiliLite.UWP/Services/ContentFilterService.cs
@@ -3,8 +3,8 @@
using System.Text.RegularExpressions;
using BiliLite.Models.Common;
using BiliLite.Models.Common.Recommend;
+using BiliLite.Models.Common.Search;
using BiliLite.Models.Common.Settings;
-using BiliLite.Modules;
using BiliLite.ViewModels.UserDynamic;
namespace BiliLite.Services
diff --git a/src/BiliLite.UWP/Startup.cs b/src/BiliLite.UWP/Startup.cs
index ce163e64c..1745f0fac 100644
--- a/src/BiliLite.UWP/Startup.cs
+++ b/src/BiliLite.UWP/Startup.cs
@@ -1,5 +1,6 @@
using BiliLite.Extensions;
using BiliLite.Services;
+using BiliLite.Services.Biz;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@@ -28,6 +29,7 @@ public void ConfigureServices(HostBuilderContext context, IServiceCollection ser
services.AddBizServices();
services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton();
}
diff --git a/src/BiliLite.UWP/ViewModels/Search/BaseSearchPivotViewModel.cs b/src/BiliLite.UWP/ViewModels/Search/BaseSearchPivotViewModel.cs
new file mode 100644
index 000000000..2b37f30f2
--- /dev/null
+++ b/src/BiliLite.UWP/ViewModels/Search/BaseSearchPivotViewModel.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Threading.Tasks;
+using System.Windows.Input;
+using BiliLite.Models.Common;
+using BiliLite.Models.Requests.Api;
+using BiliLite.Modules;
+using BiliLite.ViewModels.Common;
+using PropertyChanged;
+
+namespace BiliLite.ViewModels.Search
+{
+ public class BaseSearchPivotViewModel : BaseViewModel, ISearchPivotViewModel
+ {
+ #region Fields
+
+ protected SearchAPI SearchApi;
+
+ #endregion
+
+ #region Constructors
+
+ public BaseSearchPivotViewModel()
+ {
+ SearchApi = new SearchAPI();
+ RefreshCommand = new RelayCommand(Refresh);
+ LoadMoreCommand = new RelayCommand(LoadMore);
+ }
+
+ #endregion
+
+ #region Properties
+
+ public ICommand LoadMoreCommand { get; private set; }
+
+ public ICommand RefreshCommand { get; private set; }
+
+ [DoNotNotify]
+ public SearchType SearchType { get; set; }
+
+ [DoNotNotify]
+ public string Title { get; set; }
+
+ [DoNotNotify]
+ public string Keyword { get; set; }
+
+ [DoNotNotify]
+ public string Area { get; set; } = "";
+
+ [DoNotNotify]
+ public int Page { get; set; } = 1;
+
+ public bool Loading { get; set; }
+
+ public bool Nothing { get; set; }
+
+ public bool ShowLoadMore { get; set; }
+
+ public bool HasData { get; set; } = false;
+
+ #endregion
+
+ #region Public Methods
+
+ public virtual async void Refresh()
+ {
+ HasData = false;
+ Page = 1;
+ await LoadData();
+ }
+ public virtual async void LoadMore()
+ {
+ await LoadData();
+ }
+
+ public virtual Task LoadData()
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+}
diff --git a/src/BiliLite.UWP/ViewModels/Search/ISearchPivotViewModel.cs b/src/BiliLite.UWP/ViewModels/Search/ISearchPivotViewModel.cs
new file mode 100644
index 000000000..6335c2aab
--- /dev/null
+++ b/src/BiliLite.UWP/ViewModels/Search/ISearchPivotViewModel.cs
@@ -0,0 +1,35 @@
+using System.Threading.Tasks;
+using System.Windows.Input;
+using BiliLite.Models.Common;
+
+namespace BiliLite.ViewModels.Search
+{
+ public interface ISearchPivotViewModel
+ {
+ public ICommand LoadMoreCommand { get; }
+
+ public ICommand RefreshCommand { get; }
+
+ public SearchType SearchType { get; set; }
+
+ public string Title { get; set; }
+
+ public string Keyword { get; set; }
+
+ public string Area { get; set; }
+
+ public int Page { get; set; }
+
+ public bool Loading { get; set; }
+
+ public bool Nothing { get; set; }
+
+ public bool ShowLoadMore { get; set; }
+
+ public bool HasData { get; set; }
+
+ public void Refresh();
+
+ public Task LoadData();
+ }
+}
diff --git a/src/BiliLite.UWP/ViewModels/Search/SearchAnimeViewModel.cs b/src/BiliLite.UWP/ViewModels/Search/SearchAnimeViewModel.cs
new file mode 100644
index 000000000..ff278e180
--- /dev/null
+++ b/src/BiliLite.UWP/ViewModels/Search/SearchAnimeViewModel.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using BiliLite.Extensions;
+using BiliLite.Models;
+using BiliLite.Models.Common.Search;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace BiliLite.ViewModels.Search
+{
+ public class SearchAnimeViewModel : BaseSearchPivotViewModel
+ {
+ #region Properties
+
+ public ObservableCollection Animes { get; set; }
+
+ #endregion
+
+ #region Public Methods
+
+ public override async Task LoadData()
+ {
+ try
+ {
+ if (Loading)
+ {
+ return;
+ }
+ ShowLoadMore = false;
+ Loading = true;
+ Nothing = false;
+ var api = SearchApi.WebSearchAnime(Keyword, Page, Area);
+ if (this.SearchType == Models.Common.SearchType.Movie)
+ {
+ api = SearchApi.WebSearchMovie(Keyword, Page, Area);
+ }
+ var results = await api.Request();
+ if (results.status)
+ {
+ var data = await results.GetJson>();
+ if (data.success)
+ {
+
+ var result = JsonConvert.DeserializeObject>(data.data["result"]?.ToString() ?? "[]");
+ if (Page == 1)
+ {
+ if (result == null || result.Count == 0)
+ {
+ Nothing = true;
+ Animes?.Clear();
+ return;
+ }
+ Animes = result;
+ }
+ else
+ {
+ if (data.data != null)
+ {
+ foreach (var item in result)
+ {
+ Animes.Add(item);
+ }
+ }
+ }
+ if (Page < data.data["numPages"].ToInt32())
+ {
+ ShowLoadMore = true;
+ Page++;
+ }
+ HasData = true;
+ }
+ else
+ {
+ Notify.ShowMessageToast(data.message);
+ }
+ }
+ else
+ {
+ Notify.ShowMessageToast(results.message);
+ }
+ }
+ catch (Exception ex)
+ {
+ var handel = HandelError(ex);
+ Notify.ShowMessageToast(handel.message);
+ }
+ finally
+ {
+ Loading = false;
+ }
+ }
+
+ #endregion
+
+
+ }
+}
diff --git a/src/BiliLite.UWP/ViewModels/Search/SearchArticleViewModel.cs b/src/BiliLite.UWP/ViewModels/Search/SearchArticleViewModel.cs
new file mode 100644
index 000000000..0d2049a8e
--- /dev/null
+++ b/src/BiliLite.UWP/ViewModels/Search/SearchArticleViewModel.cs
@@ -0,0 +1,124 @@
+using BiliLite.Models;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using BiliLite.Extensions;
+using BiliLite.Models.Common.Search;
+using PropertyChanged;
+
+namespace BiliLite.ViewModels.Search
+{
+ public class SearchArticleViewModel : BaseSearchPivotViewModel
+ {
+ public SearchArticleViewModel()
+ {
+ OrderFilters = new List() {
+ new SearchFilterItem("默认排序","totalrank"),
+ new SearchFilterItem("最多阅读","click"),
+ new SearchFilterItem("最新发布","pubdate"),
+ new SearchFilterItem("最多喜欢","attention"),
+ new SearchFilterItem("最多评论","scores")
+ };
+ SelectOrder = OrderFilters[0];
+
+ RegionFilters = new List() {
+ new SearchFilterItem("全部分区","0"),
+ new SearchFilterItem("动画","2"),
+ new SearchFilterItem("游戏","1"),
+ new SearchFilterItem("影视","28"),
+ new SearchFilterItem("生活","3"),
+ new SearchFilterItem("兴趣","29"),
+ new SearchFilterItem("轻小说","16"),
+ new SearchFilterItem("科技","17"),
+ };
+
+ SelectRegion = RegionFilters[0];
+ }
+
+ [DoNotNotify]
+ public List OrderFilters { get; set; }
+
+ [DoNotNotify]
+ public SearchFilterItem SelectOrder { get; set; }
+
+ [DoNotNotify]
+ public List DurationFilters { get; set; }
+
+ [DoNotNotify]
+ public List RegionFilters { get; set; }
+
+ [DoNotNotify]
+ public SearchFilterItem SelectRegion { get; set; }
+
+ public ObservableCollection Articles { get; set; }
+
+ public override async Task LoadData()
+ {
+ try
+ {
+ if (Loading)
+ {
+ return;
+ }
+ ShowLoadMore = false;
+ Loading = true;
+ Nothing = false;
+ var results = await SearchApi.WebSearchArticle(Keyword, Page, SelectOrder.value, SelectRegion.value, Area).Request();
+ if (results.status)
+ {
+ var data = await results.GetJson>();
+ if (data.success)
+ {
+ var result = JsonConvert.DeserializeObject>(data.data["result"]?.ToString() ?? "[]");
+ if (Page == 1)
+ {
+ if (result == null || result.Count == 0)
+ {
+ Nothing = true;
+ Articles?.Clear();
+ return;
+ }
+ Articles = result;
+ }
+ else
+ {
+ if (data.data != null)
+ {
+ foreach (var item in result)
+ {
+ Articles.Add(item);
+ }
+ }
+ }
+ if (Page < data.data["numPages"].ToInt32())
+ {
+ ShowLoadMore = true;
+ Page++;
+ }
+ HasData = true;
+ }
+ else
+ {
+ Notify.ShowMessageToast(data.message);
+ }
+ }
+ else
+ {
+ Notify.ShowMessageToast(results.message);
+ }
+ }
+ catch (Exception ex)
+ {
+ var handel = HandelError(ex);
+ Notify.ShowMessageToast(handel.message);
+ }
+ finally
+ {
+ Loading = false;
+ }
+ }
+ }
+}
diff --git a/src/BiliLite.UWP/ViewModels/Search/SearchLiveRoomViewModel.cs b/src/BiliLite.UWP/ViewModels/Search/SearchLiveRoomViewModel.cs
new file mode 100644
index 000000000..eacc7f51c
--- /dev/null
+++ b/src/BiliLite.UWP/ViewModels/Search/SearchLiveRoomViewModel.cs
@@ -0,0 +1,92 @@
+using BiliLite.Models;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+using System;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using BiliLite.Extensions;
+using BiliLite.Models.Common.Search;
+
+namespace BiliLite.ViewModels.Search
+{
+ public class SearchLiveRoomViewModel : BaseSearchPivotViewModel
+ {
+ #region Properties
+
+ public ObservableCollection Rooms { get; set; }
+
+ #endregion
+
+ #region Public Methods
+
+ public override async Task LoadData()
+ {
+ try
+ {
+ if (Loading)
+ {
+ return;
+ }
+ ShowLoadMore = false;
+ Loading = true;
+ Nothing = false;
+
+ var results = await SearchApi.WebSearchLive(Keyword, Page, Area).Request();
+ if (results.status)
+ {
+ var data = await results.GetJson>();
+ if (data.success)
+ {
+
+ var result = JsonConvert.DeserializeObject>(data.data["result"]["live_room"]?.ToString() ?? "[]");
+ if (Page == 1)
+ {
+ if (result == null || result.Count == 0)
+ {
+ Nothing = true;
+ Rooms?.Clear();
+ return;
+ }
+ Rooms = result;
+ }
+ else
+ {
+ if (data.data != null)
+ {
+ foreach (var item in result)
+ {
+ Rooms.Add(item);
+ }
+ }
+ }
+ if (Page < data.data["pageinfo"]["live_room"]["numPages"].ToInt32())
+ {
+ ShowLoadMore = true;
+ Page++;
+ }
+ HasData = true;
+ }
+ else
+ {
+ Notify.ShowMessageToast(data.message);
+ }
+ }
+ else
+ {
+ Notify.ShowMessageToast(results.message);
+ }
+ }
+ catch (Exception ex)
+ {
+ var handel = HandelError(ex);
+ Notify.ShowMessageToast(handel.message);
+ }
+ finally
+ {
+ Loading = false;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/BiliLite.UWP/ViewModels/Search/SearchPageViewModel.cs b/src/BiliLite.UWP/ViewModels/Search/SearchPageViewModel.cs
new file mode 100644
index 000000000..59cdcadc6
--- /dev/null
+++ b/src/BiliLite.UWP/ViewModels/Search/SearchPageViewModel.cs
@@ -0,0 +1,125 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Windows.UI.Xaml;
+using BiliLite.Models.Common;
+using BiliLite.Models.Common.Search;
+using BiliLite.ViewModels.Common;
+using PropertyChanged;
+
+namespace BiliLite.ViewModels.Search
+{
+ public class SearchPageViewModel : BaseViewModel
+ {
+ #region Constructors
+
+ public SearchPageViewModel()
+ {
+ }
+
+ #endregion
+
+ #region Properties
+
+ public ObservableCollection SearchItems { get; set; }
+
+ [DoNotNotify]
+ public List Areas { get; set; } = new List()
+ {
+ new SearchArea("默认地区",""),
+ new SearchArea("大陆地区","cn"),
+ new SearchArea("香港地区","hk"),
+ new SearchArea("台湾地区","tw"),
+ };
+
+ [DoNotNotify]
+ public SearchArea Area { get; set; }
+
+ [DoNotNotify]
+ public ISearchPivotViewModel SelectItem { get; set; }
+
+ public ObservableCollection SuggestSearchContents { get; set; }
+
+ public int PivotIndex { get; set; }
+
+ public int ComboIndex { get; set; }
+
+ public double PivotHeaderWidth { get; set; }
+
+ public double PageWidth { get; set; }
+
+ [DoNotNotify]
+ public double SearchBoxWidth { get; } = 334;
+
+ [DependsOn(nameof(PivotHeaderWidth), nameof(PageWidth))]
+ public Thickness PivotMargin => PivotHeaderWidth + SearchBoxWidth < PageWidth ? new Thickness(0, 0, 0, 0) : new Thickness(0, 36, 0, 0);
+
+ [DependsOn(nameof(PivotHeaderWidth), nameof(PageWidth))]
+ public Thickness SearchBoxMargin => PivotHeaderWidth + SearchBoxWidth < PageWidth ? new Thickness(400, 8, 8, 0) : new Thickness(8, 8, 8, 0);
+
+ [DependsOn(nameof(PivotHeaderWidth), nameof(PageWidth))]
+ public HorizontalAlignment SearchBoxHorizontalAlignment => PivotHeaderWidth + SearchBoxWidth < PageWidth
+ ? HorizontalAlignment.Right
+ : HorizontalAlignment.Stretch;
+
+ #endregion
+
+ #region Public Methods
+
+ public void Init(int pivotIndex, int comboIndex)
+ {
+ Area = Areas[comboIndex];
+ SearchItems = new ObservableCollection() {
+ new SearchVideoViewModel()
+ {
+ Title="视频",
+ SearchType= SearchType.Video,
+ Area= Area.area
+ },
+ new SearchAnimeViewModel()
+ {
+ Title="番剧",
+ SearchType= SearchType.Anime,
+ Area= Area.area
+ },
+ new SearchLiveRoomViewModel()
+ {
+ Title="直播",
+ SearchType= SearchType.Live,
+ Area= Area.area
+ },
+ //new SearchLiveRoomVM()
+ //{
+ // Title="主播",
+ // SearchType= SearchType.Anchor
+ //},
+ new SearchUserViewModel()
+ {
+ Title="用户",
+ SearchType= SearchType.User,
+ Area= Area.area
+ },
+ new SearchAnimeViewModel()
+ {
+ Title="影视",
+ SearchType= SearchType.Movie,
+ Area= Area.area
+ },
+ new SearchArticleViewModel()
+ {
+ Title="专栏",
+ SearchType= SearchType.Article,
+ Area= Area.area
+ },
+ new SearchTopicViewModel()
+ {
+ Title="话题",
+ SearchType= SearchType.Topic,
+ Area= Area.area
+ }
+ };
+ SelectItem = SearchItems[pivotIndex];
+ }
+
+ #endregion
+ }
+}
diff --git a/src/BiliLite.UWP/ViewModels/Search/SearchTopicViewModel.cs b/src/BiliLite.UWP/ViewModels/Search/SearchTopicViewModel.cs
new file mode 100644
index 000000000..782292b81
--- /dev/null
+++ b/src/BiliLite.UWP/ViewModels/Search/SearchTopicViewModel.cs
@@ -0,0 +1,83 @@
+using BiliLite.Models;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+using System;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using BiliLite.Extensions;
+using BiliLite.Models.Common.Search;
+
+namespace BiliLite.ViewModels.Search
+{
+ public class SearchTopicViewModel : BaseSearchPivotViewModel
+ {
+ public ObservableCollection Topics { get; set; }
+
+ public override async Task LoadData()
+ {
+ try
+ {
+ if (Loading)
+ {
+ return;
+ }
+ ShowLoadMore = false;
+ Loading = true;
+ Nothing = false;
+ var results = await SearchApi.WebSearchTopic(Keyword, Page, Area).Request();
+ if (results.status)
+ {
+ var data = await results.GetJson>();
+ if (data.success)
+ {
+
+ var result = JsonConvert.DeserializeObject>(data.data["result"]?.ToString() ?? "[]");
+ if (Page == 1)
+ {
+ if (result == null || result.Count == 0)
+ {
+ Nothing = true;
+ Topics?.Clear();
+ return;
+ }
+ Topics = result;
+ }
+ else
+ {
+ if (data.data != null)
+ {
+ foreach (var item in result)
+ {
+ Topics.Add(item);
+ }
+ }
+ }
+ if (Page < data.data["numPages"].ToInt32())
+ {
+ ShowLoadMore = true;
+ Page++;
+ }
+ HasData = true;
+ }
+ else
+ {
+ Notify.ShowMessageToast(data.message);
+ }
+ }
+ else
+ {
+ Notify.ShowMessageToast(results.message);
+ }
+ }
+ catch (Exception ex)
+ {
+ var handel = HandelError(ex);
+ Notify.ShowMessageToast(handel.message);
+ }
+ finally
+ {
+ Loading = false;
+ }
+ }
+ }
+}
diff --git a/src/BiliLite.UWP/ViewModels/Search/SearchUserViewModel.cs b/src/BiliLite.UWP/ViewModels/Search/SearchUserViewModel.cs
new file mode 100644
index 000000000..b1b61e302
--- /dev/null
+++ b/src/BiliLite.UWP/ViewModels/Search/SearchUserViewModel.cs
@@ -0,0 +1,129 @@
+using BiliLite.Models;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using BiliLite.Extensions;
+using BiliLite.Models.Common.Search;
+using PropertyChanged;
+
+namespace BiliLite.ViewModels.Search
+{
+ public class SearchUserViewModel : BaseSearchPivotViewModel
+ {
+ #region Constructors
+
+ public SearchUserViewModel()
+ {
+ OrderFilters = new List() {
+ new SearchFilterItem("默认排序","&order=&order_sort="),
+ new SearchFilterItem("粉丝数由高到低","&order=fans&order_sort=0"),
+ new SearchFilterItem("粉丝数由低到高","&order=fans&order_sort=1"),
+ new SearchFilterItem("LV等级由高到低","&order=level&order_sort=0"),
+ new SearchFilterItem("LV等级由低到高","&order=level&order_sort=1"),
+ };
+ SelectOrder = OrderFilters[0];
+ TypeFilters = new List() {
+ new SearchFilterItem("全部用户","&user_type=0"),
+ new SearchFilterItem("UP主","&user_type=1"),
+ new SearchFilterItem("普通用户","&user_type=2"),
+ new SearchFilterItem("认证用户","&user_type=3")
+ };
+ SelectType = TypeFilters[0];
+
+ }
+
+ #endregion
+
+ #region Properties
+
+ [DoNotNotify]
+ public List OrderFilters { get; set; }
+
+ [DoNotNotify]
+ public SearchFilterItem SelectOrder { get; set; }
+
+ [DoNotNotify]
+ public List TypeFilters { get; set; }
+
+ [DoNotNotify]
+ public SearchFilterItem SelectType { get; set; }
+
+ public ObservableCollection Users { get; set; }
+
+ #endregion
+
+ #region Public Methods
+
+ public override async Task LoadData()
+ {
+ try
+ {
+ if (Loading)
+ {
+ return;
+ }
+ ShowLoadMore = false;
+ Loading = true;
+ Nothing = false;
+ var results = await SearchApi.WebSearchUser(Keyword, Page, SelectOrder.value, SelectType.value, Area).Request();
+ if (results.status)
+ {
+ var data = await results.GetJson>();
+ if (data.success)
+ {
+ var result = JsonConvert.DeserializeObject>(data.data["result"]?.ToString() ?? "[]");
+ if (Page == 1)
+ {
+ if (result == null || result.Count == 0)
+ {
+ Nothing = true;
+ Users?.Clear();
+ return;
+ }
+ Users = result;
+ }
+ else
+ {
+ if (data.data != null)
+ {
+ foreach (var item in result)
+ {
+ Users.Add(item);
+ }
+ }
+ }
+ if (Page < data.data["numPages"].ToInt32())
+ {
+ ShowLoadMore = true;
+ Page++;
+ }
+ HasData = true;
+ }
+ else
+ {
+ Notify.ShowMessageToast(data.message);
+ }
+ }
+ else
+ {
+ Notify.ShowMessageToast(results.message);
+ }
+ }
+ catch (Exception ex)
+ {
+ var handel = HandelError(ex);
+ Notify.ShowMessageToast(handel.message);
+ }
+ finally
+ {
+ Loading = false;
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/src/BiliLite.UWP/ViewModels/Search/SearchVideoViewModel.cs b/src/BiliLite.UWP/ViewModels/Search/SearchVideoViewModel.cs
new file mode 100644
index 000000000..b7dfda727
--- /dev/null
+++ b/src/BiliLite.UWP/ViewModels/Search/SearchVideoViewModel.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Threading.Tasks;
+using BiliLite.Extensions;
+using BiliLite.Models;
+using BiliLite.Models.Common.Search;
+using BiliLite.Models.Exceptions;
+using BiliLite.Services;
+using Microsoft.Extensions.DependencyInjection;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using PropertyChanged;
+
+namespace BiliLite.ViewModels.Search
+{
+ public class SearchVideoViewModel : BaseSearchPivotViewModel
+ {
+ #region Fields
+
+ private static readonly ILogger _logger = GlobalLogger.FromCurrentType();
+ private readonly ContentFilterService m_contentFilterService;
+
+ #endregion
+
+ #region Constructors
+
+ public SearchVideoViewModel()
+ {
+ m_contentFilterService = App.ServiceProvider.GetRequiredService();
+ OrderFilters = new List() {
+ new SearchFilterItem("综合排序",""),
+ new SearchFilterItem("最多点击","click"),
+ new SearchFilterItem("最新发布","pubdate"),
+ new SearchFilterItem("最多弹幕","dm"),
+ new SearchFilterItem("最多收藏","stow")
+ };
+ SelectOrder = OrderFilters[0];
+ DurationFilters = new List() {
+ new SearchFilterItem("全部时长",""),
+ new SearchFilterItem("10分钟以下","1"),
+ new SearchFilterItem("10-30分钟","2"),
+ new SearchFilterItem("30-60分钟","3"),
+ new SearchFilterItem("60分钟以上","4")
+ };
+ SelectDuration = DurationFilters[0];
+ RegionFilters = new List() {
+ new SearchFilterItem("全部分区","0"),
+ };
+ foreach (var item in AppHelper.Regions.Where(x => x.children != null && x.children.Count != 0))
+ {
+ RegionFilters.Add(new SearchFilterItem(item.name, item.tid.ToString()));
+ }
+ SelectRegion = RegionFilters[0];
+ }
+
+ #endregion
+
+ #region Properties
+
+
+ [DoNotNotify]
+ public List OrderFilters { get; set; }
+
+ [DoNotNotify]
+ public SearchFilterItem SelectOrder { get; set; }
+
+ [DoNotNotify]
+ public List DurationFilters { get; set; }
+
+ [DoNotNotify]
+ public SearchFilterItem SelectDuration { get; set; }
+
+ [DoNotNotify]
+ public List RegionFilters { get; set; }
+
+ [DoNotNotify]
+ public SearchFilterItem SelectRegion { get; set; }
+
+ public ObservableCollection Videos { get; set; }
+
+ #endregion
+
+ #region Public Methods
+
+ public override async Task LoadData()
+ {
+ try
+ {
+ if (Loading)
+ {
+ return;
+ }
+ ShowLoadMore = false;
+ Loading = true;
+ Nothing = false;
+ var results = await SearchApi.WebSearchVideo(Keyword, Page, SelectOrder.value, SelectDuration.value, SelectRegion.value, Area).Request();
+ if (!results.status)
+ {
+ throw new CustomizedErrorException(results.message);
+ }
+ var data = await results.GetJson>();
+ if (!data.success)
+ {
+ throw new CustomizedErrorException(data.message);
+ }
+ var searchVideoItems = JsonConvert.DeserializeObject>(data.data["result"]?.ToString() ?? "[]");
+ searchVideoItems = m_contentFilterService.FilterSearchItems(searchVideoItems);
+ var result = new ObservableCollection(searchVideoItems);
+
+ if (Page == 1)
+ {
+ if (result == null || result.Count == 0)
+ {
+ Nothing = true;
+ Videos?.Clear();
+ return;
+ }
+ Videos = result;
+ }
+ else if (data.data != null)
+ {
+ foreach (var item in result)
+ {
+ Videos.Add(item);
+ }
+ }
+ if (Page < data.data["numPages"].ToInt32())
+ {
+ ShowLoadMore = true;
+ Page++;
+ }
+ HasData = true;
+
+ }
+ catch (Exception ex)
+ {
+ if (ex is CustomizedErrorException customizedErrorException)
+ {
+ Notify.ShowMessageToast(ex.Message);
+ _logger.Error("搜索失败", ex);
+ }
+
+ var handel = HandelError(ex);
+ Notify.ShowMessageToast(handel.message);
+ }
+ finally
+ {
+ Loading = false;
+ }
+ }
+
+ #endregion
+ }
+}