diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj
index 2a8af330..72d2cd4c 100644
--- a/BetterGenshinImpact/BetterGenshinImpact.csproj
+++ b/BetterGenshinImpact/BetterGenshinImpact.csproj
@@ -10,7 +10,7 @@
true
Assets\Images\logo.ico
BetterGI
- 10.39.1
+ 10.39.2
x64
embedded
@@ -43,6 +43,7 @@
+
diff --git a/BetterGenshinImpact/Core/Video/ObsRecorder.cs b/BetterGenshinImpact/Core/Video/ObsRecorder.cs
index 2d10c7e7..716de5ea 100644
--- a/BetterGenshinImpact/Core/Video/ObsRecorder.cs
+++ b/BetterGenshinImpact/Core/Video/ObsRecorder.cs
@@ -9,6 +9,7 @@ using BetterGenshinImpact.Core.Config;
using BetterGenshinImpact.Core.Recorder;
using BetterGenshinImpact.Core.Recorder.Model;
using BetterGenshinImpact.GameTask.Common;
+using MediaInfo;
using Microsoft.Extensions.Logging;
using OBSWebsocketDotNet;
using OBSWebsocketDotNet.Communication;
@@ -206,14 +207,18 @@ public class ObsRecorder : IVideoRecorder
{
var jsonPath = Path.Combine(folderPath, $"systemInfo.json");
// 计算视频文件大小
- var fileInfo = new FileInfo(videoPath);
- var fileSize = fileInfo.Length;
+ MediaInfo.MediaInfo mediaInfo = new MediaInfo.MediaInfo();
+ mediaInfo.Open(videoPath);
+
+ string durationString = mediaInfo.Get(StreamKind.General, 0, "Duration");
+
+ Console.WriteLine($"视频时长: {durationString}");
// 读取json
var json = File.ReadAllText(jsonPath);
var info = JsonSerializer.Deserialize(json, KeyMouseRecorderJsonLine.JsonOptions);
if (info != null)
{
- info.VideoSize = fileSize.ToString();
+ info.VideoSize = durationString;
// 写入json
File.WriteAllText(jsonPath, JsonSerializer.Serialize(info, KeyMouseRecorderJsonLine.JsonOptions));
}
diff --git a/BetterGenshinImpact/Model/KeyMouseScriptItem.cs b/BetterGenshinImpact/Model/KeyMouseScriptItem.cs
index 56b5889d..98637cff 100644
--- a/BetterGenshinImpact/Model/KeyMouseScriptItem.cs
+++ b/BetterGenshinImpact/Model/KeyMouseScriptItem.cs
@@ -66,16 +66,27 @@ public partial class KeyMouseScriptItem : ObservableObject
[ObservableProperty]
private bool _isPartiallyUploaded;
+ [ObservableProperty]
+ private string _selectedTask = "";
+
+ public List TaskOptions { get; } =
+ [
+ "", "任务一", "任务二", "任务三", "任务四", "任务五",
+ "任务六", "任务七", "任务八", "任务九"
+ ];
+
private string FormatSpeed(double bytesPerSecond)
{
if (bytesPerSecond >= 1024 * 1024) // MB/s
{
return $"{bytesPerSecond / (1024 * 1024):F1} MB/s";
}
+
if (bytesPerSecond >= 1024) // KB/s
{
return $"{bytesPerSecond / 1024:F1} KB/s";
}
+
return $"{bytesPerSecond:F0} B/s";
}
@@ -84,14 +95,19 @@ public partial class KeyMouseScriptItem : ObservableObject
var dirName = new DirectoryInfo(Path).Name;
var userName = TaskContext.Instance().Config.CommonConfig.UserName;
var uid = TaskContext.Instance().Config.CommonConfig.Uid;
-
+
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(uid))
{
- throw new InvalidOperationException("用户名或UID未设置");
+ throw new InvalidOperationException("请先设置用户名和UID");
+ }
+
+ if (string.IsNullOrEmpty(SelectedTask))
+ {
+ throw new InvalidOperationException("请选择本条记录的任务");
}
var relativePath = localFilePath.Replace(_scriptPath, "").TrimStart('\\');
- var remotePath = $"{dirName[..10]}_{userName}_{uid}/{relativePath}";
+ var remotePath = $"{dirName[..10]}_{userName}_{uid}_{SelectedTask}/{relativePath}";
return remotePath.Replace(@"\", "/");
}
@@ -101,17 +117,17 @@ public partial class KeyMouseScriptItem : ObservableObject
{
var collection = DbLiteService.Instance.UserDb.GetCollection("FileUploads");
var files = Directory.GetFiles(Path, "*.*", SearchOption.AllDirectories);
-
+
var hasUploadedFiles = false;
var allFilesUploaded = true;
-
+
foreach (var file in files)
{
try
{
var remotePath = GetRemotePath(file);
var fileUploadItem = collection.FindById(remotePath);
-
+
if (fileUploadItem?.Status == UploadStatus.UploadSuccess.ToString())
{
hasUploadedFiles = true;
@@ -128,7 +144,7 @@ public partial class KeyMouseScriptItem : ObservableObject
return;
}
}
-
+
IsUploadSuccess = allFilesUploaded;
IsPartiallyUploaded = !allFilesUploaded && hasUploadedFiles;
}
@@ -174,23 +190,23 @@ public partial class KeyMouseScriptItem : ObservableObject
IsUploading = true;
IsUploadSuccess = false;
UploadProgress = 0;
-
+
var dirName = new DirectoryInfo(Path).Name;
_logger.LogDebug($"{dirName} 开始上传...");
-
+
await Task.Run(() =>
{
try
{
var tosClient = new TosClientHelper();
var files = Directory.GetFiles(Path, "*.*", SearchOption.AllDirectories);
-
+
// 计算所有文件的总大小
long totalSize = 0;
long uploadedSize = 0;
_lastUploadedSize = 0;
_lastProgressUpdateTime = DateTime.Now;
-
+
foreach (var file in files)
{
_uploadCts.Token.ThrowIfCancellationRequested();
@@ -201,19 +217,19 @@ public partial class KeyMouseScriptItem : ObservableObject
{
_uploadCts.Token.ThrowIfCancellationRequested();
var remotePath = GetRemotePath(file);
-
+
var needUploadFileName = System.IO.Path.GetFileName(file);
var fileSize = new FileInfo(file).Length;
if (needUploadFileName == "video.mkv" || needUploadFileName == "video.mp4")
{
- tosClient.UploadLargeFile(file, remotePath, 20 * 1024 * 1024, (bytes, totalBytes, percentage) =>
+ tosClient.UploadLargeFile(file, remotePath, 20 * 1024 * 1024, (bytes, totalBytes, percentage) =>
{
_uploadCts.Token.ThrowIfCancellationRequested();
var currentFileProgress = bytes;
var overallProgress = ((double)(uploadedSize + currentFileProgress) / totalSize) * 100;
UploadProgress = Math.Min(overallProgress, 99.9);
-
+
// 计算速度
var now = DateTime.Now;
var timeDiff = (now - _lastProgressUpdateTime).TotalSeconds;
@@ -222,11 +238,11 @@ public partial class KeyMouseScriptItem : ObservableObject
var sizeDiff = uploadedSize + currentFileProgress - _lastUploadedSize;
var speed = sizeDiff / timeDiff;
UploadSpeed = FormatSpeed(speed);
-
+
_lastProgressUpdateTime = now;
_lastUploadedSize = uploadedSize + currentFileProgress;
}
-
+
_logger.LogDebug($"上传进度: {overallProgress:F}%");
});
}
@@ -234,15 +250,15 @@ public partial class KeyMouseScriptItem : ObservableObject
{
tosClient.UploadFile(file, remotePath);
}
-
+
uploadedSize += fileSize;
var progress = ((double)uploadedSize / totalSize) * 100;
UploadProgress = Math.Min(progress, 99.9);
}
-
+
UploadProgress = 100;
UploadSpeed = string.Empty; // 清空速度显示
-
+
// 上传完成后,不需要额外的文件夹状态更新
// FileUploadItem 的状态已经在 TosClientHelper 中更新
IsUploadSuccess = true;
@@ -274,6 +290,7 @@ public partial class KeyMouseScriptItem : ObservableObject
{
UploadProgress = 0;
}
+
_uploadCts?.Dispose();
_uploadCts = null;
}
@@ -290,6 +307,7 @@ public partial class KeyMouseScriptItem : ObservableObject
{
break;
}
+
await Task.Delay(100);
}
}
@@ -297,7 +315,6 @@ public partial class KeyMouseScriptItem : ObservableObject
[RelayCommand]
private async Task DeleteUploadedFiles()
{
-
try
{
// 提前验证用户信息,避免开始上传后才发现问题
@@ -308,7 +325,7 @@ public partial class KeyMouseScriptItem : ObservableObject
await MessageBox.ErrorAsync("请先设置用户名和UID");
return;
}
-
+
try
{
var dirName = new DirectoryInfo(Path).Name;
@@ -323,9 +340,9 @@ public partial class KeyMouseScriptItem : ObservableObject
IsDeleting = true;
IsDeleteSuccess = false;
DeleteProgress = 0;
-
+
_logger.LogDebug($"{dirName} 开始删除...");
-
+
await Task.Run(() =>
{
try
@@ -333,7 +350,7 @@ public partial class KeyMouseScriptItem : ObservableObject
var tosClient = new TosClientHelper();
var files = Directory.GetFiles(Path, "*.*", SearchOption.AllDirectories);
var collection = DbLiteService.Instance.UserDb.GetCollection("FileUploads");
-
+
foreach (var file in files)
{
_deleteCts.Token.ThrowIfCancellationRequested();
@@ -341,10 +358,10 @@ public partial class KeyMouseScriptItem : ObservableObject
try
{
var remotePath = GetRemotePath(file);
-
+
// 删除对象存储中的文件
tosClient.DeleteObject(remotePath);
-
+
// 删除数据库中的记录
collection.Delete(remotePath);
}
@@ -353,7 +370,7 @@ public partial class KeyMouseScriptItem : ObservableObject
_logger.LogError($"删除文件失败:{ex.Message}");
}
}
-
+
IsDeleteSuccess = true;
// 重置上传状态
IsUploadSuccess = false;
@@ -391,7 +408,7 @@ public partial class KeyMouseScriptItem : ObservableObject
{
_deleteCts?.Cancel();
}
-
+
public bool VerifyFileHashes(string pcFolder, string hashFolder)
{
var hashFilePath = System.IO.Path.Combine(hashFolder, "hash.json");
diff --git a/BetterGenshinImpact/View/Pages/KeyMouseRecordPage.xaml b/BetterGenshinImpact/View/Pages/KeyMouseRecordPage.xaml
index a638fb7c..c373a5a6 100644
--- a/BetterGenshinImpact/View/Pages/KeyMouseRecordPage.xaml
+++ b/BetterGenshinImpact/View/Pages/KeyMouseRecordPage.xaml
@@ -115,14 +115,16 @@
-
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BetterGenshinImpact/ViewModel/Pages/KeyMouseRecordPageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/KeyMouseRecordPageViewModel.cs
index f3d092e3..fd47bb2c 100644
--- a/BetterGenshinImpact/ViewModel/Pages/KeyMouseRecordPageViewModel.cs
+++ b/BetterGenshinImpact/ViewModel/Pages/KeyMouseRecordPageViewModel.cs
@@ -75,6 +75,7 @@ public partial class KeyMouseRecordPageViewModel : ObservableObject, INavigation
if (existingItem != null)
{
// 如果找到现有项目,保留其状态
+ existingItem.InitializeUploadStatus();
updatedItems.Add(existingItem);
}
else