mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
add refresh time for avatar property
This commit is contained in:
@@ -48,7 +48,7 @@
|
|||||||
<GridLength x:Key="CompatGridLength2">288</GridLength>
|
<GridLength x:Key="CompatGridLength2">288</GridLength>
|
||||||
<x:Double x:Key="CompatSplitViewOpenPaneLength">212</x:Double>
|
<x:Double x:Key="CompatSplitViewOpenPaneLength">212</x:Double>
|
||||||
<x:Double x:Key="CompatSplitViewOpenPaneLength2">304</x:Double>
|
<x:Double x:Key="CompatSplitViewOpenPaneLength2">304</x:Double>
|
||||||
|
<x:Double x:Key="CompatSplitViewOpenPaneLength3">320</x:Double>
|
||||||
<x:Double x:Key="HomeAdaptiveCardHeight">180</x:Double>
|
<x:Double x:Key="HomeAdaptiveCardHeight">180</x:Double>
|
||||||
<x:Double x:Key="ContentDialogMinHeight">64</x:Double>
|
<x:Double x:Key="ContentDialogMinHeight">64</x:Double>
|
||||||
<x:Double x:Key="LargeAppBarButtonWidth">100</x:Double>
|
<x:Double x:Key="LargeAppBarButtonWidth">100</x:Double>
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ namespace Snap.Hutao.Extension;
|
|||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal static class DateTimeOffsetExtension
|
internal static class DateTimeOffsetExtension
|
||||||
{
|
{
|
||||||
|
public static readonly DateTimeOffset DatebaseDefaultTime = new(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从Unix时间戳转换
|
/// 从Unix时间戳转换
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -58,7 +58,15 @@ internal sealed class DailyNoteEntry : ObservableObject, IMappingFrom<DailyNoteE
|
|||||||
public DateTimeOffset RefreshTime { get; set; }
|
public DateTimeOffset RefreshTime { get; set; }
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public string RefreshTimeFormatted { get => SH.ModelEntityDailyNoteRefreshTimeFormat.Format(RefreshTime); }
|
public string RefreshTimeFormatted
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return RefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime
|
||||||
|
? SH.ModelEntityDailyNoteNotRefreshed
|
||||||
|
: SH.ModelEntityDailyNoteRefreshTimeFormat.Format(RefreshTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 树脂提醒阈值
|
/// 树脂提醒阈值
|
||||||
|
|||||||
@@ -420,6 +420,15 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 尚未刷新 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ModelEntityDailyNoteNotRefreshed {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ModelEntityDailyNoteNotRefreshed", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 刷新于 {0:yyyy/MM/dd HH:mm:ss} 的本地化字符串。
|
/// 查找类似 刷新于 {0:yyyy/MM/dd HH:mm:ss} 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1122,6 +1131,60 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 养成计算:尚未刷新 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ServiceAvatarInfoSummaryCalculatorNotRefreshed {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ServiceAvatarInfoSummaryCalculatorNotRefreshed", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 养成计算:{0:MM-dd HH:mm} 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ServiceAvatarInfoSummaryCalculatorRefreshTimeFormat {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ServiceAvatarInfoSummaryCalculatorRefreshTimeFormat", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 我的角色:尚未刷新 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ServiceAvatarInfoSummaryGameRecordNotRefreshed {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ServiceAvatarInfoSummaryGameRecordNotRefreshed", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 我的角色:{0:MM-dd HH:mm} 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ServiceAvatarInfoSummaryGameRecordRefreshTimeFormat {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ServiceAvatarInfoSummaryGameRecordRefreshTimeFormat", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 角色橱窗:尚未刷新 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ServiceAvatarInfoSummaryShowcaseNotRefreshed {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ServiceAvatarInfoSummaryShowcaseNotRefreshed", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 角色橱窗:{0:MM-dd HH:mm} 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 保存养成计划状态失败 的本地化字符串。
|
/// 查找类似 保存养成计划状态失败 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -237,6 +237,9 @@
|
|||||||
<data name="ModelBindingUserInitializationFailed" xml:space="preserve">
|
<data name="ModelBindingUserInitializationFailed" xml:space="preserve">
|
||||||
<value>网络异常</value>
|
<value>网络异常</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ModelEntityDailyNoteNotRefreshed" xml:space="preserve">
|
||||||
|
<value>尚未刷新</value>
|
||||||
|
</data>
|
||||||
<data name="ModelEntityDailyNoteRefreshTimeFormat" xml:space="preserve">
|
<data name="ModelEntityDailyNoteRefreshTimeFormat" xml:space="preserve">
|
||||||
<value>刷新于 {0:yyyy/MM/dd HH:mm:ss}</value>
|
<value>刷新于 {0:yyyy/MM/dd HH:mm:ss}</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -527,6 +530,24 @@
|
|||||||
<value>风元素抗性</value>
|
<value>风元素抗性</value>
|
||||||
<comment>Need EXACT same string in game</comment>
|
<comment>Need EXACT same string in game</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ServiceAvatarInfoSummaryCalculatorNotRefreshed" xml:space="preserve">
|
||||||
|
<value>养成计算:尚未刷新</value>
|
||||||
|
</data>
|
||||||
|
<data name="ServiceAvatarInfoSummaryCalculatorRefreshTimeFormat" xml:space="preserve">
|
||||||
|
<value>养成计算:{0:MM-dd HH:mm}</value>
|
||||||
|
</data>
|
||||||
|
<data name="ServiceAvatarInfoSummaryGameRecordNotRefreshed" xml:space="preserve">
|
||||||
|
<value>我的角色:尚未刷新</value>
|
||||||
|
</data>
|
||||||
|
<data name="ServiceAvatarInfoSummaryGameRecordRefreshTimeFormat" xml:space="preserve">
|
||||||
|
<value>我的角色:{0:MM-dd HH:mm}</value>
|
||||||
|
</data>
|
||||||
|
<data name="ServiceAvatarInfoSummaryShowcaseNotRefreshed" xml:space="preserve">
|
||||||
|
<value>角色橱窗:尚未刷新</value>
|
||||||
|
</data>
|
||||||
|
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
|
||||||
|
<value>角色橱窗:{0:MM-dd HH:mm}</value>
|
||||||
|
</data>
|
||||||
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
|
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
|
||||||
<value>保存养成计划状态失败</value>
|
<value>保存养成计划状态失败</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
/// <param name="webInfos">Enka信息</param>
|
/// <param name="webInfos">Enka信息</param>
|
||||||
/// <param name="token">取消令牌</param>
|
/// <param name="token">取消令牌</param>
|
||||||
/// <returns>角色列表</returns>
|
/// <returns>角色列表</returns>
|
||||||
public List<EnkaAvatarInfo> UpdateDbAvatarInfosByShowcase(string uid, IEnumerable<EnkaAvatarInfo> webInfos, CancellationToken token)
|
public List<EntityAvatarInfo> UpdateDbAvatarInfosByShowcase(string uid, IEnumerable<EnkaAvatarInfo> webInfos, CancellationToken token)
|
||||||
{
|
{
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
List<EntityAvatarInfo> dbInfos = avatarInfoDbService.GetAvatarInfoListByUid(uid);
|
List<EntityAvatarInfo> dbInfos = avatarInfoDbService.GetAvatarInfoListByUid(uid);
|
||||||
@@ -63,7 +63,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
}
|
}
|
||||||
|
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
return avatarInfoDbService.GetAvatarInfoInfoListByUid(uid);
|
return avatarInfoDbService.GetAvatarInfoListByUid(uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
/// <param name="userAndUid">用户与角色</param>
|
/// <param name="userAndUid">用户与角色</param>
|
||||||
/// <param name="token">取消令牌</param>
|
/// <param name="token">取消令牌</param>
|
||||||
/// <returns>角色列表</returns>
|
/// <returns>角色列表</returns>
|
||||||
public async ValueTask<List<EnkaAvatarInfo>> UpdateDbAvatarInfosByGameRecordCharacterAsync(UserAndUid userAndUid, CancellationToken token)
|
public async ValueTask<List<EntityAvatarInfo>> UpdateDbAvatarInfosByGameRecordCharacterAsync(UserAndUid userAndUid, CancellationToken token)
|
||||||
{
|
{
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
string uid = userAndUid.Uid.Value;
|
string uid = userAndUid.Uid.Value;
|
||||||
@@ -121,7 +121,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return avatarInfoDbService.GetAvatarInfoInfoListByUid(uid);
|
return avatarInfoDbService.GetAvatarInfoListByUid(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -130,7 +130,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
/// <param name="userAndUid">用户与角色</param>
|
/// <param name="userAndUid">用户与角色</param>
|
||||||
/// <param name="token">取消令牌</param>
|
/// <param name="token">取消令牌</param>
|
||||||
/// <returns>角色列表</returns>
|
/// <returns>角色列表</returns>
|
||||||
public async ValueTask<List<EnkaAvatarInfo>> UpdateDbAvatarInfosByCalculateAvatarDetailAsync(UserAndUid userAndUid, CancellationToken token)
|
public async ValueTask<List<EntityAvatarInfo>> UpdateDbAvatarInfosByCalculateAvatarDetailAsync(UserAndUid userAndUid, CancellationToken token)
|
||||||
{
|
{
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
string uid = userAndUid.Uid.Value;
|
string uid = userAndUid.Uid.Value;
|
||||||
@@ -173,7 +173,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return avatarInfoDbService.GetAvatarInfoInfoListByUid(uid);
|
return avatarInfoDbService.GetAvatarInfoListByUid(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using Snap.Hutao.Core.Database;
|
using Snap.Hutao.Core.Database;
|
||||||
using Snap.Hutao.Model.Entity.Database;
|
using Snap.Hutao.Model.Entity.Database;
|
||||||
using EnkaAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
|
using EnkaAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
|
||||||
using ModelAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
|
using EntityAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.AvatarInfo;
|
namespace Snap.Hutao.Service.AvatarInfo;
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ internal sealed partial class AvatarInfoDbService : IAvatarInfoDbService
|
|||||||
{
|
{
|
||||||
private readonly IServiceProvider serviceProvider;
|
private readonly IServiceProvider serviceProvider;
|
||||||
|
|
||||||
public List<ModelAvatarInfo> GetAvatarInfoListByUid(string uid)
|
public List<EntityAvatarInfo> GetAvatarInfoListByUid(string uid)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -24,19 +24,6 @@ internal sealed partial class AvatarInfoDbService : IAvatarInfoDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<EnkaAvatarInfo> GetAvatarInfoInfoListByUid(string uid)
|
|
||||||
{
|
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
|
||||||
{
|
|
||||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
|
||||||
return appDbContext.AvatarInfos
|
|
||||||
.AsNoTracking()
|
|
||||||
.Where(i => i.Uid == uid)
|
|
||||||
.Select(i => i.Info)
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeleteAvatarInfoRangeByUid(string uid)
|
public void DeleteAvatarInfoRangeByUid(string uid)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Snap.Hutao.Web.Enka;
|
|||||||
using Snap.Hutao.Web.Enka.Model;
|
using Snap.Hutao.Web.Enka.Model;
|
||||||
using Snap.Hutao.Web.Hoyolab;
|
using Snap.Hutao.Web.Hoyolab;
|
||||||
using EnkaAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
|
using EnkaAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
|
||||||
|
using EntityAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.AvatarInfo;
|
namespace Snap.Hutao.Service.AvatarInfo;
|
||||||
|
|
||||||
@@ -56,28 +57,28 @@ internal sealed partial class AvatarInfoService : IAvatarInfoService
|
|||||||
return new(RefreshResult.ShowcaseNotOpen, default);
|
return new(RefreshResult.ShowcaseNotOpen, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<EnkaAvatarInfo> list = avatarInfoDbBulkOperation.UpdateDbAvatarInfosByShowcase(userAndUid.Uid.Value, resp.AvatarInfoList, token);
|
List<EntityAvatarInfo> list = avatarInfoDbBulkOperation.UpdateDbAvatarInfosByShowcase(userAndUid.Uid.Value, resp.AvatarInfoList, token);
|
||||||
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
||||||
return new(RefreshResult.Ok, summary);
|
return new(RefreshResult.Ok, summary);
|
||||||
}
|
}
|
||||||
|
|
||||||
case RefreshOption.RequestFromHoyolabGameRecord:
|
case RefreshOption.RequestFromHoyolabGameRecord:
|
||||||
{
|
{
|
||||||
List<EnkaAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByGameRecordCharacterAsync(userAndUid, token).ConfigureAwait(false);
|
List<EntityAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByGameRecordCharacterAsync(userAndUid, token).ConfigureAwait(false);
|
||||||
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
||||||
return new(RefreshResult.Ok, summary);
|
return new(RefreshResult.Ok, summary);
|
||||||
}
|
}
|
||||||
|
|
||||||
case RefreshOption.RequestFromHoyolabCalculate:
|
case RefreshOption.RequestFromHoyolabCalculate:
|
||||||
{
|
{
|
||||||
List<EnkaAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByCalculateAvatarDetailAsync(userAndUid, token).ConfigureAwait(false);
|
List<EntityAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByCalculateAvatarDetailAsync(userAndUid, token).ConfigureAwait(false);
|
||||||
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
||||||
return new(RefreshResult.Ok, summary);
|
return new(RefreshResult.Ok, summary);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
List<EnkaAvatarInfo> list = avatarInfoDbService.GetAvatarInfoInfoListByUid(userAndUid.Uid.Value);
|
List<EntityAvatarInfo> list = avatarInfoDbService.GetAvatarInfoListByUid(userAndUid.Uid.Value);
|
||||||
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
return new(RefreshResult.Ok, summary.Avatars.Count == 0 ? null : summary);
|
return new(RefreshResult.Ok, summary.Avatars.Count == 0 ? null : summary);
|
||||||
@@ -96,7 +97,7 @@ internal sealed partial class AvatarInfoService : IAvatarInfoService
|
|||||||
?? await enkaClient.GetDataAsync(uid, token).ConfigureAwait(false);
|
?? await enkaClient.GetDataAsync(uid, token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async ValueTask<Summary> GetSummaryCoreAsync(IEnumerable<EnkaAvatarInfo> avatarInfos, CancellationToken token)
|
private async ValueTask<Summary> GetSummaryCoreAsync(IEnumerable<Model.Entity.AvatarInfo> avatarInfos, CancellationToken token)
|
||||||
{
|
{
|
||||||
using (ValueStopwatch.MeasureExecution(logger))
|
using (ValueStopwatch.MeasureExecution(logger))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,5 +17,5 @@ internal interface ISummaryFactory
|
|||||||
/// <param name="avatarInfos">角色列表</param>
|
/// <param name="avatarInfos">角色列表</param>
|
||||||
/// <param name="token">取消令牌</param>
|
/// <param name="token">取消令牌</param>
|
||||||
/// <returns>简述对象</returns>
|
/// <returns>简述对象</returns>
|
||||||
ValueTask<Summary> CreateAsync(IEnumerable<Web.Enka.Model.AvatarInfo> avatarInfos, CancellationToken token);
|
ValueTask<Summary> CreateAsync(IEnumerable<Model.Entity.AvatarInfo> avatarInfos, CancellationToken token);
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ using Snap.Hutao.Model.Metadata.Converter;
|
|||||||
using Snap.Hutao.Model.Primitive;
|
using Snap.Hutao.Model.Primitive;
|
||||||
using Snap.Hutao.ViewModel.AvatarProperty;
|
using Snap.Hutao.ViewModel.AvatarProperty;
|
||||||
using Snap.Hutao.Web.Enka.Model;
|
using Snap.Hutao.Web.Enka.Model;
|
||||||
|
using EntityAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
|
||||||
using MetadataAvatar = Snap.Hutao.Model.Metadata.Avatar.Avatar;
|
using MetadataAvatar = Snap.Hutao.Model.Metadata.Avatar.Avatar;
|
||||||
using MetadataWeapon = Snap.Hutao.Model.Metadata.Weapon.Weapon;
|
using MetadataWeapon = Snap.Hutao.Model.Metadata.Weapon.Weapon;
|
||||||
using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
|
using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
|
||||||
@@ -21,7 +22,12 @@ namespace Snap.Hutao.Service.AvatarInfo.Factory;
|
|||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal sealed class SummaryAvatarFactory
|
internal sealed class SummaryAvatarFactory
|
||||||
{
|
{
|
||||||
|
private static readonly DateTimeOffset DefaultRefreshTime = new(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0));
|
||||||
|
|
||||||
private readonly ModelAvatarInfo avatarInfo;
|
private readonly ModelAvatarInfo avatarInfo;
|
||||||
|
private readonly DateTimeOffset showcaseRefreshTime;
|
||||||
|
private readonly DateTimeOffset gameRecordRefreshTime;
|
||||||
|
private readonly DateTimeOffset calculatorRefreshTime;
|
||||||
private readonly SummaryMetadataContext metadataContext;
|
private readonly SummaryMetadataContext metadataContext;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -29,10 +35,14 @@ internal sealed class SummaryAvatarFactory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="metadataContext">元数据上下文</param>
|
/// <param name="metadataContext">元数据上下文</param>
|
||||||
/// <param name="avatarInfo">角色信息</param>
|
/// <param name="avatarInfo">角色信息</param>
|
||||||
public SummaryAvatarFactory(SummaryMetadataContext metadataContext, ModelAvatarInfo avatarInfo)
|
public SummaryAvatarFactory(SummaryMetadataContext metadataContext, EntityAvatarInfo avatarInfo)
|
||||||
{
|
{
|
||||||
this.metadataContext = metadataContext;
|
this.metadataContext = metadataContext;
|
||||||
this.avatarInfo = avatarInfo;
|
this.avatarInfo = avatarInfo.Info;
|
||||||
|
|
||||||
|
showcaseRefreshTime = avatarInfo.ShowcaseRefreshTime;
|
||||||
|
gameRecordRefreshTime = avatarInfo.GameRecordRefreshTime;
|
||||||
|
calculatorRefreshTime = avatarInfo.CalculatorRefreshTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -67,6 +77,17 @@ internal sealed class SummaryAvatarFactory
|
|||||||
Weapon = reliquaryAndWeapon.Weapon,
|
Weapon = reliquaryAndWeapon.Weapon,
|
||||||
Reliquaries = reliquaryAndWeapon.Reliquaries,
|
Reliquaries = reliquaryAndWeapon.Reliquaries,
|
||||||
Score = $"{reliquaryAndWeapon.Reliquaries.Sum(r => r.Score):F2}",
|
Score = $"{reliquaryAndWeapon.Reliquaries.Sum(r => r.Score):F2}",
|
||||||
|
|
||||||
|
// times
|
||||||
|
ShowcaseRefreshTimeFormat = showcaseRefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime
|
||||||
|
? SH.ServiceAvatarInfoSummaryShowcaseNotRefreshed
|
||||||
|
: SH.ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat.Format(showcaseRefreshTime),
|
||||||
|
GameRecordRefreshTimeFormat = gameRecordRefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime
|
||||||
|
? SH.ServiceAvatarInfoSummaryGameRecordNotRefreshed
|
||||||
|
: SH.ServiceAvatarInfoSummaryGameRecordRefreshTimeFormat.Format(gameRecordRefreshTime),
|
||||||
|
CalculatorRefreshTimeFormat = calculatorRefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime
|
||||||
|
? SH.ServiceAvatarInfoSummaryCalculatorNotRefreshed
|
||||||
|
: SH.ServiceAvatarInfoSummaryCalculatorRefreshTimeFormat.Format(calculatorRefreshTime),
|
||||||
};
|
};
|
||||||
|
|
||||||
ApplyCostumeIconOrDefault(ref propertyAvatar, avatar);
|
ApplyCostumeIconOrDefault(ref propertyAvatar, avatar);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
using Snap.Hutao.Model.Metadata;
|
using Snap.Hutao.Model.Metadata;
|
||||||
using Snap.Hutao.Service.Metadata;
|
using Snap.Hutao.Service.Metadata;
|
||||||
using Snap.Hutao.ViewModel.AvatarProperty;
|
using Snap.Hutao.ViewModel.AvatarProperty;
|
||||||
using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
|
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.AvatarInfo.Factory;
|
namespace Snap.Hutao.Service.AvatarInfo.Factory;
|
||||||
|
|
||||||
@@ -19,7 +18,7 @@ internal sealed partial class SummaryFactory : ISummaryFactory
|
|||||||
private readonly IMetadataService metadataService;
|
private readonly IMetadataService metadataService;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async ValueTask<Summary> CreateAsync(IEnumerable<ModelAvatarInfo> avatarInfos, CancellationToken token)
|
public async ValueTask<Summary> CreateAsync(IEnumerable<Model.Entity.AvatarInfo> avatarInfos, CancellationToken token)
|
||||||
{
|
{
|
||||||
SummaryMetadataContext metadataContext = new()
|
SummaryMetadataContext metadataContext = new()
|
||||||
{
|
{
|
||||||
@@ -35,7 +34,7 @@ internal sealed partial class SummaryFactory : ISummaryFactory
|
|||||||
return new()
|
return new()
|
||||||
{
|
{
|
||||||
Avatars = avatarInfos
|
Avatars = avatarInfos
|
||||||
.Where(a => !AvatarIds.IsPlayer(a.AvatarId))
|
.Where(a => !AvatarIds.IsPlayer(a.Info.AvatarId))
|
||||||
.Select(a => new SummaryAvatarFactory(metadataContext, a).Create())
|
.Select(a => new SummaryAvatarFactory(metadataContext, a).Create())
|
||||||
.OrderByDescending(a => a.LevelNumber)
|
.OrderByDescending(a => a.LevelNumber)
|
||||||
.ThenBy(a => a.Name)
|
.ThenBy(a => a.Name)
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using EnkaAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
|
using EntityAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
|
||||||
using ModelAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
|
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.AvatarInfo;
|
namespace Snap.Hutao.Service.AvatarInfo;
|
||||||
|
|
||||||
@@ -10,7 +9,5 @@ internal interface IAvatarInfoDbService
|
|||||||
{
|
{
|
||||||
void DeleteAvatarInfoRangeByUid(string uid);
|
void DeleteAvatarInfoRangeByUid(string uid);
|
||||||
|
|
||||||
List<EnkaAvatarInfo> GetAvatarInfoInfoListByUid(string uid);
|
List<EntityAvatarInfo> GetAvatarInfoListByUid(string uid);
|
||||||
|
|
||||||
List<ModelAvatarInfo> GetAvatarInfoListByUid(string uid);
|
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
DisplayMode="Inline"
|
DisplayMode="Inline"
|
||||||
IsPaneOpen="True"
|
IsPaneOpen="True"
|
||||||
OpenPaneLength="{StaticResource CompatSplitViewOpenPaneLength}"
|
OpenPaneLength="{StaticResource CompatSplitViewOpenPaneLength3}"
|
||||||
PaneBackground="Transparent">
|
PaneBackground="Transparent">
|
||||||
<SplitView.Pane>
|
<SplitView.Pane>
|
||||||
<ListView ItemsSource="{Binding Summary.Avatars}" SelectedItem="{Binding SelectedAvatar, Mode=TwoWay}">
|
<ListView ItemsSource="{Binding Summary.Avatars}" SelectedItem="{Binding SelectedAvatar, Mode=TwoWay}">
|
||||||
@@ -236,7 +236,8 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition Width="auto"/>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<shci:CachedImage
|
<shci:CachedImage
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
@@ -245,13 +246,34 @@
|
|||||||
Margin="0,0,12,12"
|
Margin="0,0,12,12"
|
||||||
Source="{Binding SideIcon, Mode=OneWay}"/>
|
Source="{Binding SideIcon, Mode=OneWay}"/>
|
||||||
<StackPanel Grid.Column="1" VerticalAlignment="Center">
|
<StackPanel Grid.Column="1" VerticalAlignment="Center">
|
||||||
<TextBlock Margin="12,0,0,0" Text="{Binding Name}"/>
|
<TextBlock
|
||||||
|
Margin="12,0,0,0"
|
||||||
|
Text="{Binding Name}"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
TextWrapping="NoWrap"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="12,0,0,0"
|
Margin="12,0,0,0"
|
||||||
Opacity="0.7"
|
Opacity="0.7"
|
||||||
Style="{StaticResource CaptionTextBlockStyle}"
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
Text="{Binding Level}"/>
|
Text="{Binding Level}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<StackPanel
|
||||||
|
Grid.Column="2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Opacity="0.7">
|
||||||
|
<TextBlock
|
||||||
|
FontSize="11"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{Binding ShowcaseRefreshTimeFormat}"/>
|
||||||
|
<TextBlock
|
||||||
|
FontSize="11"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{Binding GameRecordRefreshTimeFormat}"/>
|
||||||
|
<TextBlock
|
||||||
|
FontSize="11"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{Binding CalculatorRefreshTimeFormat}"/>
|
||||||
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</ListView.ItemTemplate>
|
||||||
|
|||||||
@@ -93,6 +93,12 @@ internal sealed class AvatarView : INameIconSide, ICalculableSource<ICalculableA
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public uint FetterLevel { get; set; }
|
public uint FetterLevel { get; set; }
|
||||||
|
|
||||||
|
public string ShowcaseRefreshTimeFormat { get; set; }
|
||||||
|
|
||||||
|
public string GameRecordRefreshTimeFormat { get; set; }
|
||||||
|
|
||||||
|
public string CalculatorRefreshTimeFormat { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id
|
/// Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user