支持UP主用户空间的合集和列表

pull/514/merge
leiurayer 2 years ago
parent 49895b8b7f
commit 3b70055729

@ -0,0 +1,32 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Users.Models
{
// https://api.bilibili.com/x/polymer/space/seasons_archives_list?mid={mid}&season_id={seasonId}&page_num={pageNum}&page_size={pageSize}&sort_reverse=false
public class SpaceSeasonsDetailOrigin : BaseModel
{
//[JsonProperty("code")]
//public int Code { get; set; }
//[JsonProperty("message")]
//public string Message { get; set; }
//[JsonProperty("ttl")]
//public int Ttl { get; set; }
[JsonProperty("data")]
public SpaceSeasonsDetail Data { get; set; }
}
public class SpaceSeasonsDetail : BaseModel
{
[JsonProperty("aids")]
public List<long> Aids { get; set; }
[JsonProperty("archives")]
public List<SpaceSeasonsSeriesArchives> Archives { get; set; }
[JsonProperty("meta")]
public SpaceSeasonsMeta Meta { get; set; }
[JsonProperty("page")]
public SpaceSeasonsSeriesPage Page { get; set; }
}
}

@ -0,0 +1,26 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Users.Models
{
public class SpaceSeasons : BaseModel
{
[JsonProperty("archives")]
public List<SpaceSeasonsSeriesArchives> Archives { get; set; }
[JsonProperty("meta")]
public SpaceSeasonsMeta Meta { get; set; }
[JsonProperty("recent_aids")]
public List<long> RecentAids { get; set; }
}
public class SpaceSeries : BaseModel
{
[JsonProperty("archives")]
public List<SpaceSeasonsSeriesArchives> Archives { get; set; }
[JsonProperty("meta")]
public SpaceSeriesMeta Meta { get; set; }
[JsonProperty("recent_aids")]
public List<long> RecentAids { get; set; }
}
}

@ -0,0 +1,29 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.Users.Models
{
public class SpaceSeasonsSeriesArchives : BaseModel
{
[JsonProperty("aid")]
public long Aid { get; set; }
[JsonProperty("bvid")]
public string Bvid { get; set; }
[JsonProperty("ctime")]
public long Ctime { get; set; }
[JsonProperty("duration")]
public long Duration { get; set; }
[JsonProperty("interactive_video")]
public bool InteractiveVideo { get; set; }
[JsonProperty("pic")]
public string Pic { get; set; }
[JsonProperty("pubdate")]
public long Pubdate { get; set; }
[JsonProperty("stat")]
public SpaceSeasonsSeriesStat Stat { get; set; }
// state
[JsonProperty("title")]
public string Title { get; set; }
// ugc_pay
}
}

@ -0,0 +1,51 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Users.Models
{
public class SpaceSeasonsSeriesMeta : BaseModel
{
[JsonProperty("category")]
public int Category { get; set; }
[JsonProperty("cover")]
public string Cover { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("mid")]
public long Mid { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("total")]
public int Total { get; set; }
}
public class SpaceSeasonsMeta : SpaceSeasonsSeriesMeta
{
[JsonProperty("ptime")]
public long Ptime { get; set; }
[JsonProperty("season_id")]
public long SeasonId { get; set; }
}
public class SpaceSeriesMeta : SpaceSeasonsSeriesMeta
{
[JsonProperty("creator")]
public string Creator { get; set; }
[JsonProperty("ctime")]
public long Ctime { get; set; }
[JsonProperty("keywords")]
public List<string> Keywords { get; set; }
[JsonProperty("last_update_ts")]
public long LastUpdate { get; set; }
[JsonProperty("mtime")]
public long Mtime { get; set; }
[JsonProperty("raw_keywords")]
public string RawKeywords { get; set; }
[JsonProperty("series_id")]
public long SeriesId { get; set; }
[JsonProperty("state")]
public int State { get; set; }
}
}

@ -0,0 +1,36 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Users.Models
{
// https://api.bilibili.com/x/space/channel/video?mid={mid}&page_num={pageNum}&page_size={pageSize}
public class SpaceSeasonsSeriesOrigin : BaseModel
{
//[JsonProperty("code")]
//public int Code { get; set; }
//[JsonProperty("message")]
//public string Message { get; set; }
//[JsonProperty("ttl")]
//public int Ttl { get; set; }
[JsonProperty("data")]
public SpaceSeasonsSeriesData Data { get; set; }
}
public class SpaceSeasonsSeriesData : BaseModel
{
[JsonProperty("items_lists")]
public SpaceSeasonsSeries ItemsLists { get; set; }
}
public class SpaceSeasonsSeries : BaseModel
{
[JsonProperty("page")]
public SpaceSeasonsSeriesPage Page { get; set; }
[JsonProperty("seasons_list")]
public List<SpaceSeasons> SeasonsList { get; set; }
[JsonProperty("series_list")]
public List<SpaceSeries> SeriesList { get; set; }
}
}

@ -0,0 +1,15 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.Users.Models
{
public class SpaceSeasonsSeriesPage : BaseModel
{
[JsonProperty("page_num")]
public int PageNum;
[JsonProperty("page_size")]
public int PageSize;
[JsonProperty("total")]
public int Total;
}
}

@ -0,0 +1,11 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.Users.Models
{
public class SpaceSeasonsSeriesStat : BaseModel
{
[JsonProperty("view")]
public long View { get; set; }
}
}

@ -0,0 +1,29 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Users.Models
{
// https://api.bilibili.com/x/series/archives?mid={mid}&series_id={seriesId}&only_normal=true&sort=desc&pn={pn}&ps={ps}
public class SpaceSeriesDetailOrigin : BaseModel
{
//[JsonProperty("code")]
//public int Code { get; set; }
//[JsonProperty("message")]
//public string Message { get; set; }
//[JsonProperty("ttl")]
//public int Ttl { get; set; }
[JsonProperty("data")]
public SpaceSeriesDetail Data { get; set; }
}
public class SpaceSeriesDetail : BaseModel
{
[JsonProperty("aids")]
public List<long> Aids { get; set; }
// page
[JsonProperty("archives")]
public List<SpaceSeasonsSeriesArchives> Archives { get; set; }
}
}

@ -0,0 +1,28 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Users.Models
{
// https://api.bilibili.com/x/series/series?series_id={seriesId}
public class SpaceSeriesMetaOrigin : BaseModel
{
//[JsonProperty("code")]
//public int Code { get; set; }
//[JsonProperty("message")]
//public string Message { get; set; }
//[JsonProperty("ttl")]
//public int Ttl { get; set; }
[JsonProperty("data")]
public SpaceSeriesMetaData Data { get; set; }
}
public class SpaceSeriesMetaData : BaseModel
{
[JsonProperty("meta")]
public SpaceSeriesMeta Meta { get; set; }
[JsonProperty("recent_aids")]
public List<long> RecentAids { get; set; }
}
}

@ -232,20 +232,125 @@ namespace DownKyi.Core.BiliApi.Users
#region 合集和列表
// TODO
// https://api.bilibili.com/x/polymer/space/seasons_series_list?mid=27899754&page_num=1&page_size=18
// page_size最大值为20
/// <summary>
/// 查询用户的合集和列表
/// </summary>
/// <param name="mid"></param>
/// <param name="pageNum">第几页</param>
/// <param name="pageSize">每页的数量最大值为20</param>
/// <returns></returns>
public static SpaceSeasonsSeries GetSeasonsSeries(long mid, int pageNum, int pageSize)
{
// https://api.bilibili.com/x/polymer/space/seasons_series_list?mid=49246269&page_num=1&page_size=18
string url = $"https://api.bilibili.com/x/polymer/space/seasons_series_list?mid={mid}&page_num={pageNum}&page_size={pageSize}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
// https://api.bilibili.com/x/polymer/space/seasons_archives_list?mid=23947287&season_id=665&sort_reverse=false&page_num=1&page_size=30
try
{
SpaceSeasonsSeriesOrigin origin = JsonConvert.DeserializeObject<SpaceSeasonsSeriesOrigin>(response);
if (origin == null || origin.Data == null || origin.Data.ItemsLists == null)
{ return null; }
return origin.Data.ItemsLists;
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetSeasonsSeries()发生异常: {0}", e);
LogManager.Error("UserSpace", e);
return null;
}
}
/// <summary>
/// 查询用户的合集的视频详情
/// </summary>
/// <param name="mid"></param>
/// <param name="seasonId"></param>
/// <param name="pageNum"></param>
/// <param name="pageSize"></param>
public static SpaceSeasonsDetail GetSeasonsDetail(long mid, long seasonId, int pageNum, int pageSize)
{
// https://api.bilibili.com/x/polymer/space/seasons_archives_list?mid=23947287&season_id=665&sort_reverse=false&page_num=1&page_size=30
string url = $"https://api.bilibili.com/x/polymer/space/seasons_archives_list?mid={mid}&season_id={seasonId}&page_num={pageNum}&page_size={pageSize}&sort_reverse=false";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
// https://api.bilibili.com/x/series/archives?mid=27899754&series_id=1253087&only_normal=true&sort=desc&pn=1&ps=30
// https://api.bilibili.com/x/series/archives?mid=27899754&series_id=1253087&only_normal=true&sort=asc&pn=1&ps=30
// https://api.bilibili.com/x/series/series?series_id=1253087
try
{
SpaceSeasonsDetailOrigin origin = JsonConvert.DeserializeObject<SpaceSeasonsDetailOrigin>(response);
if (origin == null || origin.Data == null)
{ return null; }
return origin.Data;
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetSeasonsDetail()发生异常: {0}", e);
LogManager.Error("UserSpace", e);
return null;
}
}
/// <summary>
/// 查询用户的列表元数据
/// </summary>
/// <param name="seriesId"></param>
/// <returns></returns>
public static SpaceSeriesMetaData GetSeriesMeta(long seriesId)
{
// https://api.bilibili.com/x/series/series?series_id=1253087
string url = $"https://api.bilibili.com/x/series/series?series_id={seriesId}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
try
{
SpaceSeriesMetaOrigin origin = JsonConvert.DeserializeObject<SpaceSeriesMetaOrigin>(response);
if (origin == null || origin.Data == null)
{ return null; }
return origin.Data;
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetSeriesMeta()发生异常: {0}", e);
LogManager.Error("UserSpace", e);
return null;
}
}
/// <summary>
/// 查询用户的列表的视频详情
/// </summary>
/// <param name="mid"></param>
/// <param name="seriesId"></param>
/// <param name="pn"></param>
/// <param name="ps"></param>
/// <returns></returns>
public static SpaceSeriesDetail GetSeriesDetail(long mid, long seriesId, int pn, int ps)
{
// https://api.bilibili.com/x/series/archives?mid=27899754&series_id=1253087&only_normal=true&sort=desc&pn=1&ps=30
string url = $"https://api.bilibili.com/x/series/archives?mid={mid}&series_id={seriesId}&only_normal=true&sort=desc&pn={pn}&ps={ps}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
try
{
SpaceSeriesDetailOrigin origin = JsonConvert.DeserializeObject<SpaceSeriesDetailOrigin>(response);
if (origin == null || origin.Data == null)
{ return null; }
return origin.Data;
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetSeriesDetail()发生异常: {0}", e);
LogManager.Error("UserSpace", e);
return null;
}
}
#endregion
#region 课程
/// <summary>
/// 查询用户发布的课程列表
/// </summary>

@ -217,6 +217,15 @@
<Compile Include="BiliApi\Users\Models\SpacePublicationListTypeVideoZone.cs" />
<Compile Include="BiliApi\Users\Models\SpacePublicationListVideo.cs" />
<Compile Include="BiliApi\Users\Models\SpacePublicationPage.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSeasonsDetail.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSeasonsSeries.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSeasonsSeriesArchives.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSeasonsSeriesMeta.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSeasonsSeriesOrigin.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSeasonsSeriesPage.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSeasonsSeriesStat.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSeriesDetail.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSeriesMeta.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSettings.cs" />
<Compile Include="BiliApi\Users\Models\SpaceSettingsToutu.cs" />
<Compile Include="BiliApi\Users\Models\UpStat.cs" />

@ -180,6 +180,7 @@ namespace DownKyi
containerRegistry.RegisterForNavigation<ViewUserSpace>(ViewUserSpaceViewModel.Tag);
containerRegistry.RegisterForNavigation<ViewPublication>(ViewPublicationViewModel.Tag);
containerRegistry.RegisterForNavigation<Views.ViewChannel>(ViewModels.ViewChannelViewModel.Tag);
containerRegistry.RegisterForNavigation<Views.ViewSeasonsSeries>(ViewModels.ViewSeasonsSeriesViewModel.Tag);
containerRegistry.RegisterForNavigation<ViewMySpace>(ViewMySpaceViewModel.Tag);
containerRegistry.RegisterForNavigation<ViewMyFavorites>(ViewMyFavoritesViewModel.Tag);
@ -206,6 +207,7 @@ namespace DownKyi
// UserSpace
containerRegistry.RegisterForNavigation<ViewArchive>(ViewArchiveViewModel.Tag);
containerRegistry.RegisterForNavigation<Views.UserSpace.ViewChannel>(ViewModels.UserSpace.ViewChannelViewModel.Tag);
containerRegistry.RegisterForNavigation<Views.UserSpace.ViewSeasonsSeries>(ViewModels.UserSpace.ViewSeasonsSeriesViewModel.Tag);
// dialogs
containerRegistry.RegisterDialog<ViewAlertDialog>(ViewAlertDialogViewModel.Tag);

@ -164,12 +164,15 @@
<Compile Include="ViewModels\DownloadManager\ViewDownloadingViewModel.cs" />
<Compile Include="ViewModels\Toolbox\ViewBiliHelperViewModel.cs" />
<Compile Include="ViewModels\Toolbox\ViewDelogoViewModel.cs" />
<Compile Include="ViewModels\UserSpace\SeasonsSeries.cs" />
<Compile Include="ViewModels\UserSpace\Channel.cs" />
<Compile Include="ViewModels\UserSpace\PublicationZone.cs" />
<Compile Include="ViewModels\UserSpace\ViewSeasonsSeriesViewModel.cs" />
<Compile Include="ViewModels\UserSpace\ViewChannelViewModel.cs" />
<Compile Include="ViewModels\UserSpace\ViewArchiveViewModel.cs" />
<Compile Include="ViewModels\UserSpace\TabLeftBanner.cs" />
<Compile Include="ViewModels\UserSpace\TabRightBanner.cs" />
<Compile Include="ViewModels\ViewSeasonsSeriesViewModel.cs" />
<Compile Include="ViewModels\ViewChannelViewModel.cs" />
<Compile Include="ViewModels\ViewDownloadManagerViewModel.cs" />
<Compile Include="ViewModels\Toolbox\ViewExtractMediaViewModel.cs" />
@ -234,9 +237,15 @@
<Compile Include="Views\UserSpace\ViewArchive.xaml.cs">
<DependentUpon>ViewArchive.xaml</DependentUpon>
</Compile>
<Compile Include="Views\UserSpace\ViewSeasonsSeries.xaml.cs">
<DependentUpon>ViewSeasonsSeries.xaml</DependentUpon>
</Compile>
<Compile Include="Views\UserSpace\ViewChannel.xaml.cs">
<DependentUpon>ViewChannel.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ViewSeasonsSeries.xaml.cs">
<DependentUpon>ViewSeasonsSeries.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ViewChannel.xaml.cs">
<DependentUpon>ViewChannel.xaml</DependentUpon>
</Compile>
@ -426,10 +435,18 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\UserSpace\ViewSeasonsSeries.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\UserSpace\ViewChannel.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ViewSeasonsSeries.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ViewChannel.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

@ -1,4 +1,6 @@
namespace DownKyi.Images
using DownKyi.ViewModels.UserSpace;
namespace DownKyi.Images
{
public class NormalIcon
{
@ -267,6 +269,46 @@
Fill = "#FF000000"
};
Channel1 = new VectorImage
{
Height = 24,
Width = 24,
Data = @"M116.57 0 q-30.86 0 -57.71 16 q-26.85 16 -42.85 42.85 q-16 26.85 -16 57.71 l0 468.57 q0 30.86 16 57.72
q16 26.86 42.85 42.86 q26.85 16 57.71 16 l643.43 0 q32 0 58.86 -16 q26.86 -16 42.86 -42.86
q16 -26.86 16 -57.72 l0 -468.57 q0 -30.86 -16 -57.71 q-16 -26.85 -42.86 -42.85 q-26.86 -16 -58.86 -16
l-643.43 0 ZM262.86 848 q-40 0 -72.57 -25.71 q-32.58 -25.72 -39.43 -62.29 l697.14 0 q36.57 0 62.29 -25.71
q25.71 -25.72 25.71 -62.29 l0 -521.14 q37.71 11.43 62.86 42.28 q25.14 30.86 25.14 69.72 l0 468.57
q0 30.86 -16 57.72 q-16 26.86 -42.86 42.86 q-26.86 16 -58.86 16 l-643.43 0 ZM88 174.86
q0 -36.57 25.14 -62.29 q25.14 -25.71 61.72 -25.71 l526.85 0 q36.58 0 62.29 25.71 q25.71 25.72 25.71 62.29
l0 350.85 q0 36.58 -25.71 62.29 q-25.71 25.71 -62.29 25.71 l-526.85 0 q-36.57 0 -61.72 -25.71
q-25.14 -25.71 -25.14 -62.29 l0 -350.85 ZM609.14 374.86 q11.43 -6.86 11.43 -22.29 q0 -15.43 -11.43 -26.86
l-214.85 -146.28 q-13.72 -10.29 -28.57 -1.72 q-14.86 8.58 -14.86 26.86 l0 297.14 q0 18.29 14.86 26.86
q14.85 8.57 28.57 -2.86 l214.85 -150.85 Z",
Fill = "#FF000000"
};
SeasonsSeries = new VectorImage
{
Height = 24,
Width = 24,
Data = @"M974.2 382.22 l-401.47 177.37 q-28.88 13.75 -60.5 13.75 q-31.62 0 -60.5 -13.75 l-400.09 -177.37
q-20.63 -11 -33 -30.25 q-12.38 -19.25 -13.06 -43.31 q-0.68 -24.06 10.32 -45.38 q11 -21.32 31.62 -35.07
l402.85 -210.36 q28.87 -17.87 63.25 -17.87 q34.38 0 63.25 19.25 l398.72 207.61 q22 12.37 33.69 34.37
q11.68 22 10.31 46.06 q-1.38 24.06 -13.06 44 q-11.69 19.94 -32.31 30.94 ZM939.83 292.86 l-400.1 -207.62
q-11 -8.25 -24.75 -9.62 q-16.5 1.37 -30.25 9.62 l-400.1 207.62 q-2.75 6.87 -2.75 12.37 q0 5.5 4.13 9.62
l397.35 175.99 q20.62 9.63 28.18 9.63 q7.56 0 26.81 -8.25 l404.22 -178.74 q1.38 -11 -4.12 -20.62
l1.38 0 ZM20.01 512.84 q8.25 -4.12 19.25 -4.12 q11 0 19.25 5.5 q16.5 9.62 39.87 20.62 l413.85 186.99
l394.6 -178.74 l60.49 -30.25 q9.63 -4.12 19.94 -4.12 q10.31 0 19.25 5.5 q8.94 5.5 13.75 15.12
q4.81 9.63 3.43 19.25 q-1.37 23.37 -21.99 31.62 l-64.62 31.62 l-424.85 193.87 l-422.1 -192.49
q-35.74 -12.38 -68.74 -33 q-9.63 -5.5 -15.13 -14.43 q-5.5 -8.94 -6.18 -19.25 q-0.69 -10.32 4.82 -19.25
q5.5 -8.94 15.12 -14.44 l0 0 ZM58.51 732.83 q17.87 9.62 41.25 20.62 l412.47 186.99 l394.6 -178.74
l60.49 -30.25 q9.63 -5.5 19.94 -4.81 q10.31 0.69 19.25 6.18 q8.94 5.5 13.75 15.12 q4.81 9.63 3.43 19.94
q-1.37 10.32 -6.87 18.57 q-5.5 8.25 -15.12 12.37 l-64.62 31.62 l-424.85 192.49 l-422.1 -191.11
q-35.74 -13.75 -68.74 -34.37 q-13.75 -6.88 -17.88 -22 q-4.13 -15.13 3.44 -28.87 q7.56 -13.75 22.68 -17.87
q15.13 -4.13 28.88 4.13 Z",
Fill = "#FF000000"
};
PlatformIpad = new VectorImage
{
Height = 16,
@ -357,6 +399,8 @@
public VectorImage VideoUp { get; private set; }
public VectorImage Channel { get; private set; }
public VectorImage Channel1 { get; private set; }
public VectorImage SeasonsSeries { get; private set; }
public VectorImage PlatformIpad { get; private set; }
public VectorImage PlatformMobile { get; private set; }

@ -63,6 +63,7 @@
<system:String x:Key="AllPublicationZones">全部</system:String>
<system:String x:Key="Publication">投稿视频</system:String>
<system:String x:Key="Channel">频道</system:String>
<system:String x:Key="SeasonsSeries">合集和列表</system:String>
<system:String x:Key="UserSpaceWait">请稍等,马上就好~</system:String>
<!-- PublicFavorites -->

@ -0,0 +1,47 @@
using DownKyi.Images;
using Prism.Mvvm;
using System.Windows.Media;
namespace DownKyi.ViewModels.UserSpace
{
public class SeasonsSeries : BindableBase
{
public long Id { get; set; }
private ImageSource cover;
public ImageSource Cover
{
get => cover;
set => SetProperty(ref cover, value);
}
private VectorImage typeImage;
public VectorImage TypeImage
{
get => typeImage;
set => SetProperty(ref typeImage, value);
}
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
private int count;
public int Count
{
get => count;
set => SetProperty(ref count, value);
}
private string ctime;
public string Ctime
{
get => ctime;
set => SetProperty(ref ctime, value);
}
}
}

@ -0,0 +1,199 @@
using DownKyi.Core.BiliApi.Users.Models;
using DownKyi.Core.Storage;
using DownKyi.Events;
using DownKyi.Images;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
namespace DownKyi.ViewModels.UserSpace
{
public class ViewSeasonsSeriesViewModel : BaseViewModel
{
public const string Tag = "PageUserSpaceSeasonsSeries";
private long mid = -1;
#region 页面属性申明
private ObservableCollection<SeasonsSeries> seasonsSeries;
public ObservableCollection<SeasonsSeries> SeasonsSeries
{
get => seasonsSeries;
set => SetProperty(ref seasonsSeries, value);
}
private int selectedItem;
public int SelectedItem
{
get => selectedItem;
set => SetProperty(ref selectedItem, value);
}
#endregion
public ViewSeasonsSeriesViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
{
#region 属性初始化
SeasonsSeries = new ObservableCollection<SeasonsSeries>();
#endregion
}
#region 命令申明
// 视频选择事件
private DelegateCommand<object> seasonsSeriesCommand;
public DelegateCommand<object> SeasonsSeriesCommand => seasonsSeriesCommand ?? (seasonsSeriesCommand = new DelegateCommand<object>(ExecuteSeasonsSeriesCommand));
/// <summary>
/// 视频选择事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteSeasonsSeriesCommand(object parameter)
{
if (!(parameter is SeasonsSeries seasonsSeries)) { return; }
// 应该用枚举的,偷懒直接用数字
int type = 0;
if (seasonsSeries.TypeImage == NormalIcon.Instance().SeasonsSeries)
{
type = 1;
}
else if (seasonsSeries.TypeImage == NormalIcon.Instance().Channel1)
{
type = 2;
}
Dictionary<string, object> data = new Dictionary<string, object>
{
{ "mid", mid },
{ "id", seasonsSeries.Id },
{ "name", seasonsSeries.Name },
{ "count", seasonsSeries.Count },
{ "type", type }
};
// 进入视频页面
NavigationParam param = new NavigationParam
{
ViewName = ViewModels.ViewSeasonsSeriesViewModel.Tag,
ParentViewName = ViewUserSpaceViewModel.Tag,
Parameter = data
};
eventAggregator.GetEvent<NavigationEvent>().Publish(param);
SelectedItem = -1;
}
#endregion
public override void OnNavigatedFrom(NavigationContext navigationContext)
{
base.OnNavigatedFrom(navigationContext);
SeasonsSeries.Clear();
SelectedItem = -1;
}
/// <summary>
/// 接收mid参数
/// </summary>
/// <param name="navigationContext"></param>
public async override void OnNavigatedTo(NavigationContext navigationContext)
{
base.OnNavigatedTo(navigationContext);
SeasonsSeries.Clear();
SelectedItem = -1;
// 根据传入参数不同执行不同任务
var parameter = navigationContext.Parameters.GetValue<SpaceSeasonsSeries>("object");
if (parameter == null)
{
return;
}
// 传入mid
mid = navigationContext.Parameters.GetValue<long>("mid");
foreach (var item in parameter.SeasonsList)
{
if (item.Meta.Total <= 0) { continue; }
BitmapImage image = null;
if (item.Meta.Cover == null || item.Meta.Cover == "")
{
image = new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png"));
}
else
{
StorageCover storageCover = new StorageCover();
string cover = null;
await Task.Run(() =>
{
cover = storageCover.GetCover(item.Meta.Cover);
});
image = storageCover.GetCoverThumbnail(cover, 190, 190);
}
// 当地时区
DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
DateTime dateCTime = startTime.AddSeconds(item.Meta.Ptime);
string mtime = dateCTime.ToString("yyyy-MM-dd");
SeasonsSeries.Add(new SeasonsSeries
{
Id = item.Meta.SeasonId,
Cover = image,
TypeImage = NormalIcon.Instance().SeasonsSeries,
Name = item.Meta.Name,
Count = item.Meta.Total,
Ctime = mtime
});
}
foreach (var item in parameter.SeriesList)
{
if (item.Meta.Total <= 0) { continue; }
BitmapImage image = null;
if (item.Meta.Cover == null || item.Meta.Cover == "")
{
image = new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png"));
}
else
{
StorageCover storageCover = new StorageCover();
string cover = null;
await Task.Run(() =>
{
cover = storageCover.GetCover(item.Meta.Cover);
});
image = storageCover.GetCoverThumbnail(cover, 190, 190);
}
// 当地时区
DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
DateTime dateCTime = startTime.AddSeconds(item.Meta.Mtime);
string mtime = dateCTime.ToString("yyyy-MM-dd");
SeasonsSeries.Add(new SeasonsSeries
{
Id = item.Meta.SeriesId,
Cover = image,
TypeImage = NormalIcon.Instance().Channel1,
Name = item.Meta.Name,
Count = item.Meta.Total,
Ctime = mtime
});
}
}
}
}

@ -0,0 +1,672 @@
using DownKyi.Core.BiliApi.VideoStream;
using DownKyi.Core.Storage;
using DownKyi.Core.Utils;
using DownKyi.CustomControl;
using DownKyi.Events;
using DownKyi.Images;
using DownKyi.Services;
using DownKyi.Services.Download;
using DownKyi.Utils;
using DownKyi.ViewModels.PageViewModels;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
namespace DownKyi.ViewModels
{
public class ViewSeasonsSeriesViewModel : BaseViewModel
{
public const string Tag = "PageSeasonsSeries";
private readonly IDialogService dialogService;
private CancellationTokenSource tokenSource;
private long mid = -1;
private long id = -1;
private int type = 0;
// 每页视频数量,暂时在此写死,以后在设置中增加选项
private readonly int VideoNumberInPage = 30;
#region 页面属性申明
private string pageName = Tag;
public string PageName
{
get => pageName;
set => SetProperty(ref pageName, value);
}
private GifImage loading;
public GifImage Loading
{
get => loading;
set => SetProperty(ref loading, value);
}
private Visibility loadingVisibility;
public Visibility LoadingVisibility
{
get => loadingVisibility;
set => SetProperty(ref loadingVisibility, value);
}
private Visibility noDataVisibility;
public Visibility NoDataVisibility
{
get => noDataVisibility;
set => SetProperty(ref noDataVisibility, value);
}
private VectorImage arrowBack;
public VectorImage ArrowBack
{
get => arrowBack;
set => SetProperty(ref arrowBack, value);
}
private VectorImage downloadManage;
public VectorImage DownloadManage
{
get => downloadManage;
set => SetProperty(ref downloadManage, value);
}
private string title;
public string Title
{
get => title;
set => SetProperty(ref title, value);
}
private bool isEnabled = true;
public bool IsEnabled
{
get => isEnabled;
set => SetProperty(ref isEnabled, value);
}
private CustomPagerViewModel pager;
public CustomPagerViewModel Pager
{
get => pager;
set => SetProperty(ref pager, value);
}
private ObservableCollection<ChannelMedia> medias;
public ObservableCollection<ChannelMedia> Medias
{
get => medias;
set => SetProperty(ref medias, value);
}
private bool isSelectAll;
public bool IsSelectAll
{
get => isSelectAll;
set => SetProperty(ref isSelectAll, value);
}
#endregion
public ViewSeasonsSeriesViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator)
{
this.dialogService = dialogService;
#region 属性初始化
// 初始化loading gif
Loading = new GifImage(Properties.Resources.loading);
Loading.StartAnimate();
LoadingVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Collapsed;
ArrowBack = NavigationIcon.Instance().ArrowBack;
ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark");
// 下载管理按钮
DownloadManage = ButtonIcon.Instance().DownloadManage;
DownloadManage.Height = 24;
DownloadManage.Width = 24;
DownloadManage.Fill = DictionaryResource.GetColor("ColorPrimary");
Medias = new ObservableCollection<ChannelMedia>();
#endregion
}
#region 命令申明
// 返回事件
private DelegateCommand backSpaceCommand;
public DelegateCommand BackSpaceCommand => backSpaceCommand ?? (backSpaceCommand = new DelegateCommand(ExecuteBackSpace));
/// <summary>
/// 返回事件
/// </summary>
private void ExecuteBackSpace()
{
ArrowBack.Fill = DictionaryResource.GetColor("ColorText");
// 结束任务
tokenSource?.Cancel();
NavigationParam parameter = new NavigationParam
{
ViewName = ParentView,
ParentViewName = null,
Parameter = null
};
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
}
// 前往下载管理页面
private DelegateCommand downloadManagerCommand;
public DelegateCommand DownloadManagerCommand => downloadManagerCommand ?? (downloadManagerCommand = new DelegateCommand(ExecuteDownloadManagerCommand));
/// <summary>
/// 前往下载管理页面
/// </summary>
private void ExecuteDownloadManagerCommand()
{
NavigationParam parameter = new NavigationParam
{
ViewName = ViewDownloadManagerViewModel.Tag,
ParentViewName = Tag,
Parameter = null
};
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
}
// 全选按钮点击事件
private DelegateCommand<object> selectAllCommand;
public DelegateCommand<object> SelectAllCommand => selectAllCommand ?? (selectAllCommand = new DelegateCommand<object>(ExecuteSelectAllCommand));
/// <summary>
/// 全选按钮点击事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteSelectAllCommand(object parameter)
{
if (IsSelectAll)
{
foreach (var item in Medias)
{
item.IsSelected = true;
}
}
else
{
foreach (var item in Medias)
{
item.IsSelected = false;
}
}
}
// 列表选择事件
private DelegateCommand<object> mediasCommand;
public DelegateCommand<object> MediasCommand => mediasCommand ?? (mediasCommand = new DelegateCommand<object>(ExecuteMediasCommand));
/// <summary>
/// 列表选择事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteMediasCommand(object parameter)
{
if (!(parameter is IList selectedMedia)) { return; }
if (selectedMedia.Count == Medias.Count)
{
IsSelectAll = true;
}
else
{
IsSelectAll = false;
}
}
// 添加选中项到下载列表事件
private DelegateCommand addToDownloadCommand;
public DelegateCommand AddToDownloadCommand => addToDownloadCommand ?? (addToDownloadCommand = new DelegateCommand(ExecuteAddToDownloadCommand));
/// <summary>
/// 添加选中项到下载列表事件
/// </summary>
private void ExecuteAddToDownloadCommand()
{
AddToDownload(true);
}
// 添加所有视频到下载列表事件
private DelegateCommand addAllToDownloadCommand;
public DelegateCommand AddAllToDownloadCommand => addAllToDownloadCommand ?? (addAllToDownloadCommand = new DelegateCommand(ExecuteAddAllToDownloadCommand));
/// <summary>
/// 添加所有视频到下载列表事件
/// </summary>
private void ExecuteAddAllToDownloadCommand()
{
AddToDownload(false);
}
#endregion
/// <summary>
/// 添加到下载
/// </summary>
/// <param name="isOnlySelected"></param>
private async void AddToDownload(bool isOnlySelected)
{
// 频道里只有视频
AddToDownloadService addToDownloadService = new AddToDownloadService(PlayStreamType.VIDEO);
// 选择文件夹
string directory = addToDownloadService.SetDirectory(dialogService);
// 视频计数
int i = 0;
await Task.Run(() =>
{
// 为了避免执行其他操作时,
// Medias变化导致的异常
var list = Medias.ToList();
// 添加到下载
foreach (var media in list)
{
// 只下载选中项,跳过未选中项
if (isOnlySelected && !media.IsSelected) { continue; }
/// 有分P的就下载全部
// 开启服务
VideoInfoService videoInfoService = new VideoInfoService(media.Bvid);
addToDownloadService.SetVideoInfoService(videoInfoService);
addToDownloadService.GetVideo();
addToDownloadService.ParseVideo(videoInfoService);
// 下载
i += addToDownloadService.AddToDownload(eventAggregator, directory);
}
});
if (directory == null)
{
return;
}
// 通知用户添加到下载列表的结果
if (i <= 0)
{
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipAddDownloadingZero"));
}
else
{
eventAggregator.GetEvent<MessageEvent>().Publish($"{DictionaryResource.GetString("TipAddDownloadingFinished1")}{i}{DictionaryResource.GetString("TipAddDownloadingFinished2")}");
}
}
private void OnCountChanged_Pager(int count) { }
private bool OnCurrentChanged_Pager(int old, int current)
{
if (!IsEnabled)
{
//Pager.Current = old;
return false;
}
Medias.Clear();
IsSelectAll = false;
LoadingVisibility = Visibility.Visible;
NoDataVisibility = Visibility.Collapsed;
//UpdateChannel(current);
if (type == 1) { UpdateSeasons(current); }
if (type == 2) { UpdateSeries(current); }
return true;
}
//private async void UpdateChannel(int current)
//{
// // 是否正在获取数据
// // 在所有的退出分支中都需要设为true
// IsEnabled = false;
// await Task.Run(() =>
// {
// CancellationToken cancellationToken = tokenSource.Token;
// var channels = Core.BiliApi.Users.UserSpace.GetChannelVideoList(mid, cid, current, VideoNumberInPage);
// if (channels == null || channels.Count == 0)
// {
// // 没有数据UI提示
// LoadingVisibility = Visibility.Collapsed;
// NoDataVisibility = Visibility.Visible;
// return;
// }
// foreach (var video in channels)
// {
// if (video.Cid == 0)
// {
// continue;
// }
// // 查询、保存封面
// string coverUrl = video.Pic;
// BitmapImage cover;
// if (coverUrl == null || coverUrl == "")
// {
// cover = null; // new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png"));
// }
// else
// {
// if (!coverUrl.ToLower().StartsWith("http"))
// {
// coverUrl = $"https:{video.Pic}";
// }
// StorageCover storageCover = new StorageCover();
// cover = storageCover.GetCoverThumbnail(video.Aid, video.Bvid, -1, coverUrl, 200, 125);
// }
// // 播放数
// string play = string.Empty;
// if (video.Stat != null)
// {
// if (video.Stat.View > 0)
// {
// play = Format.FormatNumber(video.Stat.View);
// }
// else
// {
// play = "--";
// }
// }
// else
// {
// play = "--";
// }
// DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区
// DateTime dateCTime = startTime.AddSeconds(video.Ctime);
// string ctime = dateCTime.ToString("yyyy-MM-dd");
// App.PropertyChangeAsync(new Action(() =>
// {
// ChannelMedia media = new ChannelMedia(eventAggregator)
// {
// Avid = video.Aid,
// Bvid = video.Bvid,
// Cover = cover ?? new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")),
// Duration = Format.FormatDuration3(video.Duration),
// Title = video.Title,
// PlayNumber = play,
// CreateTime = ctime
// };
// Medias.Add(media);
// LoadingVisibility = Visibility.Collapsed;
// NoDataVisibility = Visibility.Collapsed;
// }));
// // 判断是否该结束线程若为true跳出循环
// if (cancellationToken.IsCancellationRequested)
// {
// break;
// }
// }
// }, (tokenSource = new CancellationTokenSource()).Token);
// IsEnabled = true;
//}
private async void UpdateSeasons(int current)
{
// 是否正在获取数据
// 在所有的退出分支中都需要设为true
IsEnabled = false;
await Task.Run(() =>
{
CancellationToken cancellationToken = tokenSource.Token;
var seasons = Core.BiliApi.Users.UserSpace.GetSeasonsDetail(mid, id, current, VideoNumberInPage);
if (seasons == null || seasons.Meta.Total == 0)
{
// 没有数据UI提示
LoadingVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Visible;
return;
}
foreach (var video in seasons.Archives)
{
//if (video.Cid == 0)
//{
// continue;
//}
// 查询、保存封面
string coverUrl = video.Pic;
BitmapImage cover;
if (coverUrl == null || coverUrl == "")
{
cover = null; // new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png"));
}
else
{
if (!coverUrl.ToLower().StartsWith("http"))
{
coverUrl = $"https:{video.Pic}";
}
StorageCover storageCover = new StorageCover();
cover = storageCover.GetCoverThumbnail(video.Aid, video.Bvid, -1, coverUrl, 200, 125);
}
// 播放数
string play = string.Empty;
if (video.Stat != null)
{
if (video.Stat.View > 0)
{
play = Format.FormatNumber(video.Stat.View);
}
else
{
play = "--";
}
}
else
{
play = "--";
}
DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区
DateTime dateCTime = startTime.AddSeconds(video.Ctime);
string ctime = dateCTime.ToString("yyyy-MM-dd");
App.PropertyChangeAsync(new Action(() =>
{
ChannelMedia media = new ChannelMedia(eventAggregator)
{
Avid = video.Aid,
Bvid = video.Bvid,
Cover = cover ?? new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")),
Duration = Format.FormatDuration3(video.Duration),
Title = video.Title,
PlayNumber = play,
CreateTime = ctime
};
Medias.Add(media);
LoadingVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Collapsed;
}));
// 判断是否该结束线程若为true跳出循环
if (cancellationToken.IsCancellationRequested)
{
break;
}
}
}, (tokenSource = new CancellationTokenSource()).Token);
IsEnabled = true;
}
private async void UpdateSeries(int current)
{
// 是否正在获取数据
// 在所有的退出分支中都需要设为true
IsEnabled = false;
await Task.Run(() =>
{
CancellationToken cancellationToken = tokenSource.Token;
var meta = Core.BiliApi.Users.UserSpace.GetSeriesMeta(id);
var series = Core.BiliApi.Users.UserSpace.GetSeriesDetail(mid, id, current, VideoNumberInPage);
if (series == null || meta.Meta.Total == 0)
{
// 没有数据UI提示
LoadingVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Visible;
return;
}
foreach (var video in series.Archives)
{
//if (video.Cid == 0)
//{
// continue;
//}
// 查询、保存封面
string coverUrl = video.Pic;
BitmapImage cover;
if (coverUrl == null || coverUrl == "")
{
cover = null; // new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png"));
}
else
{
if (!coverUrl.ToLower().StartsWith("http"))
{
coverUrl = $"https:{video.Pic}";
}
StorageCover storageCover = new StorageCover();
cover = storageCover.GetCoverThumbnail(video.Aid, video.Bvid, -1, coverUrl, 200, 125);
}
// 播放数
string play = string.Empty;
if (video.Stat != null)
{
if (video.Stat.View > 0)
{
play = Format.FormatNumber(video.Stat.View);
}
else
{
play = "--";
}
}
else
{
play = "--";
}
DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区
DateTime dateCTime = startTime.AddSeconds(video.Ctime);
string ctime = dateCTime.ToString("yyyy-MM-dd");
App.PropertyChangeAsync(new Action(() =>
{
ChannelMedia media = new ChannelMedia(eventAggregator)
{
Avid = video.Aid,
Bvid = video.Bvid,
Cover = cover ?? new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")),
Duration = Format.FormatDuration3(video.Duration),
Title = video.Title,
PlayNumber = play,
CreateTime = ctime
};
Medias.Add(media);
LoadingVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Collapsed;
}));
// 判断是否该结束线程若为true跳出循环
if (cancellationToken.IsCancellationRequested)
{
break;
}
}
}, (tokenSource = new CancellationTokenSource()).Token);
IsEnabled = true;
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
{
base.OnNavigatedTo(navigationContext);
ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark");
DownloadManage = ButtonIcon.Instance().DownloadManage;
DownloadManage.Height = 24;
DownloadManage.Width = 24;
DownloadManage.Fill = DictionaryResource.GetColor("ColorPrimary");
// 根据传入参数不同执行不同任务
var parameter = navigationContext.Parameters.GetValue<Dictionary<string, object>>("Parameter");
if (parameter == null)
{
return;
}
Medias.Clear();
IsSelectAll = false;
mid = (long)parameter["mid"];
id = (long)parameter["id"];
type = (int)parameter["type"];
Title = (string)parameter["name"];
int count = (int)parameter["count"];
// 页面选择
Pager = new CustomPagerViewModel(1, (int)Math.Ceiling((double)count / VideoNumberInPage));
Pager.CurrentChanged += OnCurrentChanged_Pager;
Pager.CountChanged += OnCountChanged_Pager;
Pager.Current = 1;
}
}
}

@ -220,12 +220,15 @@ namespace DownKyi.ViewModels
switch (banner.Id)
{
case 0:
case 0: // 投稿
regionManager.RequestNavigate("UserSpaceContentRegion", ViewArchiveViewModel.Tag, param);
break;
case 1:
case 1: // 频道(弃用)
regionManager.RequestNavigate("UserSpaceContentRegion", UserSpace.ViewChannelViewModel.Tag, param);
break;
case 2: // 合集和列表
regionManager.RequestNavigate("UserSpaceContentRegion", UserSpace.ViewSeasonsSeriesViewModel.Tag, param);
break;
}
}
@ -385,20 +388,38 @@ namespace DownKyi.ViewModels
}
// 频道
List<SpaceChannelList> channelList = null;
//List<SpaceChannelList> channelList = null;
//await Task.Run(() =>
//{
// channelList = Core.BiliApi.Users.UserSpace.GetChannelList(mid);
//});
//if (channelList != null && channelList.Count > 0)
//{
// TabLeftBanners.Add(new TabLeftBanner
// {
// Object = channelList,
// Id = 1,
// Icon = NormalIcon.Instance().Channel,
// IconColor = "#FF23C9ED",
// Title = DictionaryResource.GetString("Channel")
// });
//}
// 合集和列表
SpaceSeasonsSeries seasonsSeries = null;
await Task.Run(() =>
{
channelList = Core.BiliApi.Users.UserSpace.GetChannelList(mid);
seasonsSeries = Core.BiliApi.Users.UserSpace.GetSeasonsSeries(mid, 1, 20);
});
if (channelList != null && channelList.Count > 0)
if (seasonsSeries != null && seasonsSeries.Page.Total > 0)
{
TabLeftBanners.Add(new TabLeftBanner
{
Object = channelList,
Id = 1,
Object = seasonsSeries,
Id = 2,
Icon = NormalIcon.Instance().Channel,
IconColor = "#FF23C9ED",
Title = DictionaryResource.GetString("Channel")
Title = DictionaryResource.GetString("SeasonsSeries")
});
}

@ -0,0 +1,135 @@
<UserControl
x:Class="DownKyi.Views.UserSpace.ViewSeasonsSeries"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox
x:Name="nameSeasonsSeries"
ItemsSource="{Binding SeasonsSeries}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectedIndex="{Binding SelectedItem}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SeasonsSeriesCommand}" CommandParameter="{Binding ElementName=nameSeasonsSeries, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border
x:Name="Bd"
Padding="0"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<StackPanel
Grid.Row="0"
Margin="30,0,30,10"
HorizontalAlignment="Left"
Orientation="Vertical">
<Border
Width="190"
Height="119"
HorizontalAlignment="Center"
CornerRadius="5"
Cursor="Hand">
<Border.Background>
<!-- 长宽比1.6 -->
<ImageBrush ImageSource="{Binding Cover}" />
</Border.Background>
<Border
Width="70"
HorizontalAlignment="Right"
Background="{DynamicResource BrushBorderTranslucent100}"
CornerRadius="0 5 5 0">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock
FontSize="16"
Foreground="{DynamicResource BrushText}"
Text="{Binding Count}" />
<!--<Image
Height="18"
Margin="0,10,0,0"
Source="/DownKyi;component/Resources/channel.png" />-->
<ContentControl
Width="20"
Height="20"
Margin="0,10,0,0"
VerticalAlignment="Center">
<Path
Width="20"
Height="20"
Data="{Binding TypeImage.Data}"
Fill="#E5E9EF"
Stretch="Uniform" />
</ContentControl>
</StackPanel>
</Border>
</Border>
<TextBlock
MaxWidth="190"
Margin="0,5,0,0"
HorizontalAlignment="Left"
Cursor="Hand"
Text="{Binding Name}"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding Name}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource BrushPrimary}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Foreground" Value="{DynamicResource BrushTextDark}" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock
Name="nameZoneCount"
Margin="0,5,0,0"
HorizontalAlignment="Left"
Foreground="{DynamicResource BrushTextGrey2}"
Text="{Binding Ctime}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
</UserControl>

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DownKyi.Views.UserSpace
{
/// <summary>
/// ViewChannel.xaml 的交互逻辑
/// </summary>
public partial class ViewSeasonsSeries : UserControl
{
public ViewSeasonsSeries()
{
InitializeComponent();
}
}
}

@ -0,0 +1,331 @@
<UserControl
x:Class="DownKyi.Views.ViewSeasonsSeries"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:DownKyi.CustomControl"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<UserControl.Resources>
<Style x:Key="MediaListStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<StackPanel
Name="nameItemPanel"
Margin="15,15,10,5"
Cursor="Hand"
Orientation="Vertical">
<Border
Name="nameCover"
Width="190"
Height="119"
HorizontalAlignment="Center"
CornerRadius="5">
<Border.Background>
<!-- 长宽比1.6 -->
<ImageBrush ImageSource="{Binding Cover}" />
</Border.Background>
<Grid Width="190" Height="119">
<Image
Name="nameChecked"
Width="24"
Height="24"
Margin="0,10,15,0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Source="/DownKyi;component/Resources/checked.png" />
<Border
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Background="{DynamicResource BrushMask}"
CornerRadius="5 0 5 0">
<TextBlock
Name="nameDuration"
Padding="6,0"
Foreground="{DynamicResource BrushText}"
Text="{Binding Duration}" />
</Border>
</Grid>
</Border>
<TextBlock
Name="nameTitle"
Height="35"
MaxWidth="190"
Margin="0,10,0,0"
Foreground="{DynamicResource BrushTextDark}"
Tag="{Binding Bvid}"
Text="{Binding Title}"
TextTrimming="CharacterEllipsis"
TextWrapping="Wrap"
ToolTip="{Binding Title}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding TitleCommand}" CommandParameter="{Binding DataContext.PageName, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
<Grid Margin="0,3,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<Image
Width="11"
Height="11"
Source="/DownKyi;component/Resources/play.png" />
<TextBlock
Margin="5,0,0,0"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding PlayNumber}" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Image
Width="12"
Height="11"
Source="/DownKyi;component/Resources/time.png" />
<TextBlock
Margin="5,0,0,0"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding CreateTime}" />
</StackPanel>
</Grid>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="nameChecked" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="nameChecked" Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger SourceName="nameTitle" Property="IsMouseOver" Value="True">
<Setter TargetName="nameTitle" Property="Foreground" Value="{DynamicResource BrushPrimary}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="1" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="0"
Margin="10,5,0,5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding BackSpaceCommand}"
Style="{StaticResource ImageBtnStyle}">
<StackPanel Orientation="Horizontal">
<ContentControl Width="24" Height="24">
<Path
Width="{Binding ArrowBack.Width}"
Height="{Binding ArrowBack.Height}"
Data="{Binding ArrowBack.Data}"
Fill="{Binding ArrowBack.Fill}"
Stretch="None" />
</ContentControl>
<TextBlock
VerticalAlignment="Center"
FontSize="16"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource SeasonsSeries}" />
<TextBlock
VerticalAlignment="Center"
FontSize="16"
Foreground="{DynamicResource BrushTextDark}"
Text=" - ">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Title}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding Title}" Value="">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock
VerticalAlignment="Center"
FontSize="16"
Foreground="{DynamicResource BrushTextDark}"
Text="{Binding Title}" />
</StackPanel>
</Button>
<Button
Grid.Column="2"
Width="24"
Height="24"
Margin="10,5"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Command="{Binding DownloadManagerCommand}"
Style="{StaticResource ImageBtnStyle}"
ToolTip="{DynamicResource DownloadManager}">
<ContentControl>
<Path
Width="{Binding DownloadManage.Width}"
Height="{Binding DownloadManage.Height}"
Data="{Binding DownloadManage.Data}"
Fill="{Binding DownloadManage.Fill}"
Stretch="Uniform" />
</ContentControl>
</Button>
</Grid>
<TextBlock Grid.Row="1" Background="{DynamicResource BrushBorder}" />
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="1" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<ListBox
x:Name="nameMedias"
Grid.Row="0"
BorderThickness="0"
ItemContainerStyle="{StaticResource MediaListStyle}"
ItemsSource="{Binding Medias}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionMode="Extended">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding MediasCommand}" CommandParameter="{Binding ElementName=nameMedias, Path=SelectedItems}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border
x:Name="Bd"
Padding="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
</ListBox>
<!-- 加载gif -->
<StackPanel
Grid.Row="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Vertical"
Visibility="{Binding LoadingVisibility}">
<ContentControl
Width="40"
Height="40"
Content="{Binding Loading}" />
<TextBlock
Margin="0,10,0,0"
FontSize="14"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource PublicationWait}" />
</StackPanel>
<!-- 没有数据提示 -->
<Image
Grid.Row="0"
Width="256"
Height="256"
Source="/DownKyi;component/Resources/no-data.png"
Visibility="{Binding NoDataVisibility}" />
<TextBlock Grid.Row="1" Background="{DynamicResource BrushBorder}" />
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="80" />
</Grid.ColumnDefinitions>
<CheckBox
Grid.Column="0"
Margin="10,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding SelectAllCommand}"
CommandParameter="{Binding ElementName=nameMedias, Path=SelectedItem}"
Content="{DynamicResource SelectAll}"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding IsSelectAll, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
<custom:CustomPager
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
DataContext="{Binding Pager}" />
<Button
Grid.Column="2"
Margin="0,0,10,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Command="{Binding AddToDownloadCommand}"
Content="{DynamicResource DownloadSelectedPublication}"
FontSize="12"
Foreground="{DynamicResource BrushText}"
Style="{StaticResource BtnStyle}" />
<Button
Grid.Column="3"
Margin="0,0,10,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Command="{Binding AddAllToDownloadCommand}"
Content="{DynamicResource DownloadAllPublication}"
FontSize="12"
Foreground="{DynamicResource BrushText}"
Style="{StaticResource BtnStyle}" />
</Grid>
</Grid>
</Grid>
</UserControl>

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DownKyi.Views
{
/// <summary>
/// ViewChannel.xaml 的交互逻辑
/// </summary>
public partial class ViewSeasonsSeries : UserControl
{
public ViewSeasonsSeries()
{
InitializeComponent();
}
}
}
Loading…
Cancel
Save