整理代码。将models中的viewModel迁移至ViewModels中;下载列表的数据库设计;其他异常检测

croire 3 years ago
parent 158c77f951
commit fb0fcf1e7e

@ -0,0 +1,30 @@
using DownKyi.Core.BiliApi.VideoStream;
using DownKyi.Core.Storage.Database.Download;
using DownKyi.Models;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace DownKyi.Core.Test.Database
{
[TestClass]
public class BinaryTest
{
[TestMethod]
public void TestMethod1()
{
Downloading downloading = new Downloading
{
Gid = "gid",
PlayStreamType = PlayStreamType.VIDEO,
DownloadContent = "视频",
DownloadStatusTitle = "下载中",
Progress = 50,
DownloadingFileSize = "60MB/120MB",
MaxSpeed = 123456,
SpeedDisplay = "5MB/s",
};
DownloadingDb db = new DownloadingDb();
db.Insert("testId", downloading);
}
}
}

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.props')" /> <Import Project="..\packages\MSTest.TestAdapter.2.2.8\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.2.2.8\build\net45\MSTest.TestAdapter.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -40,22 +40,27 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.2.1.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath> <HintPath>..\packages\MSTest.TestFramework.2.2.8\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.2.1.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath> <HintPath>..\packages\MSTest.TestFramework.2.2.8\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="PresentationCore" />
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.112.1, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<HintPath>..\packages\System.Data.SQLite.Core.1.0.112.2\lib\net40\System.Data.SQLite.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BiliApi\UnitTest1.cs" /> <Compile Include="BiliApi\UnitTest1.cs" />
<Compile Include="BiliApi\Video\DynamicTest.cs" /> <Compile Include="BiliApi\Video\DynamicTest.cs" />
<Compile Include="BiliApi\Video\RankingTest.cs" /> <Compile Include="BiliApi\Video\RankingTest.cs" />
<Compile Include="BiliApi\Video\VideoInfoTest.cs" /> <Compile Include="BiliApi\Video\VideoInfoTest.cs" />
<Compile Include="Database\BinaryTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Test\UnitTest1.cs" /> <Compile Include="Test\UnitTest1.cs" />
</ItemGroup> </ItemGroup>
@ -72,6 +77,10 @@
<Project>{4fde0364-f65b-4812-bfe8-34e886624fbd}</Project> <Project>{4fde0364-f65b-4812-bfe8-34e886624fbd}</Project>
<Name>DownKyi.Core</Name> <Name>DownKyi.Core</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\DownKyi\DownKyi.csproj">
<Project>{97075FCD-6E8F-4FF9-B73A-994197F3765A}</Project>
<Name>DownKyi</Name>
</ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
@ -79,8 +88,10 @@
<PropertyGroup> <PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText> <ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.props'))" /> <Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.2.8\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.8\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.targets'))" /> <Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.2.8\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.8\build\net45\MSTest.TestAdapter.targets'))" />
<Error Condition="!Exists('..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets'))" />
</Target> </Target>
<Import Project="..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.targets')" /> <Import Project="..\packages\MSTest.TestAdapter.2.2.8\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.2.2.8\build\net45\MSTest.TestAdapter.targets')" />
<Import Project="..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets')" />
</Project> </Project>

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="MSTest.TestAdapter" version="2.1.1" targetFramework="net472" /> <package id="MSTest.TestAdapter" version="2.2.8" targetFramework="net472" />
<package id="MSTest.TestFramework" version="2.1.1" targetFramework="net472" /> <package id="MSTest.TestFramework" version="2.2.8" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" /> <package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" />
<package id="System.Data.SQLite.Core" version="1.0.112.2" targetFramework="net472" />
</packages> </packages>

@ -28,14 +28,16 @@ namespace DownKyi.Core.Aria2cNet.Server
ListenPort = config.ListenPort; ListenPort = config.ListenPort;
// aria目录 // aria目录
string ariaDir = Environment.CurrentDirectory + "\\aria\\"; string ariaDir = Environment.CurrentDirectory + "\\aria\\";
//string ariaDir = StorageManager.GetAriaDir();
// 会话文件 // 会话文件
#if DEBUG #if DEBUG
string sessionFile = ariaDir + "aira.session"; string sessionFile = Path.Combine(ariaDir, "aira.session");
#else #else
string sessionFile = ariaDir + "aira.session.gz"; string sessionFile =Path.Combine(ariaDir, "aira.session.gz");
#endif #endif
// 日志文件 // 日志文件
string logFile = ariaDir + "aira.log"; string logFile = Path.Combine(ariaDir, "aira.log");
// 自动保存会话文件的时间间隔 // 自动保存会话文件的时间间隔
int saveSessionInterval = 30; int saveSessionInterval = 30;

@ -1,4 +1,4 @@
namespace DownKyi.Models namespace DownKyi.Core.BiliApi.VideoStream
{ {
public enum PlayStreamType public enum PlayStreamType
{ {

@ -174,6 +174,7 @@
<Compile Include="BiliApi\VideoStream\Models\PlayUrlSupportFormat.cs" /> <Compile Include="BiliApi\VideoStream\Models\PlayUrlSupportFormat.cs" />
<Compile Include="BiliApi\VideoStream\Models\Subtitle.cs" /> <Compile Include="BiliApi\VideoStream\Models\Subtitle.cs" />
<Compile Include="BiliApi\VideoStream\Models\SubtitleInfo.cs" /> <Compile Include="BiliApi\VideoStream\Models\SubtitleInfo.cs" />
<Compile Include="BiliApi\VideoStream\PlayStreamType.cs" />
<Compile Include="BiliApi\VideoStream\VideoStream.cs" /> <Compile Include="BiliApi\VideoStream\VideoStream.cs" />
<Compile Include="BiliApi\Video\Dynamic.cs" /> <Compile Include="BiliApi\Video\Dynamic.cs" />
<Compile Include="BiliApi\Video\Models\RankingVideoView.cs" /> <Compile Include="BiliApi\Video\Models\RankingVideoView.cs" />
@ -239,6 +240,10 @@
<Compile Include="Settings\Models\VideoSettings.cs" /> <Compile Include="Settings\Models\VideoSettings.cs" />
<Compile Include="Settings\SettingsManager.cs" /> <Compile Include="Settings\SettingsManager.cs" />
<Compile Include="Storage\Constant.cs" /> <Compile Include="Storage\Constant.cs" />
<Compile Include="Storage\Database\Download\DownloadBaseDb.cs" />
<Compile Include="Storage\Database\Download\DownloadDb.cs" />
<Compile Include="Storage\Database\Download\DownloadedDb.cs" />
<Compile Include="Storage\Database\Download\DownloadingDb.cs" />
<Compile Include="Storage\Database\Header.cs" /> <Compile Include="Storage\Database\Header.cs" />
<Compile Include="Storage\Database\HeaderDb.cs" /> <Compile Include="Storage\Database\HeaderDb.cs" />
<Compile Include="Storage\StorageCover.cs" /> <Compile Include="Storage\StorageCover.cs" />

@ -10,6 +10,9 @@ namespace DownKyi.Core.Storage
// 根目录 // 根目录
private static string Root { get; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/Downkyi"; private static string Root { get; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/Downkyi";
// Aria
public static string Aria { get; } = $"{Root}/Aria";
// 日志 // 日志
public static string Logs { get; } = $"{Root}/Logs"; public static string Logs { get; } = $"{Root}/Logs";
@ -17,6 +20,7 @@ namespace DownKyi.Core.Storage
public static string Database { get; } = $"{Root}/Storage"; public static string Database { get; } = $"{Root}/Storage";
// 历史(搜索、下载) (加密) // 历史(搜索、下载) (加密)
public static string Download { get; } = $"{Database}/Download.db";
public static string History { get; } = $"{Database}/History.db"; public static string History { get; } = $"{Database}/History.db";
// 配置 // 配置

@ -8,6 +8,7 @@ namespace DownKyi.Core.Storage.Database
{ {
private const string key = "b5018ecc-09d1-4da2-aa49-4625e41e623e"; private const string key = "b5018ecc-09d1-4da2-aa49-4625e41e623e";
private readonly DbHelper dbHelper = new DbHelper(StorageManager.GetCoverIndex(), key); private readonly DbHelper dbHelper = new DbHelper(StorageManager.GetCoverIndex(), key);
private readonly string tableName = "cover";
public CoverDb() public CoverDb()
{ {
@ -30,7 +31,7 @@ namespace DownKyi.Core.Storage.Database
{ {
try try
{ {
string sql = $"insert into cover values ({cover.Avid}, '{cover.Bvid}', {cover.Cid}, '{cover.Url}', '{cover.Md5}')"; string sql = $"insert into {tableName} values ({cover.Avid}, '{cover.Bvid}', {cover.Cid}, '{cover.Url}', '{cover.Md5}')";
dbHelper.ExecuteNonQuery(sql); dbHelper.ExecuteNonQuery(sql);
} }
catch (Exception e) catch (Exception e)
@ -48,7 +49,7 @@ namespace DownKyi.Core.Storage.Database
{ {
try try
{ {
string sql = $"update cover set avid={cover.Avid}, bvid='{cover.Bvid}', cid={cover.Cid}, md5='{cover.Md5}' where url glob '{cover.Url}'"; string sql = $"update {tableName} set avid={cover.Avid}, bvid='{cover.Bvid}', cid={cover.Cid}, md5='{cover.Md5}' where url glob '{cover.Url}'";
dbHelper.ExecuteNonQuery(sql); dbHelper.ExecuteNonQuery(sql);
} }
catch (Exception e) catch (Exception e)
@ -65,7 +66,7 @@ namespace DownKyi.Core.Storage.Database
/// <returns></returns> /// <returns></returns>
public List<Cover> QueryAll() public List<Cover> QueryAll()
{ {
string sql = $"select * from cover"; string sql = $"select * from {tableName}";
return Query(sql); return Query(sql);
} }
@ -76,17 +77,10 @@ namespace DownKyi.Core.Storage.Database
/// <returns></returns> /// <returns></returns>
public Cover QueryByUrl(string url) public Cover QueryByUrl(string url)
{ {
string sql = $"select * from cover where url glob '{url}'"; string sql = $"select * from {tableName} where url glob '{url}'";
var query = Query(sql); List<Cover> query = Query(sql);
if (query.Count > 0) return query.Count > 0 ? query[0] : null;
{
return query[0];
}
else
{
return null;
}
} }
/// <summary> /// <summary>
@ -96,7 +90,7 @@ namespace DownKyi.Core.Storage.Database
/// <returns></returns> /// <returns></returns>
public Cover QueryByMd5(string md5) public Cover QueryByMd5(string md5)
{ {
string sql = $"select * from cover where md5 glob '{md5}'"; string sql = $"select * from {tableName} where md5 glob '{md5}'";
var query = Query(sql); var query = Query(sql);
if (query.Count > 0) if (query.Count > 0)
@ -141,7 +135,7 @@ namespace DownKyi.Core.Storage.Database
/// </summary> /// </summary>
private void CreateTable() private void CreateTable()
{ {
string sql = "create table if not exists cover (avid unsigned big int, bvid varchar(20), cid unsigned big int, url varchar(255) unique, md5 varchar(32) unique)"; string sql = $"create table if not exists {tableName} (avid unsigned big int, bvid varchar(20), cid unsigned big int, url varchar(255) unique, md5 varchar(32) unique)";
dbHelper.ExecuteNonQuery(sql); dbHelper.ExecuteNonQuery(sql);
} }

@ -64,7 +64,7 @@ namespace DownKyi.Core.Storage.Database
/// 执行一条SQL语句 /// 执行一条SQL语句
/// </summary> /// </summary>
/// <param name="sql"></param> /// <param name="sql"></param>
public void ExecuteNonQuery(string sql) public void ExecuteNonQuery(string sql, Action<SQLiteParameterCollection> action = null)
{ {
lock (conn) lock (conn)
{ {
@ -74,6 +74,8 @@ namespace DownKyi.Core.Storage.Database
using (var command = conn.CreateCommand()) using (var command = conn.CreateCommand())
{ {
command.CommandText = sql; command.CommandText = sql;
// 添加参数
action?.Invoke(command.Parameters);
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }
tr.Commit(); tr.Commit();

@ -0,0 +1,11 @@
namespace DownKyi.Core.Storage.Database.Download
{
public class DownloadBaseDb : DownloadDb
{
public DownloadBaseDb()
{
tableName = "download_base";
CreateTable();
}
}
}

@ -0,0 +1,99 @@
using DownKyi.Core.Logging;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace DownKyi.Core.Storage.Database.Download
{
public class DownloadDb
{
private const string key = "bdb8eb69-3698-4af9-b722-9312d0fba623";
private readonly DbHelper dbHelper = new DbHelper(StorageManager.GetDownload());
//private readonly DbHelper dbHelper = new DbHelper(StorageManager.GetDownload(), key);
protected string tableName = "download";
//public DownloadDb()
//{
// CreateTable();
//}
/// <summary>
/// 关闭数据库连接
/// </summary>
public void Close()
{
dbHelper.Close();
}
/// <summary>
/// 插入新的数据
/// </summary>
/// <param name="obj"></param>
public void Insert(string uuid, object obj)
{
// 定义一个流
Stream stream = new MemoryStream();
// 定义一个格式化器
BinaryFormatter formatter = new BinaryFormatter();
// 序列化
formatter.Serialize(stream, obj);
byte[] array = null;
array = new byte[stream.Length];
//将二进制流写入数组
stream.Position = 0;
stream.Read(array, 0, (int)stream.Length);
//关闭流
stream.Close();
try
{
string sql = $"insert into {tableName}(id, data) values (@id, @data)";
dbHelper.ExecuteNonQuery(sql, new Action<SQLiteParameterCollection>((para) =>
{
para.Add("@id", DbType.String).Value = uuid;
para.Add("@data", DbType.Binary).Value = array;
}));
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("Insert()发生异常: {0}", e);
LogManager.Error("DownloadingDb", e);
}
}
/// <summary>
/// 查询所有数据
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
public Dictionary<string, object> QueryAll(string sql)
{
Dictionary<string, object> objects = new Dictionary<string, object>();
dbHelper.ExecuteQuery(sql, reader =>
{
while (reader.Read())
{
objects.Add((string)reader["id"], reader["data"]);
}
});
return objects;
}
/// <summary>
/// 如果表不存在则创建表
/// </summary>
protected void CreateTable()
{
string sql = $"create table if not exists {tableName} (id varchar(255), data blob)";
dbHelper.ExecuteNonQuery(sql);
}
}
}

@ -0,0 +1,11 @@
namespace DownKyi.Core.Storage.Database.Download
{
public class DownloadedDb : DownloadDb
{
public DownloadedDb()
{
tableName = "downloaded";
CreateTable();
}
}
}

@ -0,0 +1,11 @@
namespace DownKyi.Core.Storage.Database.Download
{
public class DownloadingDb : DownloadDb
{
public DownloadingDb()
{
tableName = "downloading";
CreateTable();
}
}
}

@ -8,6 +8,7 @@ namespace DownKyi.Core.Storage.Database
{ {
private const string key = "7c1f1f40-7cdf-4d11-ad28-f0137a3c5308"; private const string key = "7c1f1f40-7cdf-4d11-ad28-f0137a3c5308";
private readonly DbHelper dbHelper = new DbHelper(StorageManager.GetHeaderIndex(), key); private readonly DbHelper dbHelper = new DbHelper(StorageManager.GetHeaderIndex(), key);
private readonly string tableName = "header";
public HeaderDb() public HeaderDb()
{ {
@ -30,7 +31,7 @@ namespace DownKyi.Core.Storage.Database
{ {
try try
{ {
string sql = $"insert into header values ({header.Mid}, '{header.Name}', '{header.Url}', '{header.Md5}')"; string sql = $"insert into {tableName} values ({header.Mid}, '{header.Name}', '{header.Url}', '{header.Md5}')";
dbHelper.ExecuteNonQuery(sql); dbHelper.ExecuteNonQuery(sql);
} }
catch (Exception e) catch (Exception e)
@ -48,7 +49,7 @@ namespace DownKyi.Core.Storage.Database
{ {
try try
{ {
string sql = $"update header set name='{header.Name}', url='{header.Url}', md5='{header.Md5}' where mid={header.Mid}"; string sql = $"update {tableName} set name='{header.Name}', url='{header.Url}', md5='{header.Md5}' where mid={header.Mid}";
dbHelper.ExecuteNonQuery(sql); dbHelper.ExecuteNonQuery(sql);
} }
catch (Exception e) catch (Exception e)
@ -64,7 +65,7 @@ namespace DownKyi.Core.Storage.Database
/// <returns></returns> /// <returns></returns>
public List<Header> QueryAll() public List<Header> QueryAll()
{ {
string sql = $"select * from header"; string sql = $"select * from {tableName}";
return Query(sql); return Query(sql);
} }
@ -75,17 +76,10 @@ namespace DownKyi.Core.Storage.Database
/// <returns></returns> /// <returns></returns>
public Header QueryByMid(long mid) public Header QueryByMid(long mid)
{ {
string sql = $"select * from header where mid={mid}"; string sql = $"select * from {tableName} where mid={mid}";
var query = Query(sql); List<Header> query = Query(sql);
if (query.Count > 0) return query.Count > 0 ? query[0] : null;
{
return query[0];
}
else
{
return null;
}
} }
@ -120,7 +114,7 @@ namespace DownKyi.Core.Storage.Database
/// </summary> /// </summary>
private void CreateTable() private void CreateTable()
{ {
string sql = "create table if not exists header (mid unsigned big int unique, name varchar(255), url varchar(255), md5 varchar(32))"; string sql = $"create table if not exists {tableName} (mid unsigned big int unique, name varchar(255), url varchar(255), md5 varchar(32))";
dbHelper.ExecuteNonQuery(sql); dbHelper.ExecuteNonQuery(sql);
} }

@ -4,6 +4,26 @@ namespace DownKyi.Core.Storage
{ {
public static class StorageManager public static class StorageManager
{ {
/// <summary>
/// 获取历史记录的文件路径
/// </summary>
/// <returns></returns>
public static string GetAriaDir()
{
CreateDirectory(Constant.Aria);
return Constant.Aria;
}
/// <summary>
/// 获取历史记录的文件路径
/// </summary>
/// <returns></returns>
public static string GetDownload()
{
CreateDirectory(Constant.Database);
return Constant.Download;
}
/// <summary> /// <summary>
/// 获取历史记录的文件路径 /// 获取历史记录的文件路径
/// </summary> /// </summary>

@ -1,4 +1,5 @@
using DownKyi.Models; using DownKyi.Core.Settings;
using DownKyi.Models;
using DownKyi.Services.Download; using DownKyi.Services.Download;
using DownKyi.Utils; using DownKyi.Utils;
using DownKyi.ViewModels; using DownKyi.ViewModels;
@ -13,7 +14,9 @@ using DownKyi.Views.Settings;
using DownKyi.Views.Toolbox; using DownKyi.Views.Toolbox;
using Prism.Ioc; using Prism.Ioc;
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
using System.Windows; using System.Windows;
namespace DownKyi namespace DownKyi
@ -104,5 +107,39 @@ namespace DownKyi
Current.Dispatcher.Invoke(callback); Current.Dispatcher.Invoke(callback);
} }
/// <summary>
/// 下载完成列表排序
/// </summary>
/// <param name="finishedSort"></param>
public static void SortDownloadedList(DownloadFinishedSort finishedSort)
{
List<DownloadedItem> list = DownloadedList.ToList();
switch (finishedSort)
{
case DownloadFinishedSort.DOWNLOAD:
// 按下载先后排序
list.Sort((x, y) => { return x.Downloaded.FinishedTimestamp.CompareTo(y.Downloaded.FinishedTimestamp); });
break;
case DownloadFinishedSort.NUMBER:
// 按序号排序
list.Sort((x, y) =>
{
int compare = x.MainTitle.CompareTo(y.MainTitle);
return compare == 0 ? x.Order.CompareTo(y.Order) : compare;
});
break;
default:
break;
}
// 更新下载完成列表
// 如果有更好的方法再重写
DownloadedList.Clear();
foreach (DownloadedItem item in list)
{
DownloadedList.Add(item);
}
}
} }
} }

@ -88,20 +88,19 @@
<Compile Include="Images\LogoIcon.cs" /> <Compile Include="Images\LogoIcon.cs" />
<Compile Include="Images\NavigationIcon.cs" /> <Compile Include="Images\NavigationIcon.cs" />
<Compile Include="Images\NormalIcon.cs" /> <Compile Include="Images\NormalIcon.cs" />
<Compile Include="Models\DownloadBaseItem.cs" /> <Compile Include="Models\DownloadBase.cs" />
<Compile Include="Models\DownloadedItem.cs" /> <Compile Include="Models\Downloaded.cs" />
<Compile Include="Models\DownloadingItem.cs" /> <Compile Include="Models\Downloading.cs" />
<Compile Include="Models\DownloadStatus.cs" /> <Compile Include="Models\DownloadStatus.cs" />
<Compile Include="Models\Favorites.cs" /> <Compile Include="ViewModels\PageViewModels\Favorites.cs" />
<Compile Include="Models\FavoritesMedia.cs" /> <Compile Include="ViewModels\PageViewModels\FavoritesMedia.cs" />
<Compile Include="Models\DisplayFileNamePart.cs" /> <Compile Include="ViewModels\Settings\DisplayFileNamePart.cs" />
<Compile Include="Models\ParseScopeDisplay.cs" /> <Compile Include="Models\ParseScopeDisplay.cs" />
<Compile Include="Models\PlayStreamType.cs" /> <Compile Include="ViewModels\PageViewModels\TabHeader.cs" />
<Compile Include="Models\TabHeader.cs" /> <Compile Include="ViewModels\PageViewModels\VideoQuality.cs" />
<Compile Include="Models\VideoQuality.cs" /> <Compile Include="ViewModels\PageViewModels\VideoInfoView.cs" />
<Compile Include="Models\VideoInfoView.cs" /> <Compile Include="ViewModels\PageViewModels\VideoPage.cs" />
<Compile Include="Models\VideoPage.cs" /> <Compile Include="ViewModels\PageViewModels\VideoSection.cs" />
<Compile Include="Models\VideoSection.cs" />
<Compile Include="Services\BangumiInfoService.cs" /> <Compile Include="Services\BangumiInfoService.cs" />
<Compile Include="Services\CheeseInfoService.cs" /> <Compile Include="Services\CheeseInfoService.cs" />
<Compile Include="Services\Download\AriaDownloadService.cs" /> <Compile Include="Services\Download\AriaDownloadService.cs" />
@ -119,6 +118,9 @@
<Compile Include="ViewModels\BaseViewModel.cs" /> <Compile Include="ViewModels\BaseViewModel.cs" />
<Compile Include="ViewModels\Dialogs\ViewDownloadSetterViewModel.cs" /> <Compile Include="ViewModels\Dialogs\ViewDownloadSetterViewModel.cs" />
<Compile Include="ViewModels\Dialogs\BaseDialogViewModel.cs" /> <Compile Include="ViewModels\Dialogs\BaseDialogViewModel.cs" />
<Compile Include="ViewModels\DownloadManager\DownloadBaseItem.cs" />
<Compile Include="ViewModels\DownloadManager\DownloadedItem.cs" />
<Compile Include="ViewModels\DownloadManager\DownloadingItem.cs" />
<Compile Include="ViewModels\Settings\ViewBasicViewModel.cs" /> <Compile Include="ViewModels\Settings\ViewBasicViewModel.cs" />
<Compile Include="ViewModels\Settings\ViewAboutViewModel.cs" /> <Compile Include="ViewModels\Settings\ViewAboutViewModel.cs" />
<Compile Include="ViewModels\Settings\ViewDanmakuViewModel.cs" /> <Compile Include="ViewModels\Settings\ViewDanmakuViewModel.cs" />

@ -7,29 +7,29 @@ namespace DownKyi.Images
private double width; private double width;
public double Width public double Width
{ {
get { return width; } get => width;
set { SetProperty(ref width, value); } set => SetProperty(ref width, value);
} }
private double height; private double height;
public double Height public double Height
{ {
get { return height; } get => height;
set { SetProperty(ref height, value); } set => SetProperty(ref height, value);
} }
private string data; private string data;
public string Data public string Data
{ {
get { return data; } get => data;
set { SetProperty(ref data, value); } set => SetProperty(ref data, value);
} }
private string fill; private string fill;
public string Fill public string Fill
{ {
get { return fill; } get => fill;
set { SetProperty(ref fill, value); } set => SetProperty(ref fill, value);
} }
} }

@ -91,6 +91,12 @@
<system:String x:Key="ContinueAllDownloading">全部开始</system:String> <system:String x:Key="ContinueAllDownloading">全部开始</system:String>
<system:String x:Key="DeleteAllDownloading">全部删除</system:String> <system:String x:Key="DeleteAllDownloading">全部删除</system:String>
<system:String x:Key="TotalDownloaded1">已下载</system:String>
<system:String x:Key="TotalDownloaded2">个视频!</system:String>
<system:String x:Key="DownloadedSortByTime">按下载先后排序</system:String>
<system:String x:Key="DownloadedSortByOrder">按序号排序</system:String>
<system:String x:Key="ClearAllDownloaded">清空所有记录</system:String>
<!-- Settings --> <!-- Settings -->
<system:String x:Key="PressEnterToApplySettingTip">按回车键应用设置</system:String> <system:String x:Key="PressEnterToApplySettingTip">按回车键应用设置</system:String>

@ -0,0 +1,75 @@
using DownKyi.Core.BiliApi.BiliUtils;
using System;
using System.Collections.Generic;
namespace DownKyi.Models
{
[Serializable]
public class DownloadBase
{
public DownloadBase()
{
// 唯一id
Uuid = Guid.NewGuid().ToString("N");
// 初始化需要下载的内容
NeedDownloadContent = new Dictionary<string, bool>
{
{ "downloadAudio", true },
{ "downloadVideo", true },
{ "downloadDanmaku", true },
{ "downloadSubtitle", true },
{ "downloadCover", true }
};
}
// 此条下载项的id
public string Uuid { get; }
// 需要下载的内容
public Dictionary<string, bool> NeedDownloadContent { get; private set; }
// 视频的id
public string Bvid { get; set; }
public long Avid { get; set; }
public long Cid { get; set; }
public long EpisodeId { get; set; }
// 视频封面的url
public string CoverUrl { get; set; }
// 视频page的封面的url
public string PageCoverUrl { get; set; }
// 分区id
public int ZoneId { get; set; }
// 视频序号
public int Order { get; set; }
// 视频主标题
public string MainTitle { get; set; }
// 视频标题
public string Name { get; set; }
// 时长
public string Duration { get; set; }
// 视频编码名称AVC、HEVC
public string VideoCodecName { get; set; }
// 视频画质
public Quality Resolution { get; set; }
// 音频编码
public Quality AudioCodec { get; set; }
// 文件路径,不包含扩展名,所有内容均以此路径下载
public string FilePath { get; set; }
// 文件大小
public string FileSize { get; set; }
}
}

@ -1,125 +0,0 @@
using DownKyi.Core.BiliApi.BiliUtils;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Windows.Media;
namespace DownKyi.Models
{
public class DownloadBaseItem : BindableBase
{
public DownloadBaseItem()
{
// 唯一id
Uuid = Guid.NewGuid().ToString("N");
// 初始化需要下载的内容
NeedDownloadContent = new Dictionary<string, bool>
{
{ "downloadAudio", true },
{ "downloadVideo", true },
{ "downloadDanmaku", true },
{ "downloadSubtitle", true },
{ "downloadCover", true }
};
}
// 此条下载项的id
public string Uuid { get; }
// 需要下载的内容
public Dictionary<string, bool> NeedDownloadContent { get; private set; }
// 视频的id
public string Bvid { get; set; }
public long Avid { get; set; }
public long Cid { get; set; }
public long EpisodeId { get; set; }
// 视频封面的url
public string CoverUrl { get; set; }
// 视频page的封面的url
public string PageCoverUrl { get; set; }
private DrawingImage zoneImage;
public DrawingImage ZoneImage
{
get => zoneImage;
set => SetProperty(ref zoneImage, value);
}
// 视频序号
private int order;
public int Order
{
get => order;
set => SetProperty(ref order, value);
}
// 视频主标题
private string mainTitle;
public string MainTitle
{
get => mainTitle;
set => SetProperty(ref mainTitle, value);
}
// 视频标题
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
// 时长
private string duration;
public string Duration
{
get => duration;
set => SetProperty(ref duration, value);
}
// 视频编码
// "hev1.2.4.L156.90"
// "avc1.640034"
//public string VideoCodecId { get; set; }
// 视频编码名称AVC、HEVC
private string videoCodecName;
public string VideoCodecName
{
get => videoCodecName;
set => SetProperty(ref videoCodecName, value);
}
// 视频画质
private Quality resolution;
public Quality Resolution
{
get => resolution;
set => SetProperty(ref resolution, value);
}
// 音频编码
private Quality audioCodec;
public Quality AudioCodec
{
get => audioCodec;
set => SetProperty(ref audioCodec, value);
}
// 文件路径,不包含扩展名,所有内容均以此路径下载
public string FilePath { get; set; }
// 文件大小
private string fileSize;
public string FileSize
{
get => fileSize;
set => SetProperty(ref fileSize, value);
}
}
}

@ -0,0 +1,30 @@
using System;
namespace DownKyi.Models
{
[Serializable]
public class Downloaded// : DownloadBase
{
public Downloaded() : base()
{
}
// 下载速度
public string MaxSpeedDisplay { get; set; }
// 完成时间戳
public long FinishedTimestamp { get; set; }
public void SetFinishedTimestamp(long finishedTimestamp)
{
FinishedTimestamp = finishedTimestamp;
DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区
DateTime dateTime = startTime.AddSeconds(finishedTimestamp);
FinishedTime = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
}
// 完成时间
public string FinishedTime { get; set; }
}
}

@ -1,9 +0,0 @@
namespace DownKyi.Models
{
public class DownloadedItem : DownloadBaseItem
{
public DownloadedItem() : base()
{
}
}
}

@ -0,0 +1,47 @@
using DownKyi.Core.BiliApi.VideoStream;
using System;
using System.Collections.Generic;
namespace DownKyi.Models
{
[Serializable]
public class Downloading// : DownloadBase
{
public Downloading() : base()
{
// 初始化下载的文件列表
DownloadFiles = new List<string>();
}
// Aria相关
public string Gid { get; set; }
// 下载的文件
public List<string> DownloadFiles { get; private set; }
// 视频类别
public PlayStreamType PlayStreamType { get; set; }
// 下载状态
public DownloadStatus DownloadStatus { get; set; }
// 正在下载内容(音频、视频、弹幕、字幕、封面)
public string DownloadContent { get; set; }
// 下载状态显示
public string DownloadStatusTitle { get; set; }
// 下载进度
public float Progress { get; set; }
// 已下载大小/文件大小
public string DownloadingFileSize { get; set; }
// 下载的最高速度
public long MaxSpeed { get; set; }
// 下载速度
public string SpeedDisplay { get; set; }
}
}

@ -2,10 +2,11 @@
using DownKyi.Core.BiliApi.Bangumi.Models; using DownKyi.Core.BiliApi.Bangumi.Models;
using DownKyi.Core.BiliApi.BiliUtils; using DownKyi.Core.BiliApi.BiliUtils;
using DownKyi.Core.BiliApi.VideoStream; using DownKyi.Core.BiliApi.VideoStream;
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.Storage; using DownKyi.Core.Storage;
using DownKyi.Core.Utils; using DownKyi.Core.Utils;
using DownKyi.Models;
using DownKyi.Utils; using DownKyi.Utils;
using DownKyi.ViewModels.PageViewModels;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@ -39,7 +40,7 @@ namespace DownKyi.Services
if (ParseEntrance.IsBangumiMediaId(input) || ParseEntrance.IsBangumiMediaUrl(input)) if (ParseEntrance.IsBangumiMediaId(input) || ParseEntrance.IsBangumiMediaUrl(input))
{ {
long mediaId = ParseEntrance.GetBangumiMediaId(input); long mediaId = ParseEntrance.GetBangumiMediaId(input);
var bangumiMedia = BangumiInfo.BangumiMediaInfo(mediaId); BangumiMedia bangumiMedia = BangumiInfo.BangumiMediaInfo(mediaId);
bangumiSeason = BangumiInfo.BangumiSeasonInfo(bangumiMedia.SeasonId); bangumiSeason = BangumiInfo.BangumiSeasonInfo(bangumiMedia.SeasonId);
} }
} }
@ -56,7 +57,7 @@ namespace DownKyi.Services
if (bangumiSeason.Episodes.Count == 0) { return pages; } if (bangumiSeason.Episodes.Count == 0) { return pages; }
int order = 0; int order = 0;
foreach (var episode in bangumiSeason.Episodes) foreach (BangumiEpisode episode in bangumiSeason.Episodes)
{ {
order++; order++;
@ -125,25 +126,16 @@ namespace DownKyi.Services
} }
}; };
foreach (var section in bangumiSeason.Section) foreach (BangumiSection section in bangumiSeason.Section)
{ {
List<VideoPage> pages = new List<VideoPage>(); List<VideoPage> pages = new List<VideoPage>();
int order = 0; int order = 0;
foreach (var episode in section.Episodes) foreach (BangumiEpisode episode in section.Episodes)
{ {
order++; order++;
// 标题 // 标题
string name; string name = episode.LongTitle != null && episode.LongTitle != "" ? $"{episode.Title} {episode.LongTitle}" : episode.Title;
if (episode.LongTitle != null && episode.LongTitle != "")
{
name = $"{episode.Title} {episode.LongTitle}";
}
else
{
name = episode.Title;
}
VideoPage page = new VideoPage VideoPage page = new VideoPage
{ {
Avid = episode.Aid, Avid = episode.Aid,
@ -176,7 +168,7 @@ namespace DownKyi.Services
/// <param name="page"></param> /// <param name="page"></param>
public void GetVideoStream(VideoPage page) public void GetVideoStream(VideoPage page)
{ {
var playUrl = VideoStream.GetBangumiPlayUrl(page.Avid, page.Bvid, page.Cid); PlayUrl playUrl = VideoStream.GetBangumiPlayUrl(page.Avid, page.Bvid, page.Cid);
Utils.VideoPageInfo(playUrl, page); Utils.VideoPageInfo(playUrl, page);
} }

@ -2,10 +2,11 @@
using DownKyi.Core.BiliApi.Cheese; using DownKyi.Core.BiliApi.Cheese;
using DownKyi.Core.BiliApi.Cheese.Models; using DownKyi.Core.BiliApi.Cheese.Models;
using DownKyi.Core.BiliApi.VideoStream; using DownKyi.Core.BiliApi.VideoStream;
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.Storage; using DownKyi.Core.Storage;
using DownKyi.Core.Utils; using DownKyi.Core.Utils;
using DownKyi.Models;
using DownKyi.Utils; using DownKyi.Utils;
using DownKyi.ViewModels.PageViewModels;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
@ -48,7 +49,7 @@ namespace DownKyi.Services
if (cheeseView.Episodes.Count == 0) { return pages; } if (cheeseView.Episodes.Count == 0) { return pages; }
int order = 0; int order = 0;
foreach (var episode in cheeseView.Episodes) foreach (CheeseEpisode episode in cheeseView.Episodes)
{ {
order++; order++;
string name = episode.Title; string name = episode.Title;
@ -87,7 +88,7 @@ namespace DownKyi.Services
/// <param name="page"></param> /// <param name="page"></param>
public void GetVideoStream(VideoPage page) public void GetVideoStream(VideoPage page)
{ {
var playUrl = VideoStream.GetCheesePlayUrl(page.Avid, page.Bvid, page.Cid, page.EpisodeId); PlayUrl playUrl = VideoStream.GetCheesePlayUrl(page.Avid, page.Bvid, page.Cid, page.EpisodeId);
Utils.VideoPageInfo(playUrl, page); Utils.VideoPageInfo(playUrl, page);
} }

@ -13,6 +13,7 @@ using DownKyi.Core.Storage;
using DownKyi.Core.Utils; using DownKyi.Core.Utils;
using DownKyi.Models; using DownKyi.Models;
using DownKyi.Utils; using DownKyi.Utils;
using DownKyi.ViewModels.DownloadManager;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -118,14 +119,14 @@ namespace DownKyi.Services.Download
if (downloadVideo.BackupUrl != null) { urls.AddRange(downloadVideo.BackupUrl); } if (downloadVideo.BackupUrl != null) { urls.AddRange(downloadVideo.BackupUrl); }
// 路径 // 路径
string[] temp = downloading.FilePath.Split('/'); string[] temp = downloading.DownloadBase.FilePath.Split('/');
string path = downloading.FilePath.Replace(temp[temp.Length - 1], ""); string path = downloading.DownloadBase.FilePath.Replace(temp[temp.Length - 1], "");
// 下载文件名 // 下载文件名
string fileName = Guid.NewGuid().ToString("N"); string fileName = Guid.NewGuid().ToString("N");
// 记录本次下载的文件 // 记录本次下载的文件
downloading.DownloadFiles.Add(fileName); downloading.Downloading.DownloadFiles.Add(fileName);
// 开始下载 // 开始下载
DownloadResult downloadStatus = DownloadByAria(downloading, urls, path, fileName); DownloadResult downloadStatus = DownloadByAria(downloading, urls, path, fileName);
@ -160,7 +161,7 @@ namespace DownKyi.Services.Download
// 查询、保存封面 // 查询、保存封面
StorageCover storageCover = new StorageCover(); StorageCover storageCover = new StorageCover();
string cover = storageCover.GetCover(downloading.Avid, downloading.Bvid, downloading.Cid, coverUrl); string cover = storageCover.GetCover(downloading.DownloadBase.Avid, downloading.DownloadBase.Bvid, downloading.DownloadBase.Cid, coverUrl);
if (cover == null) if (cover == null)
{ {
return null; return null;
@ -172,7 +173,7 @@ namespace DownKyi.Services.Download
File.Copy(cover, fileName, true); File.Copy(cover, fileName, true);
// 记录本次下载的文件 // 记录本次下载的文件
downloading.DownloadFiles.Add(fileName); downloading.Downloading.DownloadFiles.Add(fileName);
return fileName; return fileName;
} }
@ -200,10 +201,10 @@ namespace DownKyi.Services.Download
downloading.SpeedDisplay = string.Empty; downloading.SpeedDisplay = string.Empty;
string title = $"{downloading.Name}"; string title = $"{downloading.Name}";
string assFile = $"{downloading.FilePath}.ass"; string assFile = $"{downloading.DownloadBase.FilePath}.ass";
// 记录本次下载的文件 // 记录本次下载的文件
downloading.DownloadFiles.Add(assFile); downloading.Downloading.DownloadFiles.Add(assFile);
int screenWidth = SettingsManager.GetInstance().GetDanmakuScreenWidth(); int screenWidth = SettingsManager.GetInstance().GetDanmakuScreenWidth();
int screenHeight = SettingsManager.GetInstance().GetDanmakuScreenHeight(); int screenHeight = SettingsManager.GetInstance().GetDanmakuScreenHeight();
@ -236,7 +237,7 @@ namespace DownKyi.Services.Download
.SetTopFilter(SettingsManager.GetInstance().GetDanmakuTopFilter() == AllowStatus.YES) .SetTopFilter(SettingsManager.GetInstance().GetDanmakuTopFilter() == AllowStatus.YES)
.SetBottomFilter(SettingsManager.GetInstance().GetDanmakuBottomFilter() == AllowStatus.YES) .SetBottomFilter(SettingsManager.GetInstance().GetDanmakuBottomFilter() == AllowStatus.YES)
.SetScrollFilter(SettingsManager.GetInstance().GetDanmakuScrollFilter() == AllowStatus.YES) .SetScrollFilter(SettingsManager.GetInstance().GetDanmakuScrollFilter() == AllowStatus.YES)
.Create(downloading.Avid, downloading.Cid, subtitleConfig, assFile); .Create(downloading.DownloadBase.Avid, downloading.DownloadBase.Cid, subtitleConfig, assFile);
return assFile; return assFile;
} }
@ -257,7 +258,7 @@ namespace DownKyi.Services.Download
List<string> srtFiles = new List<string>(); List<string> srtFiles = new List<string>();
var subRipTexts = VideoStream.GetSubtitle(downloading.Avid, downloading.Bvid, downloading.Cid); var subRipTexts = VideoStream.GetSubtitle(downloading.DownloadBase.Avid, downloading.DownloadBase.Bvid, downloading.DownloadBase.Cid);
if (subRipTexts == null) if (subRipTexts == null)
{ {
return null; return null;
@ -265,13 +266,13 @@ namespace DownKyi.Services.Download
foreach (var subRip in subRipTexts) foreach (var subRip in subRipTexts)
{ {
string srtFile = $"{downloading.FilePath}_{subRip.LanDoc}.srt"; string srtFile = $"{downloading.DownloadBase.FilePath}_{subRip.LanDoc}.srt";
try try
{ {
File.WriteAllText(srtFile, subRip.SrtString); File.WriteAllText(srtFile, subRip.SrtString);
// 记录本次下载的文件 // 记录本次下载的文件
downloading.DownloadFiles.Add(srtFile); downloading.Downloading.DownloadFiles.Add(srtFile);
srtFiles.Add(srtFile); srtFiles.Add(srtFile);
} }
@ -302,10 +303,10 @@ namespace DownKyi.Services.Download
// 下载速度 // 下载速度
downloading.SpeedDisplay = string.Empty; downloading.SpeedDisplay = string.Empty;
string finalFile = $"{downloading.FilePath}.mp4"; string finalFile = $"{downloading.DownloadBase.FilePath}.mp4";
if (videoUid == null) if (videoUid == null)
{ {
finalFile = $"{downloading.FilePath}.aac"; finalFile = $"{downloading.DownloadBase.FilePath}.aac";
} }
// 合并音视频 // 合并音视频
@ -339,22 +340,22 @@ namespace DownKyi.Services.Download
// 下载速度 // 下载速度
downloading.SpeedDisplay = string.Empty; downloading.SpeedDisplay = string.Empty;
if (downloading.PlayUrl != null && downloading.DownloadStatus == DownloadStatus.NOT_STARTED) if (downloading.PlayUrl != null && downloading.Downloading.DownloadStatus == DownloadStatus.NOT_STARTED)
{ {
return; return;
} }
// 解析 // 解析
switch (downloading.PlayStreamType) switch (downloading.Downloading.PlayStreamType)
{ {
case PlayStreamType.VIDEO: case PlayStreamType.VIDEO:
downloading.PlayUrl = VideoStream.GetVideoPlayUrl(downloading.Avid, downloading.Bvid, downloading.Cid); downloading.PlayUrl = VideoStream.GetVideoPlayUrl(downloading.DownloadBase.Avid, downloading.DownloadBase.Bvid, downloading.DownloadBase.Cid);
break; break;
case PlayStreamType.BANGUMI: case PlayStreamType.BANGUMI:
downloading.PlayUrl = VideoStream.GetBangumiPlayUrl(downloading.Avid, downloading.Bvid, downloading.Cid); downloading.PlayUrl = VideoStream.GetBangumiPlayUrl(downloading.DownloadBase.Avid, downloading.DownloadBase.Bvid, downloading.DownloadBase.Cid);
break; break;
case PlayStreamType.CHEESE: case PlayStreamType.CHEESE:
downloading.PlayUrl = VideoStream.GetCheesePlayUrl(downloading.Avid, downloading.Bvid, downloading.Cid, downloading.EpisodeId); downloading.PlayUrl = VideoStream.GetCheesePlayUrl(downloading.DownloadBase.Avid, downloading.DownloadBase.Bvid, downloading.DownloadBase.Cid, downloading.DownloadBase.EpisodeId);
break; break;
default: default:
break; break;
@ -399,7 +400,7 @@ namespace DownKyi.Services.Download
int downloadingCount = 0; int downloadingCount = 0;
foreach (DownloadingItem downloading in downloadingList) foreach (DownloadingItem downloading in downloadingList)
{ {
if (downloading.DownloadStatus == DownloadStatus.DOWNLOADING) if (downloading.Downloading.DownloadStatus == DownloadStatus.DOWNLOADING)
{ {
downloadingCount++; downloadingCount++;
} }
@ -413,7 +414,7 @@ namespace DownKyi.Services.Download
} }
// 开始下载 // 开始下载
if (downloading.DownloadStatus == DownloadStatus.NOT_STARTED || downloading.DownloadStatus == DownloadStatus.WAIT_FOR_DOWNLOAD) if (downloading.Downloading.DownloadStatus == DownloadStatus.NOT_STARTED || downloading.Downloading.DownloadStatus == DownloadStatus.WAIT_FOR_DOWNLOAD)
{ {
SingleDownload(downloading); SingleDownload(downloading);
downloadingCount++; downloadingCount++;
@ -441,8 +442,8 @@ namespace DownKyi.Services.Download
private async void SingleDownload(DownloadingItem downloading) private async void SingleDownload(DownloadingItem downloading)
{ {
// 路径 // 路径
string[] temp = downloading.FilePath.Split('/'); string[] temp = downloading.DownloadBase.FilePath.Split('/');
string path = downloading.FilePath.Replace(temp[temp.Length - 1], ""); string path = downloading.DownloadBase.FilePath.Replace(temp[temp.Length - 1], "");
// 路径不存在则创建 // 路径不存在则创建
if (!Directory.Exists(path)) if (!Directory.Exists(path))
{ {
@ -451,12 +452,12 @@ namespace DownKyi.Services.Download
await Task.Run(new Action(() => await Task.Run(new Action(() =>
{ {
downloading.DownloadStatus = DownloadStatus.DOWNLOADING; downloading.Downloading.DownloadStatus = DownloadStatus.DOWNLOADING;
// 初始化 // 初始化
downloading.DownloadStatusTitle = string.Empty; downloading.DownloadStatusTitle = string.Empty;
downloading.DownloadContent = string.Empty; downloading.DownloadContent = string.Empty;
downloading.DownloadFiles.Clear(); downloading.Downloading.DownloadFiles.Clear();
// 解析并依次下载音频、视频、弹幕、字幕、封面等内容 // 解析并依次下载音频、视频、弹幕、字幕、封面等内容
Parse(downloading); Parse(downloading);
@ -466,7 +467,7 @@ namespace DownKyi.Services.Download
string audioUid = null; string audioUid = null;
// 如果需要下载音频 // 如果需要下载音频
if (downloading.NeedDownloadContent["downloadAudio"]) if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"])
{ {
audioUid = DownloadAudio(downloading); audioUid = DownloadAudio(downloading);
} }
@ -476,7 +477,7 @@ namespace DownKyi.Services.Download
string videoUid = null; string videoUid = null;
// 如果需要下载视频 // 如果需要下载视频
if (downloading.NeedDownloadContent["downloadVideo"]) if (downloading.DownloadBase.NeedDownloadContent["downloadVideo"])
{ {
videoUid = DownloadVideo(downloading); videoUid = DownloadVideo(downloading);
} }
@ -486,7 +487,7 @@ namespace DownKyi.Services.Download
string outputDanmaku = null; string outputDanmaku = null;
// 如果需要下载弹幕 // 如果需要下载弹幕
if (downloading.NeedDownloadContent["downloadDanmaku"]) if (downloading.DownloadBase.NeedDownloadContent["downloadDanmaku"])
{ {
outputDanmaku = DownloadDanmaku(downloading); outputDanmaku = DownloadDanmaku(downloading);
} }
@ -496,7 +497,7 @@ namespace DownKyi.Services.Download
List<string> outputSubtitles = null; List<string> outputSubtitles = null;
// 如果需要下载字幕 // 如果需要下载字幕
if (downloading.NeedDownloadContent["downloadSubtitle"]) if (downloading.DownloadBase.NeedDownloadContent["downloadSubtitle"])
{ {
outputSubtitles = DownloadSubtitle(downloading); outputSubtitles = DownloadSubtitle(downloading);
} }
@ -506,15 +507,15 @@ namespace DownKyi.Services.Download
string outputCover = null; string outputCover = null;
// 如果需要下载封面 // 如果需要下载封面
if (downloading.NeedDownloadContent["downloadCover"]) if (downloading.DownloadBase.NeedDownloadContent["downloadCover"])
{ {
string fileName = $"{downloading.FilePath}.{GetImageExtension(downloading.PageCoverUrl)}"; string fileName = $"{downloading.DownloadBase.FilePath}.{GetImageExtension(downloading.DownloadBase.PageCoverUrl)}";
// page的封面 // page的封面
outputCover = DownloadCover(downloading, downloading.PageCoverUrl, fileName); outputCover = DownloadCover(downloading, downloading.DownloadBase.PageCoverUrl, fileName);
// 封面 // 封面
DownloadCover(downloading, downloading.CoverUrl, $"{path}/Cover.{GetImageExtension(downloading.CoverUrl)}"); DownloadCover(downloading, downloading.DownloadBase.CoverUrl, $"{path}/Cover.{GetImageExtension(downloading.DownloadBase.CoverUrl)}");
} }
// 暂停 // 暂停
@ -522,7 +523,7 @@ namespace DownKyi.Services.Download
// 混流 // 混流
string outputMedia = string.Empty; string outputMedia = string.Empty;
if (downloading.NeedDownloadContent["downloadAudio"] || downloading.NeedDownloadContent["downloadVideo"]) if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"] || downloading.DownloadBase.NeedDownloadContent["downloadVideo"])
{ {
outputMedia = MixedFlow(downloading, audioUid, videoUid); outputMedia = MixedFlow(downloading, audioUid, videoUid);
} }
@ -531,7 +532,7 @@ namespace DownKyi.Services.Download
Pause(downloading); Pause(downloading);
// 检测音频、视频是否下载成功 // 检测音频、视频是否下载成功
if (downloading.NeedDownloadContent["downloadAudio"] || downloading.NeedDownloadContent["downloadVideo"]) if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"] || downloading.DownloadBase.NeedDownloadContent["downloadVideo"])
{ {
// 只有下载音频不下载视频时才输出aac // 只有下载音频不下载视频时才输出aac
// 只要下载视频就输出mp4 // 只要下载视频就输出mp4
@ -542,13 +543,13 @@ namespace DownKyi.Services.Download
} }
// 检测弹幕是否下载成功 // 检测弹幕是否下载成功
if (downloading.NeedDownloadContent["downloadDanmaku"] && File.Exists(outputDanmaku)) if (downloading.DownloadBase.NeedDownloadContent["downloadDanmaku"] && File.Exists(outputDanmaku))
{ {
// 成功 // 成功
} }
// 检测字幕是否下载成功 // 检测字幕是否下载成功
if (downloading.NeedDownloadContent["downloadSubtitle"]) if (downloading.DownloadBase.NeedDownloadContent["downloadSubtitle"])
{ {
if (outputSubtitles == null) if (outputSubtitles == null)
{ {
@ -567,7 +568,7 @@ namespace DownKyi.Services.Download
} }
// 检测封面是否下载成功 // 检测封面是否下载成功
if (downloading.NeedDownloadContent["downloadCover"] && File.Exists(outputCover)) if (downloading.DownloadBase.NeedDownloadContent["downloadCover"] && File.Exists(outputCover))
{ {
// 成功 // 成功
} }
@ -578,6 +579,29 @@ namespace DownKyi.Services.Download
// 下载结果是否成功等 // 下载结果是否成功等
// 对是否成功的判断只要outputMedia存在则成功否则失败 // 对是否成功的判断只要outputMedia存在则成功否则失败
Downloaded downloaded = new Downloaded
{
MaxSpeedDisplay = Format.FormatSpeed(downloading.Downloading.MaxSpeed),
};
// 设置完成时间
downloaded.SetFinishedTimestamp(new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds());
DownloadedItem downloadedItem = new DownloadedItem
{
DownloadBase = downloading.DownloadBase,
Downloaded = downloaded
};
App.PropertyChangeAsync(new Action(() =>
{
// 加入到下载完成list中并从下载中list去除
App.DownloadedList.Add(downloadedItem);
App.DownloadingList.Remove(downloading);
// 下载完成列表排序
DownloadFinishedSort finishedSort = SettingsManager.GetInstance().GetDownloadFinishedSort();
App.SortDownloadedList(finishedSort);
}));
})); }));
} }
@ -607,7 +631,7 @@ namespace DownKyi.Services.Download
{ {
string oldStatus = downloading.DownloadStatusTitle; string oldStatus = downloading.DownloadStatusTitle;
downloading.DownloadStatusTitle = DictionaryResource.GetString("Pausing"); downloading.DownloadStatusTitle = DictionaryResource.GetString("Pausing");
while (downloading.DownloadStatus == DownloadStatus.PAUSE) while (downloading.Downloading.DownloadStatus == DownloadStatus.PAUSE)
{ {
// 降低CPU占用 // 降低CPU占用
Thread.Sleep(100); Thread.Sleep(100);
@ -621,7 +645,7 @@ namespace DownKyi.Services.Download
downloadingCount = 0; downloadingCount = 0;
foreach (DownloadingItem item in downloadingList) foreach (DownloadingItem item in downloadingList)
{ {
if (item.DownloadStatus == DownloadStatus.DOWNLOADING) if (item.Downloading.DownloadStatus == DownloadStatus.DOWNLOADING)
{ {
downloadingCount++; downloadingCount++;
} }
@ -731,7 +755,7 @@ namespace DownKyi.Services.Download
// 保存gid // 保存gid
string gid = ariaAddUri.Result.Result; string gid = ariaAddUri.Result.Result;
downloading.Gid = gid; downloading.Downloading.Gid = gid;
// 管理下载 // 管理下载
AriaManager ariaManager = new AriaManager(); AriaManager ariaManager = new AriaManager();
@ -739,15 +763,15 @@ namespace DownKyi.Services.Download
ariaManager.DownloadFinish += AriaDownloadFinish; ariaManager.DownloadFinish += AriaDownloadFinish;
return ariaManager.GetDownloadStatus(gid, new Action(() => return ariaManager.GetDownloadStatus(gid, new Action(() =>
{ {
switch (downloading.DownloadStatus) switch (downloading.Downloading.DownloadStatus)
{ {
case DownloadStatus.PAUSE: case DownloadStatus.PAUSE:
Task<AriaPause> ariaPause = AriaClient.PauseAsync(downloading.Gid); Task<AriaPause> ariaPause = AriaClient.PauseAsync(downloading.Downloading.Gid);
// 通知UI并阻塞当前线程 // 通知UI并阻塞当前线程
Pause(downloading); Pause(downloading);
break; break;
case DownloadStatus.DOWNLOADING: case DownloadStatus.DOWNLOADING:
Task<AriaPause> ariaUnpause = AriaClient.UnpauseAsync(downloading.Gid); Task<AriaPause> ariaUnpause = AriaClient.UnpauseAsync(downloading.Downloading.Gid);
break; break;
} }
})); }));
@ -756,7 +780,7 @@ namespace DownKyi.Services.Download
private void AriaTellStatus(long totalLength, long completedLength, long speed, string gid) private void AriaTellStatus(long totalLength, long completedLength, long speed, string gid)
{ {
// 当前的下载视频 // 当前的下载视频
DownloadingItem video = downloadingList.FirstOrDefault(it => it.Gid == gid); DownloadingItem video = downloadingList.FirstOrDefault(it => it.Downloading.Gid == gid);
if (video == null) { return; } if (video == null) { return; }
float percent = 0; float percent = 0;
@ -778,9 +802,9 @@ namespace DownKyi.Services.Download
video.SpeedDisplay = Format.FormatSpeed(speed); video.SpeedDisplay = Format.FormatSpeed(speed);
// 最大下载速度 // 最大下载速度
if (video.MaxSpeed < speed) if (video.Downloading.MaxSpeed < speed)
{ {
video.MaxSpeed = speed; video.Downloading.MaxSpeed = speed;
} }
} }

@ -1,4 +1,4 @@
using DownKyi.Models; using DownKyi.ViewModels.DownloadManager;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
namespace DownKyi.Services.Download namespace DownKyi.Services.Download

@ -1,4 +1,4 @@
using DownKyi.Models; using DownKyi.ViewModels.DownloadManager;
using System.Collections.Generic; using System.Collections.Generic;
namespace DownKyi.Services.Download namespace DownKyi.Services.Download

@ -1,7 +1,7 @@
using DownKyi.Core.BiliApi.Favorites; using DownKyi.Core.BiliApi.Favorites;
using DownKyi.Core.Storage; using DownKyi.Core.Storage;
using DownKyi.Core.Utils; using DownKyi.Core.Utils;
using DownKyi.Models; using DownKyi.ViewModels.PageViewModels;
using Prism.Events; using Prism.Events;
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;

@ -1,4 +1,4 @@
using DownKyi.Models; using DownKyi.ViewModels.PageViewModels;
using Prism.Events; using Prism.Events;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;

@ -1,4 +1,4 @@
using DownKyi.Models; using DownKyi.ViewModels.PageViewModels;
using System.Collections.Generic; using System.Collections.Generic;
namespace DownKyi.Services namespace DownKyi.Services

@ -3,7 +3,7 @@ using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.Settings; using DownKyi.Core.Settings;
using DownKyi.Core.Settings.Models; using DownKyi.Core.Settings.Models;
using DownKyi.Core.Utils; using DownKyi.Core.Utils;
using DownKyi.Models; using DownKyi.ViewModels.PageViewModels;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

@ -4,7 +4,7 @@ using DownKyi.Core.BiliApi.Video.Models;
using DownKyi.Core.BiliApi.VideoStream; using DownKyi.Core.BiliApi.VideoStream;
using DownKyi.Core.Storage; using DownKyi.Core.Storage;
using DownKyi.Core.Utils; using DownKyi.Core.Utils;
using DownKyi.Models; using DownKyi.ViewModels.PageViewModels;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
@ -39,13 +39,13 @@ namespace DownKyi.Services
/// 获取视频剧集 /// 获取视频剧集
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public List<Models.VideoPage> GetVideoPages() public List<ViewModels.PageViewModels.VideoPage> GetVideoPages()
{ {
if (videoView == null) { return null; } if (videoView == null) { return null; }
if (videoView.Pages == null) { return null; } if (videoView.Pages == null) { return null; }
if (videoView.Pages.Count == 0) { return null; } if (videoView.Pages.Count == 0) { return null; }
List<Models.VideoPage> videoPages = new List<Models.VideoPage>(); List<ViewModels.PageViewModels.VideoPage> videoPages = new List<ViewModels.PageViewModels.VideoPage>();
int order = 0; int order = 0;
foreach (var page in videoView.Pages) foreach (var page in videoView.Pages)
@ -72,7 +72,7 @@ namespace DownKyi.Services
} }
} }
Models.VideoPage videoPage = new Models.VideoPage ViewModels.PageViewModels.VideoPage videoPage = new ViewModels.PageViewModels.VideoPage
{ {
Avid = videoView.Aid, Avid = videoView.Aid,
Bvid = videoView.Bvid, Bvid = videoView.Bvid,
@ -104,12 +104,12 @@ namespace DownKyi.Services
foreach (var section in videoView.UgcSeason.Sections) foreach (var section in videoView.UgcSeason.Sections)
{ {
List<Models.VideoPage> pages = new List<Models.VideoPage>(); List<ViewModels.PageViewModels.VideoPage> pages = new List<ViewModels.PageViewModels.VideoPage>();
int order = 0; int order = 0;
foreach (var episode in section.Episodes) foreach (var episode in section.Episodes)
{ {
order++; order++;
Models.VideoPage page = new Models.VideoPage ViewModels.PageViewModels.VideoPage page = new ViewModels.PageViewModels.VideoPage
{ {
Avid = episode.Aid, Avid = episode.Aid,
Bvid = episode.Bvid, Bvid = episode.Bvid,
@ -141,7 +141,7 @@ namespace DownKyi.Services
/// 获取视频流的信息从VideoPage返回 /// 获取视频流的信息从VideoPage返回
/// </summary> /// </summary>
/// <param name="page"></param> /// <param name="page"></param>
public void GetVideoStream(Models.VideoPage page) public void GetVideoStream(ViewModels.PageViewModels.VideoPage page)
{ {
var playUrl = VideoStream.GetVideoPlayUrl(page.Avid, page.Bvid, page.Cid); var playUrl = VideoStream.GetVideoPlayUrl(page.Avid, page.Bvid, page.Cid);
Utils.VideoPageInfo(playUrl, page); Utils.VideoPageInfo(playUrl, page);

@ -15,8 +15,10 @@ namespace DownKyi.Utils
/// <returns></returns> /// <returns></returns>
public static string GetColor(string resourceKey) public static string GetColor(string resourceKey)
{ {
Color color = (Color)Application.Current.Resources[resourceKey]; //Color color = (Color)Application.Current.Resources[resourceKey];
return color.ToString(); //return color.ToString();
return Application.Current == null ? "#00000000" : ((Color)Application.Current.Resources[resourceKey]).ToString();
} }
/// <summary> /// <summary>

@ -41,6 +41,8 @@ namespace DownKyi.ViewModels
/// <param name="callback"></param> /// <param name="callback"></param>
protected void PropertyChangeAsync(Action callback) protected void PropertyChangeAsync(Action callback)
{ {
if (Application.Current == null) { return; }
Application.Current.Dispatcher.Invoke(callback); Application.Current.Dispatcher.Invoke(callback);
} }

@ -0,0 +1,122 @@
using DownKyi.Core.BiliApi.BiliUtils;
using DownKyi.Core.BiliApi.Zone;
using DownKyi.Models;
using Prism.Mvvm;
using System.Windows;
using System.Windows.Media;
namespace DownKyi.ViewModels.DownloadManager
{
public class DownloadBaseItem : BindableBase
{
// model数据
private DownloadBase downloadBase;
public DownloadBase DownloadBase
{
get => downloadBase;
set
{
downloadBase = value;
ZoneImage = (DrawingImage)Application.Current.Resources[VideoZoneIcon.Instance().GetZoneImageKey(DownloadBase.ZoneId)];
}
}
// 视频分区image
private DrawingImage zoneImage;
public DrawingImage ZoneImage
{
get => zoneImage;
set => SetProperty(ref zoneImage, value);
}
// 视频序号
public int Order
{
get => DownloadBase.Order;
set
{
DownloadBase.Order = value;
RaisePropertyChanged("Order");
}
}
// 视频主标题
public string MainTitle
{
get => DownloadBase.MainTitle;
set
{
DownloadBase.MainTitle = value;
RaisePropertyChanged("MainTitle");
}
}
// 视频标题
public string Name
{
get => DownloadBase.Name;
set
{
DownloadBase.Name = value;
RaisePropertyChanged("Name");
}
}
// 时长
public string Duration
{
get => DownloadBase.Duration;
set
{
DownloadBase.Duration = value;
RaisePropertyChanged("Duration");
}
}
// 视频编码名称AVC、HEVC
public string VideoCodecName
{
get => DownloadBase.VideoCodecName;
set
{
DownloadBase.VideoCodecName = value;
RaisePropertyChanged("VideoCodecName");
}
}
// 视频画质
public Quality Resolution
{
get => DownloadBase.Resolution;
set
{
DownloadBase.Resolution = value;
RaisePropertyChanged("Resolution");
}
}
// 音频编码
public Quality AudioCodec
{
get => DownloadBase.AudioCodec;
set
{
DownloadBase.AudioCodec = value;
RaisePropertyChanged("AudioCodec");
}
}
// 文件大小
public string FileSize
{
get => DownloadBase.FileSize;
set
{
DownloadBase.FileSize = value;
RaisePropertyChanged("FileSize");
}
}
}
}

@ -0,0 +1,122 @@
using DownKyi.Images;
using DownKyi.Models;
using Prism.Commands;
using System.IO;
namespace DownKyi.ViewModels.DownloadManager
{
public class DownloadedItem : DownloadBaseItem
{
public DownloadedItem() : base()
{
}
// model数据
public Downloaded Downloaded { get; set; }
// 下载速度
public string MaxSpeedDisplay
{
get => Downloaded.MaxSpeedDisplay;
set
{
Downloaded.MaxSpeedDisplay = value;
RaisePropertyChanged("MaxSpeedDisplay");
}
}
// 完成时间
public string FinishedTime
{
get => Downloaded.FinishedTime;
set
{
Downloaded.FinishedTime = value;
RaisePropertyChanged("FinishedTime");
}
}
#region 控制按钮
private VectorImage openFolder;
public VectorImage OpenFolder
{
get => openFolder;
set => SetProperty(ref openFolder, value);
}
private VectorImage openVideo;
public VectorImage OpenVideo
{
get => openVideo;
set => SetProperty(ref openVideo, value);
}
private VectorImage removeVideo;
public VectorImage RemoveVideo
{
get => removeVideo;
set => SetProperty(ref removeVideo, value);
}
#endregion
#region 命令申明
// 打开文件夹事件
private DelegateCommand openFolderCommand;
public DelegateCommand OpenFolderCommand => openFolderCommand ?? (openFolderCommand = new DelegateCommand(ExecuteOpenFolderCommand));
/// <summary>
/// 打开文件夹事件
/// </summary>
private void ExecuteOpenFolderCommand()
{
string videoPath = $"{DownloadBase.FilePath}.mp4";
if (File.Exists(videoPath))
{
System.Diagnostics.Process.Start("Explorer", "/select," + videoPath);
}
else
{
//eventAggregator.GetEvent<MessageEvent>().Publish("没有找到视频文件,可能被删除或移动!");
}
}
// 打开视频事件
private DelegateCommand openVideoCommand;
public DelegateCommand OpenVideoCommand => openVideoCommand ?? (openVideoCommand = new DelegateCommand(ExecuteOpenVideoCommand));
/// <summary>
/// 打开视频事件
/// </summary>
private void ExecuteOpenVideoCommand()
{
string videoPath = $"{DownloadBase.FilePath}.mp4";
if (File.Exists(videoPath))
{
System.Diagnostics.Process.Start(videoPath);
}
else
{
//eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipAddDownloadingZero"));
//eventAggregator.GetEvent<MessageEvent>().Publish("没有找到视频文件,可能被删除或移动!");
}
}
// 删除事件
private DelegateCommand removeVideoCommand;
public DelegateCommand RemoveVideoCommand => removeVideoCommand ?? (removeVideoCommand = new DelegateCommand(ExecuteRemoveVideoCommand));
/// <summary>
/// 删除事件
/// </summary>
private void ExecuteRemoveVideoCommand()
{
App.DownloadedList.Remove(this);
}
#endregion
}
}

@ -1,18 +1,15 @@
using DownKyi.Core.BiliApi.VideoStream.Models; using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Images; using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Utils; using DownKyi.Utils;
using Prism.Commands; using Prism.Commands;
using System.Collections.Generic;
namespace DownKyi.Models namespace DownKyi.ViewModels.DownloadManager
{ {
public class DownloadingItem : DownloadBaseItem public class DownloadingItem : DownloadBaseItem
{ {
public DownloadingItem() : base() public DownloadingItem() : base()
{ {
// 初始化下载的文件列表
DownloadFiles = new List<string>();
// 暂停继续按钮 // 暂停继续按钮
StartOrPause = ButtonIcon.Instance().Pause; StartOrPause = ButtonIcon.Instance().Pause;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
@ -22,62 +19,65 @@ namespace DownKyi.Models
Delete.Fill = DictionaryResource.GetColor("ColorPrimary"); Delete.Fill = DictionaryResource.GetColor("ColorPrimary");
} }
public PlayUrl PlayUrl { get; set; } // model数据
public Downloading Downloading { get; set; }
// Aria相关
public string Gid { get; set; }
// 下载的文件
public List<string> DownloadFiles { get; private set; }
// 视频类别
public PlayStreamType PlayStreamType { get; set; }
// 视频流链接
public PlayUrl PlayUrl { get; set; }
// 正在下载内容(音频、视频、弹幕、字幕、封面) // 正在下载内容(音频、视频、弹幕、字幕、封面)
private string downloadContent;
public string DownloadContent public string DownloadContent
{ {
get => downloadContent; get => Downloading.DownloadContent;
set => SetProperty(ref downloadContent, value); set
{
Downloading.DownloadContent = value;
RaisePropertyChanged("DownloadContent");
}
} }
// 下载状态
public DownloadStatus DownloadStatus { get; set; }
// 下载状态显示 // 下载状态显示
private string downloadStatusTitle;
public string DownloadStatusTitle public string DownloadStatusTitle
{ {
get => downloadStatusTitle; get => Downloading.DownloadStatusTitle;
set => SetProperty(ref downloadStatusTitle, value); set
{
Downloading.DownloadStatusTitle = value;
RaisePropertyChanged("DownloadStatusTitle");
}
} }
// 下载进度 // 下载进度
private float progress;
public float Progress public float Progress
{ {
get => progress; get => Downloading.Progress;
set => SetProperty(ref progress, value); set
{
Downloading.Progress = value;
RaisePropertyChanged("Progress");
}
} }
// 已下载大小/文件大小 // 已下载大小/文件大小
private string downloadingFileSize;
public string DownloadingFileSize public string DownloadingFileSize
{ {
get => downloadingFileSize; get => Downloading.DownloadingFileSize;
set => SetProperty(ref downloadingFileSize, value); set
{
Downloading.DownloadingFileSize = value;
RaisePropertyChanged("DownloadingFileSize");
}
} }
// 下载的最高速度
public long MaxSpeed { get; set; }
// 下载速度 // 下载速度
private string speedDisplay;
public string SpeedDisplay public string SpeedDisplay
{ {
get => speedDisplay; get => Downloading.SpeedDisplay;
set => SetProperty(ref speedDisplay, value); set
{
Downloading.SpeedDisplay = value;
RaisePropertyChanged("SpeedDisplay");
}
} }
@ -110,26 +110,26 @@ namespace DownKyi.Models
/// </summary> /// </summary>
private void ExecuteStartOrPauseCommand() private void ExecuteStartOrPauseCommand()
{ {
switch (DownloadStatus) switch (Downloading.DownloadStatus)
{ {
case DownloadStatus.NOT_STARTED: case DownloadStatus.NOT_STARTED:
case DownloadStatus.WAIT_FOR_DOWNLOAD: case DownloadStatus.WAIT_FOR_DOWNLOAD:
DownloadStatus = DownloadStatus.PAUSE_STARTED; Downloading.DownloadStatus = DownloadStatus.PAUSE_STARTED;
StartOrPause = ButtonIcon.Instance().Start; StartOrPause = ButtonIcon.Instance().Start;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
break; break;
case DownloadStatus.PAUSE_STARTED: case DownloadStatus.PAUSE_STARTED:
DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; Downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD;
StartOrPause = ButtonIcon.Instance().Pause; StartOrPause = ButtonIcon.Instance().Pause;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
break; break;
case DownloadStatus.PAUSE: case DownloadStatus.PAUSE:
DownloadStatus = DownloadStatus.DOWNLOADING; Downloading.DownloadStatus = DownloadStatus.DOWNLOADING;
StartOrPause = ButtonIcon.Instance().Pause; StartOrPause = ButtonIcon.Instance().Pause;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
break; break;
case DownloadStatus.DOWNLOADING: case DownloadStatus.DOWNLOADING:
DownloadStatus = DownloadStatus.PAUSE; Downloading.DownloadStatus = DownloadStatus.PAUSE;
StartOrPause = ButtonIcon.Instance().Start; StartOrPause = ButtonIcon.Instance().Start;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
break; break;
@ -138,7 +138,7 @@ namespace DownKyi.Models
// 不会出现此分支 // 不会出现此分支
break; break;
case DownloadStatus.DOWNLOAD_FAILED: case DownloadStatus.DOWNLOAD_FAILED:
DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; Downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD;
StartOrPause = ButtonIcon.Instance().Pause; StartOrPause = ButtonIcon.Instance().Pause;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
break; break;

@ -1,11 +1,7 @@
using DownKyi.Models; using DownKyi.Core.Settings;
using Prism.Commands; using Prism.Commands;
using Prism.Events; using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
namespace DownKyi.ViewModels.DownloadManager namespace DownKyi.ViewModels.DownloadManager
{ {
@ -18,15 +14,55 @@ namespace DownKyi.ViewModels.DownloadManager
private ObservableCollection<DownloadedItem> downloadedList; private ObservableCollection<DownloadedItem> downloadedList;
public ObservableCollection<DownloadedItem> DownloadedList public ObservableCollection<DownloadedItem> DownloadedList
{ {
get { return downloadedList; } get => downloadedList;
set { SetProperty(ref downloadedList, value); } set => SetProperty(ref downloadedList, value);
} }
#endregion #endregion
public ViewDownloadFinishedViewModel(IEventAggregator eventAggregator) : base(eventAggregator) public ViewDownloadFinishedViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
{ {
// 初始化DownloadedList
DownloadedList = App.DownloadedList; DownloadedList = App.DownloadedList;
} }
#region 命令申明
// 下载完成列表排序事件
private DelegateCommand<object> finishedSortCommand;
public DelegateCommand<object> FinishedSortCommand => finishedSortCommand ?? (finishedSortCommand = new DelegateCommand<object>(ExecuteFinishedSortCommand));
/// <summary>
/// 下载完成列表排序事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteFinishedSortCommand(object parameter)
{
if (!(parameter is int index)) { return; }
switch (index)
{
case 1:
App.SortDownloadedList(DownloadFinishedSort.DOWNLOAD);
break;
case 2:
App.SortDownloadedList(DownloadFinishedSort.NUMBER);
break;
}
}
// 清空下载完成列表事件
private DelegateCommand clearAllDownloadedCommand;
public DelegateCommand ClearAllDownloadedCommand => clearAllDownloadedCommand ?? (clearAllDownloadedCommand = new DelegateCommand(ExecuteClearAllDownloadedCommand));
/// <summary>
/// 清空下载完成列表事件
/// </summary>
private void ExecuteClearAllDownloadedCommand()
{
}
#endregion
} }
} }

@ -41,18 +41,18 @@ namespace DownKyi.ViewModels.DownloadManager
{ {
foreach (DownloadingItem downloading in downloadingList) foreach (DownloadingItem downloading in downloadingList)
{ {
switch (downloading.DownloadStatus) switch (downloading.Downloading.DownloadStatus)
{ {
case DownloadStatus.NOT_STARTED: case DownloadStatus.NOT_STARTED:
case DownloadStatus.WAIT_FOR_DOWNLOAD: case DownloadStatus.WAIT_FOR_DOWNLOAD:
downloading.DownloadStatus = DownloadStatus.PAUSE_STARTED; downloading.Downloading.DownloadStatus = DownloadStatus.PAUSE_STARTED;
break; break;
case DownloadStatus.PAUSE_STARTED: case DownloadStatus.PAUSE_STARTED:
break; break;
case DownloadStatus.PAUSE: case DownloadStatus.PAUSE:
break; break;
case DownloadStatus.DOWNLOADING: case DownloadStatus.DOWNLOADING:
downloading.DownloadStatus = DownloadStatus.PAUSE; downloading.Downloading.DownloadStatus = DownloadStatus.PAUSE;
break; break;
case DownloadStatus.DOWNLOAD_SUCCEED: case DownloadStatus.DOWNLOAD_SUCCEED:
// 下载成功后会从下载列表中删除 // 下载成功后会从下载列表中删除
@ -80,16 +80,16 @@ namespace DownKyi.ViewModels.DownloadManager
{ {
foreach (DownloadingItem downloading in downloadingList) foreach (DownloadingItem downloading in downloadingList)
{ {
switch (downloading.DownloadStatus) switch (downloading.Downloading.DownloadStatus)
{ {
case DownloadStatus.NOT_STARTED: case DownloadStatus.NOT_STARTED:
case DownloadStatus.WAIT_FOR_DOWNLOAD: case DownloadStatus.WAIT_FOR_DOWNLOAD:
break; break;
case DownloadStatus.PAUSE_STARTED: case DownloadStatus.PAUSE_STARTED:
downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; downloading.Downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD;
break; break;
case DownloadStatus.PAUSE: case DownloadStatus.PAUSE:
downloading.DownloadStatus = DownloadStatus.DOWNLOADING; downloading.Downloading.DownloadStatus = DownloadStatus.DOWNLOADING;
break; break;
case DownloadStatus.DOWNLOADING: case DownloadStatus.DOWNLOADING:
break; break;
@ -98,7 +98,7 @@ namespace DownKyi.ViewModels.DownloadManager
// 不会出现此分支 // 不会出现此分支
break; break;
case DownloadStatus.DOWNLOAD_FAILED: case DownloadStatus.DOWNLOAD_FAILED:
downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; downloading.Downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD;
break; break;
default: default:
break; break;

@ -1,7 +1,7 @@
using Prism.Mvvm; using Prism.Mvvm;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
namespace DownKyi.Models namespace DownKyi.ViewModels.PageViewModels
{ {
public class Favorites : BindableBase public class Favorites : BindableBase
{ {
@ -11,78 +11,78 @@ namespace DownKyi.Models
private BitmapImage cover; private BitmapImage cover;
public BitmapImage Cover public BitmapImage Cover
{ {
get { return cover; } get => cover;
set { SetProperty(ref cover, value); } set => SetProperty(ref cover, value);
} }
private string title; private string title;
public string Title public string Title
{ {
get { return title; } get => title;
set { SetProperty(ref title, value); } set => SetProperty(ref title, value);
} }
private string createTime; private string createTime;
public string CreateTime public string CreateTime
{ {
get { return createTime; } get => createTime;
set { SetProperty(ref createTime, value); } set => SetProperty(ref createTime, value);
} }
private string playNumber; private string playNumber;
public string PlayNumber public string PlayNumber
{ {
get { return playNumber; } get => playNumber;
set { SetProperty(ref playNumber, value); } set => SetProperty(ref playNumber, value);
} }
private string likeNumber; private string likeNumber;
public string LikeNumber public string LikeNumber
{ {
get { return likeNumber; } get => likeNumber;
set { SetProperty(ref likeNumber, value); } set => SetProperty(ref likeNumber, value);
} }
private string favoriteNumber; private string favoriteNumber;
public string FavoriteNumber public string FavoriteNumber
{ {
get { return favoriteNumber; } get => favoriteNumber;
set { SetProperty(ref favoriteNumber, value); } set => SetProperty(ref favoriteNumber, value);
} }
private string shareNumber; private string shareNumber;
public string ShareNumber public string ShareNumber
{ {
get { return shareNumber; } get => shareNumber;
set { SetProperty(ref shareNumber, value); } set => SetProperty(ref shareNumber, value);
} }
private string description; private string description;
public string Description public string Description
{ {
get { return description; } get => description;
set { SetProperty(ref description, value); } set => SetProperty(ref description, value);
} }
private int mediaCount; private int mediaCount;
public int MediaCount public int MediaCount
{ {
get { return mediaCount; } get => mediaCount;
set { SetProperty(ref mediaCount, value); } set => SetProperty(ref mediaCount, value);
} }
private string upName; private string upName;
public string UpName public string UpName
{ {
get { return upName; } get => upName;
set { SetProperty(ref upName, value); } set => SetProperty(ref upName, value);
} }
private BitmapImage upHeader; private BitmapImage upHeader;
public BitmapImage UpHeader public BitmapImage UpHeader
{ {
get { return upHeader; } get => upHeader;
set { SetProperty(ref upHeader, value); } set => SetProperty(ref upHeader, value);
} }
} }
} }

@ -1,12 +1,11 @@
using DownKyi.Core.BiliApi.BiliUtils; using DownKyi.Core.BiliApi.BiliUtils;
using DownKyi.Utils; using DownKyi.Utils;
using DownKyi.ViewModels;
using Prism.Commands; using Prism.Commands;
using Prism.Events; using Prism.Events;
using Prism.Mvvm; using Prism.Mvvm;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
namespace DownKyi.Models namespace DownKyi.ViewModels.PageViewModels
{ {
public class FavoritesMedia : BindableBase public class FavoritesMedia : BindableBase
{ {
@ -26,64 +25,64 @@ namespace DownKyi.Models
private bool isSelected; private bool isSelected;
public bool IsSelected public bool IsSelected
{ {
get { return isSelected; } get => isSelected;
set { SetProperty(ref isSelected, value); } set => SetProperty(ref isSelected, value);
} }
private int order; private int order;
public int Order public int Order
{ {
get { return order; } get => order;
set { SetProperty(ref order, value); } set => SetProperty(ref order, value);
} }
private BitmapImage cover; private BitmapImage cover;
public BitmapImage Cover public BitmapImage Cover
{ {
get { return cover; } get => cover;
set { SetProperty(ref cover, value); } set => SetProperty(ref cover, value);
} }
private string title; private string title;
public string Title public string Title
{ {
get { return title; } get => title;
set { SetProperty(ref title, value); } set => SetProperty(ref title, value);
} }
private string playNumber; private string playNumber;
public string PlayNumber public string PlayNumber
{ {
get { return playNumber; } get => playNumber;
set { SetProperty(ref playNumber, value); } set => SetProperty(ref playNumber, value);
} }
private string danmakuNumber; private string danmakuNumber;
public string DanmakuNumber public string DanmakuNumber
{ {
get { return danmakuNumber; } get => danmakuNumber;
set { SetProperty(ref danmakuNumber, value); } set => SetProperty(ref danmakuNumber, value);
} }
private string favoriteNumber; private string favoriteNumber;
public string FavoriteNumber public string FavoriteNumber
{ {
get { return favoriteNumber; } get => favoriteNumber;
set { SetProperty(ref favoriteNumber, value); } set => SetProperty(ref favoriteNumber, value);
} }
private string duration; private string duration;
public string Duration public string Duration
{ {
get { return duration; } get => duration;
set { SetProperty(ref duration, value); } set => SetProperty(ref duration, value);
} }
private string upName; private string upName;
public string UpName public string UpName
{ {
get { return upName; } get => upName;
set { SetProperty(ref upName, value); } set => SetProperty(ref upName, value);
} }
#endregion #endregion

@ -1,36 +1,36 @@
using DownKyi.Images; using DownKyi.Images;
using Prism.Mvvm; using Prism.Mvvm;
namespace DownKyi.Models namespace DownKyi.ViewModels.PageViewModels
{ {
public class TabHeader : BindableBase public class TabHeader : BindableBase
{ {
private int id; private int id;
public int Id public int Id
{ {
get { return id; } get => id;
set { SetProperty(ref id, value); } set => SetProperty(ref id, value);
} }
private VectorImage image; private VectorImage image;
public VectorImage Image public VectorImage Image
{ {
get { return image; } get => image;
set { SetProperty(ref image, value); } set => SetProperty(ref image, value);
} }
private string title; private string title;
public string Title public string Title
{ {
get { return title; } get => title;
set { SetProperty(ref title, value); } set => SetProperty(ref title, value);
} }
private string subTitle; private string subTitle;
public string SubTitle public string SubTitle
{ {
get { return subTitle; } get => subTitle;
set { SetProperty(ref subTitle, value); } set => SetProperty(ref subTitle, value);
} }
} }

@ -1,10 +1,8 @@
using Prism.Mvvm; using Prism.Mvvm;
using System;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
namespace DownKyi.Models namespace DownKyi.ViewModels.PageViewModels
{ {
[Serializable]
public class VideoInfoView : BindableBase public class VideoInfoView : BindableBase
{ {
public string CoverUrl { get; set; } public string CoverUrl { get; set; }

@ -2,7 +2,7 @@
using Prism.Mvvm; using Prism.Mvvm;
using System.Collections.Generic; using System.Collections.Generic;
namespace DownKyi.Models namespace DownKyi.ViewModels.PageViewModels
{ {
public class VideoPage : BindableBase public class VideoPage : BindableBase
{ {

@ -1,7 +1,7 @@
using Prism.Mvvm; using Prism.Mvvm;
using System.Collections.Generic; using System.Collections.Generic;
namespace DownKyi.Models namespace DownKyi.ViewModels.PageViewModels
{ {
public class VideoQuality : BindableBase public class VideoQuality : BindableBase
{ {

@ -1,7 +1,7 @@
using Prism.Mvvm; using Prism.Mvvm;
using System.Collections.Generic; using System.Collections.Generic;
namespace DownKyi.Models namespace DownKyi.ViewModels.PageViewModels
{ {
public class VideoSection : BindableBase public class VideoSection : BindableBase
{ {
@ -10,22 +10,22 @@ namespace DownKyi.Models
private string title; private string title;
public string Title public string Title
{ {
get { return title; } get => title;
set { SetProperty(ref title, value); } set => SetProperty(ref title, value);
} }
private bool isSelected; private bool isSelected;
public bool IsSelected public bool IsSelected
{ {
get { return isSelected; } get => isSelected;
set { SetProperty(ref isSelected, value); } set => SetProperty(ref isSelected, value);
} }
private List<VideoPage> videoPages; private List<VideoPage> videoPages;
public List<VideoPage> VideoPages public List<VideoPage> VideoPages
{ {
get { return videoPages; } get => videoPages;
set { SetProperty(ref videoPages, value); } set => SetProperty(ref videoPages, value);
} }
} }
} }

@ -1,7 +1,7 @@
using DownKyi.Core.FileName; using DownKyi.Core.FileName;
using Prism.Mvvm; using Prism.Mvvm;
namespace DownKyi.Models namespace DownKyi.ViewModels.Settings
{ {
public class DisplayFileNamePart : BindableBase public class DisplayFileNamePart : BindableBase
{ {

@ -2,7 +2,6 @@
using DownKyi.Core.FileName; using DownKyi.Core.FileName;
using DownKyi.Core.Settings; using DownKyi.Core.Settings;
using DownKyi.Events; using DownKyi.Events;
using DownKyi.Models;
using DownKyi.Utils; using DownKyi.Utils;
using Prism.Commands; using Prism.Commands;
using Prism.Events; using Prism.Events;

@ -1,8 +1,8 @@
using DownKyi.Events; using DownKyi.Events;
using DownKyi.Images; using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Utils; using DownKyi.Utils;
using DownKyi.ViewModels.DownloadManager; using DownKyi.ViewModels.DownloadManager;
using DownKyi.ViewModels.PageViewModels;
using Prism.Commands; using Prism.Commands;
using Prism.Events; using Prism.Events;
using Prism.Regions; using Prism.Regions;
@ -21,22 +21,22 @@ namespace DownKyi.ViewModels
private VectorImage arrowBack; private VectorImage arrowBack;
public VectorImage ArrowBack public VectorImage ArrowBack
{ {
get { return arrowBack; } get => arrowBack;
set { SetProperty(ref arrowBack, value); } set => SetProperty(ref arrowBack, value);
} }
private List<TabHeader> tabHeaders; private List<TabHeader> tabHeaders;
public List<TabHeader> TabHeaders public List<TabHeader> TabHeaders
{ {
get { return tabHeaders; } get => tabHeaders;
set { SetProperty(ref tabHeaders, value); } set => SetProperty(ref tabHeaders, value);
} }
private int selectTabId; private int selectTabId;
public int SelectTabId public int SelectTabId
{ {
get { return selectTabId; } get => selectTabId;
set { SetProperty(ref selectTabId, value); } set => SetProperty(ref selectTabId, value);
} }
#endregion #endregion

@ -1,9 +1,9 @@
using DownKyi.Core.Logging; using DownKyi.Core.Logging;
using DownKyi.Events; using DownKyi.Events;
using DownKyi.Images; using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Services; using DownKyi.Services;
using DownKyi.Utils; using DownKyi.Utils;
using DownKyi.ViewModels.PageViewModels;
using Prism.Commands; using Prism.Commands;
using Prism.Events; using Prism.Events;
using Prism.Regions; using Prism.Regions;
@ -23,71 +23,71 @@ namespace DownKyi.ViewModels
private string pageName = Tag; private string pageName = Tag;
public string PageName public string PageName
{ {
get { return pageName; } get => pageName;
set { SetProperty(ref pageName, value); } set => SetProperty(ref pageName, value);
} }
private VectorImage arrowBack; private VectorImage arrowBack;
public VectorImage ArrowBack public VectorImage ArrowBack
{ {
get { return arrowBack; } get => arrowBack;
set { SetProperty(ref arrowBack, value); } set => SetProperty(ref arrowBack, value);
} }
private VectorImage play; private VectorImage play;
public VectorImage Play public VectorImage Play
{ {
get { return play; } get => play;
set { SetProperty(ref play, value); } set => SetProperty(ref play, value);
} }
private VectorImage like; private VectorImage like;
public VectorImage Like public VectorImage Like
{ {
get { return like; } get => like;
set { SetProperty(ref like, value); } set => SetProperty(ref like, value);
} }
private VectorImage favorite; private VectorImage favorite;
public VectorImage Favorite public VectorImage Favorite
{ {
get { return favorite; } get => favorite;
set { SetProperty(ref favorite, value); } set => SetProperty(ref favorite, value);
} }
private VectorImage share; private VectorImage share;
public VectorImage Share public VectorImage Share
{ {
get { return share; } get => share;
set { SetProperty(ref share, value); } set => SetProperty(ref share, value);
} }
private Favorites favorites; private Favorites favorites;
public Favorites Favorites public Favorites Favorites
{ {
get { return favorites; } get => favorites;
set { SetProperty(ref favorites, value); } set => SetProperty(ref favorites, value);
} }
private ObservableCollection<FavoritesMedia> favoritesMedias; private ObservableCollection<FavoritesMedia> favoritesMedias;
public ObservableCollection<FavoritesMedia> FavoritesMedias public ObservableCollection<FavoritesMedia> FavoritesMedias
{ {
get { return favoritesMedias; } get => favoritesMedias;
set { SetProperty(ref favoritesMedias, value); } set => SetProperty(ref favoritesMedias, value);
} }
private Visibility contentVisibility; private Visibility contentVisibility;
public Visibility ContentVisibility public Visibility ContentVisibility
{ {
get { return contentVisibility; } get => contentVisibility;
set { SetProperty(ref contentVisibility, value); } set => SetProperty(ref contentVisibility, value);
} }
private Visibility noDataVisibility; private Visibility noDataVisibility;
public Visibility NoDataVisibility public Visibility NoDataVisibility
{ {
get { return noDataVisibility; } get => noDataVisibility;
set { SetProperty(ref noDataVisibility, value); } set => SetProperty(ref noDataVisibility, value);
} }
#endregion #endregion

@ -1,7 +1,7 @@
using DownKyi.Events; using DownKyi.Events;
using DownKyi.Images; using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Utils; using DownKyi.Utils;
using DownKyi.ViewModels.PageViewModels;
using DownKyi.ViewModels.Settings; using DownKyi.ViewModels.Settings;
using Prism.Commands; using Prism.Commands;
using Prism.Events; using Prism.Events;
@ -21,22 +21,22 @@ namespace DownKyi.ViewModels
private VectorImage arrowBack; private VectorImage arrowBack;
public VectorImage ArrowBack public VectorImage ArrowBack
{ {
get { return arrowBack; } get => arrowBack;
set { SetProperty(ref arrowBack, value); } set => SetProperty(ref arrowBack, value);
} }
private List<TabHeader> tabHeaders; private List<TabHeader> tabHeaders;
public List<TabHeader> TabHeaders public List<TabHeader> TabHeaders
{ {
get { return tabHeaders; } get => tabHeaders;
set { SetProperty(ref tabHeaders, value); } set => SetProperty(ref tabHeaders, value);
} }
private int selectTabId; private int selectTabId;
public int SelectTabId public int SelectTabId
{ {
get { return selectTabId; } get => selectTabId;
set { SetProperty(ref selectTabId, value); } set => SetProperty(ref selectTabId, value);
} }
#endregion #endregion

@ -1,7 +1,7 @@
using DownKyi.Events; using DownKyi.Events;
using DownKyi.Images; using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Utils; using DownKyi.Utils;
using DownKyi.ViewModels.PageViewModels;
using DownKyi.ViewModels.Toolbox; using DownKyi.ViewModels.Toolbox;
using Prism.Commands; using Prism.Commands;
using Prism.Events; using Prism.Events;
@ -21,22 +21,22 @@ namespace DownKyi.ViewModels
private VectorImage arrowBack; private VectorImage arrowBack;
public VectorImage ArrowBack public VectorImage ArrowBack
{ {
get { return arrowBack; } get => arrowBack;
set { SetProperty(ref arrowBack, value); } set => SetProperty(ref arrowBack, value);
} }
private List<TabHeader> tabHeaders; private List<TabHeader> tabHeaders;
public List<TabHeader> TabHeaders public List<TabHeader> TabHeaders
{ {
get { return tabHeaders; } get => tabHeaders;
set { SetProperty(ref tabHeaders, value); } set => SetProperty(ref tabHeaders, value);
} }
private int selectTabId; private int selectTabId;
public int SelectTabId public int SelectTabId
{ {
get { return selectTabId; } get => selectTabId;
set { SetProperty(ref selectTabId, value); } set => SetProperty(ref selectTabId, value);
} }
#endregion #endregion

@ -1,4 +1,5 @@
using DownKyi.Core.BiliApi.BiliUtils; using DownKyi.Core.BiliApi.BiliUtils;
using DownKyi.Core.BiliApi.VideoStream;
using DownKyi.Core.BiliApi.Zone; using DownKyi.Core.BiliApi.Zone;
using DownKyi.Core.FileName; using DownKyi.Core.FileName;
using DownKyi.Core.Logging; using DownKyi.Core.Logging;
@ -11,6 +12,8 @@ using DownKyi.Models;
using DownKyi.Services; using DownKyi.Services;
using DownKyi.Utils; using DownKyi.Utils;
using DownKyi.ViewModels.Dialogs; using DownKyi.ViewModels.Dialogs;
using DownKyi.ViewModels.DownloadManager;
using DownKyi.ViewModels.PageViewModels;
using Prism.Commands; using Prism.Commands;
using Prism.Events; using Prism.Events;
using Prism.Regions; using Prism.Regions;
@ -22,7 +25,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Media;
namespace DownKyi.ViewModels namespace DownKyi.ViewModels
{ {
@ -568,7 +570,7 @@ namespace DownKyi.ViewModels
// 如果存在正在下载列表,则跳过,并提示 // 如果存在正在下载列表,则跳过,并提示
foreach (DownloadingItem item in App.DownloadingList) foreach (DownloadingItem item in App.DownloadingList)
{ {
if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec) if (item.DownloadBase.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec)
{ {
eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloading")}"); eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloading")}");
continue; continue;
@ -578,7 +580,7 @@ namespace DownKyi.ViewModels
// 如果存在下载完成列表,弹出选择框是否再次下载 // 如果存在下载完成列表,弹出选择框是否再次下载
foreach (DownloadedItem item in App.DownloadedList) foreach (DownloadedItem item in App.DownloadedList)
{ {
if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec) if (item.DownloadBase.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec)
{ {
eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloaded")}"); eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloaded")}");
continue; continue;
@ -661,18 +663,16 @@ namespace DownKyi.ViewModels
} }
// 如果不存在,直接添加到下载列表 // 如果不存在,直接添加到下载列表
DownloadingItem downloading = new DownloadingItem DownloadBase downloadBase = new DownloadBase
{ {
PlayUrl = page.PlayUrl,
Bvid = page.Bvid, Bvid = page.Bvid,
Avid = page.Avid, Avid = page.Avid,
Cid = page.Cid, Cid = page.Cid,
EpisodeId = page.EpisodeId, EpisodeId = page.EpisodeId,
CoverUrl = VideoInfoView.CoverUrl, CoverUrl = VideoInfoView.CoverUrl,
PageCoverUrl = page.FirstFrame, PageCoverUrl = page.FirstFrame,
ZoneImage = (DrawingImage)Application.Current.Resources[VideoZoneIcon.Instance().GetZoneImageKey(zoneId)], ZoneId = zoneId,
FilePath = filePath,
Order = page.Order, Order = page.Order,
MainTitle = VideoInfoView.Title, MainTitle = VideoInfoView.Title,
@ -681,21 +681,30 @@ namespace DownKyi.ViewModels
VideoCodecName = page.VideoQuality.SelectedVideoCodec, VideoCodecName = page.VideoQuality.SelectedVideoCodec,
Resolution = new Quality { Name = page.VideoQuality.QualityFormat, Id = page.VideoQuality.Quality }, Resolution = new Quality { Name = page.VideoQuality.QualityFormat, Id = page.VideoQuality.Quality },
AudioCodec = Constant.GetAudioQualities().FirstOrDefault(t => { return t.Name == page.AudioQualityFormat; }), AudioCodec = Constant.GetAudioQualities().FirstOrDefault(t => { return t.Name == page.AudioQualityFormat; }),
FilePath = filePath, };
Downloading downloading = new Downloading
{
PlayStreamType = playStreamType, PlayStreamType = playStreamType,
DownloadStatus = DownloadStatus.NOT_STARTED, DownloadStatus = DownloadStatus.NOT_STARTED,
}; };
// 需要下载的内容 // 需要下载的内容
downloading.NeedDownloadContent["downloadAudio"] = downloadAudio; downloadBase.NeedDownloadContent["downloadAudio"] = downloadAudio;
downloading.NeedDownloadContent["downloadVideo"] = downloadVideo; downloadBase.NeedDownloadContent["downloadVideo"] = downloadVideo;
downloading.NeedDownloadContent["downloadDanmaku"] = downloadDanmaku; downloadBase.NeedDownloadContent["downloadDanmaku"] = downloadDanmaku;
downloading.NeedDownloadContent["downloadSubtitle"] = downloadSubtitle; downloadBase.NeedDownloadContent["downloadSubtitle"] = downloadSubtitle;
downloading.NeedDownloadContent["downloadCover"] = downloadCover; downloadBase.NeedDownloadContent["downloadCover"] = downloadCover;
DownloadingItem downloadingItem = new DownloadingItem
{
DownloadBase = downloadBase,
Downloading = downloading,
PlayUrl = page.PlayUrl,
//ZoneImage = (DrawingImage)Application.Current.Resources[VideoZoneIcon.Instance().GetZoneImageKey(zoneId)],
};
// 添加到下载列表 // 添加到下载列表
App.DownloadingList.Add(downloading); App.DownloadingList.Add(downloadingItem);
i++; i++;
} }
} }

@ -2,9 +2,303 @@
x:Class="DownKyi.Views.DownloadManager.ViewDownloadFinished" x:Class="DownKyi.Views.DownloadManager.ViewDownloadFinished"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:DownKyi.Converter"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:prism="http://prismlibrary.com/" xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"> prism:ViewModelLocator.AutoWireViewModel="True">
<UserControl.Resources>
<converter:CountConverter x:Key="CountConverter" Count="0" />
<Style x:Key="DownloadedStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualWidth}" Height="70">
<Grid> <Grid>
<TextBlock>已下载</TextBlock> <Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Width="48"
Height="48"
Source="{Binding ZoneImage}" />
<!-- 标题等视频信息 -->
<Grid
Grid.Column="1"
Margin="0,0,10,0"
HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource BrushTextDark}"
TextTrimming="CharacterEllipsis">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}-{1}-{2}">
<Binding Path="Order" />
<Binding Path="MainTitle" />
<Binding Path="Name" />
</MultiBinding>
</TextBlock.Text>
<TextBlock.ToolTip>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}-{1}">
<Binding Path="MainTitle" />
<Binding Path="Name" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</TextBlock.ToolTip>
</TextBlock>
<TextBlock
Grid.Row="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey2}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} · {1} · {2} · {3} · {4} · {5}">
<Binding Path="Duration" />
<Binding Path="Resolution.Name" />
<Binding Path="VideoCodecName" />
<Binding Path="AudioCodec.Name" />
<Binding Path="FileSize" />
<Binding Path="MaxSpeedDisplay" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid>
<TextBlock
Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{Binding FinishedTime}" />
<!-- 控制面板,暂停继续删除 -->
<Grid Grid.Column="3">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border
Grid.Column="0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Background="{DynamicResource BrushBackground}"
Cursor="Hand">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding OpenFolderCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ContentControl>
<Path
Width="{Binding OpenFolder.Width}"
Height="{Binding OpenFolder.Height}"
Data="{Binding OpenFolder.Data}"
Fill="{Binding OpenFolder.Fill}"
Stretch="UniformToFill" />
</ContentControl>
</Border>
<Border
Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Background="{DynamicResource BrushBackground}"
Cursor="Hand">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding OpenVideoCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ContentControl>
<Path
Width="{Binding OpenVideo.Width}"
Height="{Binding OpenVideo.Height}"
Data="{Binding OpenVideo.Data}"
Fill="{Binding OpenVideo.Fill}"
Stretch="UniformToFill" />
</ContentControl>
</Border>
<Border
Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Background="{DynamicResource BrushBackground}"
Cursor="Hand">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding RemoveVideoCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ContentControl>
<Path
Width="{Binding RemoveVideo.Width}"
Height="{Binding RemoveVideo.Height}"
Data="{Binding RemoveVideo.Data}"
Fill="{Binding RemoveVideo.Fill}"
Stretch="UniformToFill" />
</ContentControl>
</Border>
</Grid>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="1" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding DownloadedList}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding DownloadedList.Count}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding DownloadedList.Count, Converter={StaticResource CountConverter}}" Value="true">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<ListBox
Grid.Row="0"
BorderThickness="0"
ItemContainerStyle="{StaticResource DownloadedStyle}"
ItemsSource="{Binding DownloadedList}">
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border
x:Name="Bd"
Padding="0"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer CanContentScroll="False" Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
</ListBox>
<TextBlock Grid.Row="1" Background="{DynamicResource BrushBorderTranslucent}" />
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="130" />
<ColumnDefinition Width="110" />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Column="0"
Margin="10,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource TotalDownloaded1}" />
<TextBlock
Margin="3,0"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource BrushPrimary}"
Text="{Binding DownloadedList.Count}" />
<TextBlock
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource TotalDownloaded2}" />
</StackPanel>
<ComboBox
Name="nameFinishedSort"
Grid.Column="1"
Width="120"
HorizontalAlignment="Left"
VerticalAlignment="Center">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding FinishedSortCommand}" CommandParameter="{Binding ElementName=nameFinishedSort, Path=SelectedIndex}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ComboBoxItem Content="{DynamicResource DownloadedSortByTime}" TabIndex="1" />
<ComboBoxItem Content="{DynamicResource DownloadedSortByOrder}" TabIndex="2" />
</ComboBox>
<Button
Grid.Column="2"
Width="100"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding ClearAllDownloadedCommand}"
Content="{DynamicResource ClearAllDownloaded}"
FontSize="12"
Style="{StaticResource BtnBorderStyle}" />
</Grid>
</Grid>
<!-- TODO 没有数据时显示图片或文字 -->
<Image
Width="256"
Height="256"
Source="/DownKyi;component/Resources/nodata02.png">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding DownloadedList}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding DownloadedList.Count}" Value="0">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding DownloadedList.Count, Converter={StaticResource CountConverter}}" Value="true">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Grid> </Grid>
</UserControl> </UserControl>

@ -13,7 +13,7 @@
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}"> <ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid Height="70"> <Grid Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualWidth}" Height="70">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="70" /> <ColumnDefinition Width="70" />
@ -30,7 +30,10 @@
Source="{Binding ZoneImage}" /> Source="{Binding ZoneImage}" />
<!-- 标题等视频信息 --> <!-- 标题等视频信息 -->
<Grid Grid.Column="1" HorizontalAlignment="Left"> <Grid
Grid.Column="1"
Margin="0,0,10,0"
HorizontalAlignment="Left">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
<RowDefinition /> <RowDefinition />
@ -77,19 +80,6 @@
</MultiBinding> </MultiBinding>
</TextBlock.Text> </TextBlock.Text>
</TextBlock> </TextBlock>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}" Value="Maximized">
<Setter Property="Width" Value="auto" />
</DataTrigger>
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}" Value="Normal">
<Setter Property="Width" Value="400" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid> </Grid>
<!-- 进度条 --> <!-- 进度条 -->
@ -329,7 +319,6 @@
Content="{DynamicResource DeleteAllDownloading}" Content="{DynamicResource DeleteAllDownloading}"
FontSize="12" FontSize="12"
Style="{StaticResource BtnBorderStyle}" /> Style="{StaticResource BtnBorderStyle}" />
</Grid> </Grid>
</Grid> </Grid>

Loading…
Cancel
Save