- Notifications
You must be signed in to change notification settings - Fork744
增加首页图片更换功能#2431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
增加首页图片更换功能#2431
Uh oh!
There was an error while loading.Please reload this page.
Conversation
- 增强ResetBannerImageCommand的错误处理和日志记录- 添加完整路径检查和备用恢复方案- 优化文件删除和默认图片恢复逻辑
coderabbitaibot commentedNov 2, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
总体说明此次变更为主页添加了横幅图像管理功能。通过在视图中添加右键菜单以支持更改或重置横幅图像,并在视图模型中实现相应的业务逻辑,包括图像初始化、文件选择和状态恢复。 变更详情
流程图sequenceDiagram participant User participant ContextMenu as 右键菜单 participant ViewModel as HomePageViewModel participant FileDialog as 文件对话框 participant UI as 界面 User->>ContextMenu: 右键点击横幅 alt 更改横幅 ContextMenu->>ViewModel: 触发 ChangeBannerImageCommand ViewModel->>FileDialog: 打开文件选择对话框 FileDialog-->>ViewModel: 返回选定的图像路径 ViewModel->>ViewModel: 复制图像到自定义路径 ViewModel->>ViewModel: 更新 BannerImageSource 属性 ViewModel->>UI: 刷新横幅显示 else 重置横幅 ContextMenu->>ViewModel: 触发 ResetBannerImageCommand ViewModel->>ViewModel: 删除自定义图像 ViewModel->>ViewModel: 恢复 BannerImageSource 为默认值 ViewModel->>UI: 刷新横幅显示 end代码审查工作量评估🎯 3 (中等复杂度) | ⏱️ ~20-25 分钟 需要额外关注的区域:
诗歌
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (1)
BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs (1)
523-640:建议提取图片加载逻辑到辅助方法图片加载逻辑在多个地方重复(InitializeBannerImage、ChangeBannerImage、ResetBannerImage),建议提取为辅助方法以提高可维护性并确保加载模式的一致性。
示例重构:
privateImageSourceLoadImageFromUri(Uriuri){varbitmap=newBitmapImage();bitmap.BeginInit();bitmap.UriSource=uri;bitmap.CacheOption=BitmapCacheOption.OnLoad;bitmap.EndInit();returnbitmap;}然后在各处使用:
BannerImageSource=LoadImageFromUri(newUri(path));
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
BetterGenshinImpact/View/Pages/HomePage.xaml(2 hunks)BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs(5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs (1)
BetterGenshinImpact/View/PickerWindow.xaml.cs (1)
ImageSource(124-162)
🔇 Additional comments (4)
BetterGenshinImpact/View/Pages/HomePage.xaml (2)
29-34:右键菜单实现正确!上下文菜单的实现合理,命令绑定正确,为用户提供了便捷的背景图片管理功能。
38-38:绑定实现正确!ImageSource 正确绑定到视图模型的 BannerImageSource 属性,支持动态图片切换。
BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs (2)
79-83:属性和常量定义良好!BannerImageSource 属性使用 ObservableProperty 正确声明,图片路径常量定义清晰合理。
616-638:备用恢复机制设计良好!备用方案正确使用了
BitmapCacheOption.OnLoad,双重异常处理提供了良好的容错能力。一旦主路径按照前面的建议修复,这个备用机制将进一步增强健壮性。
| privatevoidInitializeBannerImage() | ||
| { | ||
| try | ||
| { | ||
| // 检查是否存在自定义图片 | ||
| if(File.Exists(CustomBannerImagePath)) | ||
| { | ||
| BannerImageSource=newBitmapImage(newUri(Path.GetFullPath(CustomBannerImagePath))); | ||
| _logger.LogInformation("已加载自定义背景图片"); | ||
| } | ||
| else | ||
| { | ||
| // 使用默认图片 | ||
| BannerImageSource=newBitmapImage(newUri(DefaultBannerImagePath,UriKind.Absolute)); | ||
| _logger.LogInformation("已加载默认背景图片"); | ||
| } | ||
| } | ||
| catch(Exceptionex) | ||
| { | ||
| _logger.LogError(ex,"初始化背景图片失败,使用默认图片"); | ||
| BannerImageSource=newBitmapImage(newUri(DefaultBannerImagePath,UriKind.Absolute)); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
修复 BitmapImage 文件锁定问题
当前的图片加载方式会锁定文件句柄,导致无法删除或替换自定义图片。在 WPF 中加载图片时,应使用BitmapCacheOption.OnLoad 将图片加载到内存后立即释放文件句柄。
应用此修复:
private void InitializeBannerImage() { try { // 检查是否存在自定义图片 if (File.Exists(CustomBannerImagePath)) {- BannerImageSource = new BitmapImage(new Uri(Path.GetFullPath(CustomBannerImagePath)));+ var bitmap = new BitmapImage();+ bitmap.BeginInit();+ bitmap.UriSource = new Uri(Path.GetFullPath(CustomBannerImagePath));+ bitmap.CacheOption = BitmapCacheOption.OnLoad;+ bitmap.EndInit();+ BannerImageSource = bitmap; _logger.LogInformation("已加载自定义背景图片"); } else { // 使用默认图片- BannerImageSource = new BitmapImage(new Uri(DefaultBannerImagePath, UriKind.Absolute));+ var bitmap = new BitmapImage();+ bitmap.BeginInit();+ bitmap.UriSource = new Uri(DefaultBannerImagePath, UriKind.Absolute);+ bitmap.CacheOption = BitmapCacheOption.OnLoad;+ bitmap.EndInit();+ BannerImageSource = bitmap; _logger.LogInformation("已加载默认背景图片"); } } catch (Exception ex) { _logger.LogError(ex, "初始化背景图片失败,使用默认图片");- BannerImageSource = new BitmapImage(new Uri(DefaultBannerImagePath, UriKind.Absolute));+ var bitmap = new BitmapImage();+ bitmap.BeginInit();+ bitmap.UriSource = new Uri(DefaultBannerImagePath, UriKind.Absolute);+ bitmap.CacheOption = BitmapCacheOption.OnLoad;+ bitmap.EndInit();+ BannerImageSource = bitmap; } }🤖 Prompt for AI Agents
In BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs around lines525-547, the BitmapImage is created directly from a file URI which leaves thefile handle open; change the custom-image loading to open a FileStream, callBitmapImage.BeginInit(), set BitmapCacheOption.OnLoad, set StreamSource to theFileStream (or use a MemoryStream), call EndInit(), then close/dispose theFileStream and call Freeze() on the BitmapImage so the file handle is releasedand the image is immutable; keep the default-image path creation as-is but applyFreeze() after initialization for consistency.| [RelayCommand] | ||
| privatevoidChangeBannerImage() | ||
| { | ||
| try | ||
| { | ||
| varopenFileDialog=newOpenFileDialog | ||
| { | ||
| Title="选择背景图片", | ||
| Filter="图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|所有文件|*.*", | ||
| Multiselect=false | ||
| }; | ||
| if(openFileDialog.ShowDialog()==true) | ||
| { | ||
| varselectedFile=openFileDialog.FileName; | ||
| _logger.LogInformation("用户选择了图片: {ImagePath}",selectedFile); | ||
| // 确保目标目录存在 | ||
| vardirectory=Path.GetDirectoryName(CustomBannerImagePath); | ||
| if(!string.IsNullOrEmpty(directory)&&!Directory.Exists(directory)) | ||
| { | ||
| Directory.CreateDirectory(directory); | ||
| _logger.LogInformation("创建了自定义图片目录: {Directory}",directory); | ||
| } | ||
| // 复制图片到自定义路径 | ||
| File.Copy(selectedFile,CustomBannerImagePath,true); | ||
| _logger.LogInformation("图片已复制到: {CustomPath}",CustomBannerImagePath); | ||
| // 更新UI | ||
| BannerImageSource=newBitmapImage(newUri(Path.GetFullPath(CustomBannerImagePath))); | ||
| Toast.Success("背景图片更换成功!"); | ||
| _logger.LogInformation("背景图片更换成功"); | ||
| } | ||
| } | ||
| catch(Exceptionex) | ||
| { | ||
| _logger.LogError(ex,"更换背景图片失败"); | ||
| Toast.Error($"更换背景图片失败:{ex.Message}"); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
修复文件复制和图片加载的文件锁定问题
存在两个问题:
- 第 579 行创建 BitmapImage 时未使用
BitmapCacheOption.OnLoad,会锁定新图片文件 - 第 575 行复制文件时,如果旧的自定义图片正被
BannerImageSource锁定,复制操作会失败
应用此修复:
[RelayCommand] private void ChangeBannerImage() { try { var openFileDialog = new OpenFileDialog { Title = "选择背景图片", Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|所有文件|*.*", Multiselect = false }; if (openFileDialog.ShowDialog() == true) { var selectedFile = openFileDialog.FileName; _logger.LogInformation("用户选择了图片: {ImagePath}", selectedFile); // 确保目标目录存在 var directory = Path.GetDirectoryName(CustomBannerImagePath); if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) { Directory.CreateDirectory(directory); _logger.LogInformation("创建了自定义图片目录: {Directory}", directory); }+ // 先释放当前图片的文件锁,切换到默认图片+ if (File.Exists(Path.GetFullPath(CustomBannerImagePath)))+ {+ var tempBitmap = new BitmapImage();+ tempBitmap.BeginInit();+ tempBitmap.UriSource = new Uri(DefaultBannerImagePath, UriKind.Absolute);+ tempBitmap.CacheOption = BitmapCacheOption.OnLoad;+ tempBitmap.EndInit();+ BannerImageSource = tempBitmap;+ }+ // 复制图片到自定义路径 File.Copy(selectedFile, CustomBannerImagePath, true); _logger.LogInformation("图片已复制到: {CustomPath}", CustomBannerImagePath); // 更新UI- BannerImageSource = new BitmapImage(new Uri(Path.GetFullPath(CustomBannerImagePath)));+ var bitmap = new BitmapImage();+ bitmap.BeginInit();+ bitmap.UriSource = new Uri(Path.GetFullPath(CustomBannerImagePath));+ bitmap.CacheOption = BitmapCacheOption.OnLoad;+ bitmap.EndInit();+ BannerImageSource = bitmap; Toast.Success("背景图片更换成功!"); _logger.LogInformation("背景图片更换成功"); } } catch (Exception ex) { _logger.LogError(ex, "更换背景图片失败"); Toast.Error($"更换背景图片失败: {ex.Message}"); } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| [RelayCommand] | |
| privatevoidChangeBannerImage() | |
| { | |
| try | |
| { | |
| varopenFileDialog=newOpenFileDialog | |
| { | |
| Title="选择背景图片", | |
| Filter="图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|所有文件|*.*", | |
| Multiselect=false | |
| }; | |
| if(openFileDialog.ShowDialog()==true) | |
| { | |
| varselectedFile=openFileDialog.FileName; | |
| _logger.LogInformation("用户选择了图片: {ImagePath}",selectedFile); | |
| // 确保目标目录存在 | |
| vardirectory=Path.GetDirectoryName(CustomBannerImagePath); | |
| if(!string.IsNullOrEmpty(directory)&&!Directory.Exists(directory)) | |
| { | |
| Directory.CreateDirectory(directory); | |
| _logger.LogInformation("创建了自定义图片目录: {Directory}",directory); | |
| } | |
| // 复制图片到自定义路径 | |
| File.Copy(selectedFile,CustomBannerImagePath,true); | |
| _logger.LogInformation("图片已复制到: {CustomPath}",CustomBannerImagePath); | |
| // 更新UI | |
| BannerImageSource=newBitmapImage(newUri(Path.GetFullPath(CustomBannerImagePath))); | |
| Toast.Success("背景图片更换成功!"); | |
| _logger.LogInformation("背景图片更换成功"); | |
| } | |
| } | |
| catch(Exceptionex) | |
| { | |
| _logger.LogError(ex,"更换背景图片失败"); | |
| Toast.Error($"更换背景图片失败:{ex.Message}"); | |
| } | |
| } | |
| [RelayCommand] | |
| privatevoidChangeBannerImage() | |
| { | |
| try | |
| { | |
| varopenFileDialog=newOpenFileDialog | |
| { | |
| Title="选择背景图片", | |
| Filter="图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|所有文件|*.*", | |
| Multiselect=false | |
| }; | |
| if(openFileDialog.ShowDialog()==true) | |
| { | |
| varselectedFile=openFileDialog.FileName; | |
| _logger.LogInformation("用户选择了图片: {ImagePath}",selectedFile); | |
| // 确保目标目录存在 | |
| vardirectory=Path.GetDirectoryName(CustomBannerImagePath); | |
| if(!string.IsNullOrEmpty(directory)&&!Directory.Exists(directory)) | |
| { | |
| Directory.CreateDirectory(directory); | |
| _logger.LogInformation("创建了自定义图片目录: {Directory}",directory); | |
| } | |
| // 先释放当前图片的文件锁,切换到默认图片 | |
| if(File.Exists(Path.GetFullPath(CustomBannerImagePath))) | |
| { | |
| vartempBitmap=newBitmapImage(); | |
| tempBitmap.BeginInit(); | |
| tempBitmap.UriSource=newUri(DefaultBannerImagePath,UriKind.Absolute); | |
| tempBitmap.CacheOption=BitmapCacheOption.OnLoad; | |
| tempBitmap.EndInit(); | |
| BannerImageSource=tempBitmap; | |
| } | |
| // 复制图片到自定义路径 | |
| File.Copy(selectedFile,CustomBannerImagePath,true); | |
| _logger.LogInformation("图片已复制到: {CustomPath}",CustomBannerImagePath); | |
| // 更新UI | |
| varbitmap=newBitmapImage(); | |
| bitmap.BeginInit(); | |
| bitmap.UriSource=newUri(Path.GetFullPath(CustomBannerImagePath)); | |
| bitmap.CacheOption=BitmapCacheOption.OnLoad; | |
| bitmap.EndInit(); | |
| BannerImageSource=bitmap; | |
| Toast.Success("背景图片更换成功!"); | |
| _logger.LogInformation("背景图片更换成功"); | |
| } | |
| } | |
| catch(Exceptionex) | |
| { | |
| _logger.LogError(ex,"更换背景图片失败"); | |
| Toast.Error($"更换背景图片失败:{ex.Message}"); | |
| } | |
| } |
| [RelayCommand] | ||
| privatevoidResetBannerImage() | ||
| { | ||
| try | ||
| { | ||
| // 获取自定义图片的完整路径 | ||
| varcustomImageFullPath=Path.GetFullPath(CustomBannerImagePath); | ||
| _logger.LogInformation("尝试恢复默认背景图片,自定义图片路径: {CustomPath}",customImageFullPath); | ||
| if(File.Exists(customImageFullPath)) | ||
| { | ||
| File.Delete(customImageFullPath); | ||
| _logger.LogInformation("已删除自定义背景图片: {CustomPath}",customImageFullPath); | ||
| } | ||
| else | ||
| { | ||
| _logger.LogInformation("自定义背景图片不存在: {CustomPath}",customImageFullPath); | ||
| } | ||
| // 恢复为默认图片 | ||
| _logger.LogInformation("正在恢复为默认背景图片,默认路径: {DefaultPath}",DefaultBannerImagePath); | ||
| BannerImageSource=newBitmapImage(newUri(DefaultBannerImagePath,UriKind.Absolute)); | ||
| Toast.Success("已恢复为默认背景图片!"); | ||
| _logger.LogInformation("背景图片已恢复为默认"); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
修复恢复默认图片时的文件锁定和一致性问题
存在两个问题:
- 第 612 行创建 BitmapImage 未使用
BitmapCacheOption.OnLoad,与备用方案(第 623-627 行)不一致 - 第 602 行删除文件前,需要先释放当前
BannerImageSource对该文件的锁定
应用此修复:
[RelayCommand] private void ResetBannerImage() { try { // 获取自定义图片的完整路径 var customImageFullPath = Path.GetFullPath(CustomBannerImagePath); _logger.LogInformation("尝试恢复默认背景图片,自定义图片路径: {CustomPath}", customImageFullPath);+ // 先切换到默认图片,释放自定义图片的文件锁+ var defaultBitmap = new BitmapImage();+ defaultBitmap.BeginInit();+ defaultBitmap.UriSource = new Uri(DefaultBannerImagePath, UriKind.Absolute);+ defaultBitmap.CacheOption = BitmapCacheOption.OnLoad;+ defaultBitmap.EndInit();+ BannerImageSource = defaultBitmap;+ _logger.LogInformation("已切换到默认背景图片");+ if (File.Exists(customImageFullPath)) { File.Delete(customImageFullPath); _logger.LogInformation("已删除自定义背景图片: {CustomPath}", customImageFullPath); } else { _logger.LogInformation("自定义背景图片不存在: {CustomPath}", customImageFullPath); }- // 恢复为默认图片- _logger.LogInformation("正在恢复为默认背景图片,默认路径: {DefaultPath}", DefaultBannerImagePath);- BannerImageSource = new BitmapImage(new Uri(DefaultBannerImagePath, UriKind.Absolute)); Toast.Success("已恢复为默认背景图片!"); _logger.LogInformation("背景图片已恢复为默认"); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| [RelayCommand] | |
| privatevoidResetBannerImage() | |
| { | |
| try | |
| { | |
| // 获取自定义图片的完整路径 | |
| varcustomImageFullPath=Path.GetFullPath(CustomBannerImagePath); | |
| _logger.LogInformation("尝试恢复默认背景图片,自定义图片路径: {CustomPath}",customImageFullPath); | |
| if(File.Exists(customImageFullPath)) | |
| { | |
| File.Delete(customImageFullPath); | |
| _logger.LogInformation("已删除自定义背景图片: {CustomPath}",customImageFullPath); | |
| } | |
| else | |
| { | |
| _logger.LogInformation("自定义背景图片不存在: {CustomPath}",customImageFullPath); | |
| } | |
| // 恢复为默认图片 | |
| _logger.LogInformation("正在恢复为默认背景图片,默认路径: {DefaultPath}",DefaultBannerImagePath); | |
| BannerImageSource=newBitmapImage(newUri(DefaultBannerImagePath,UriKind.Absolute)); | |
| Toast.Success("已恢复为默认背景图片!"); | |
| _logger.LogInformation("背景图片已恢复为默认"); | |
| } | |
| [RelayCommand] | |
| privatevoidResetBannerImage() | |
| { | |
| try | |
| { | |
| // 获取自定义图片的完整路径 | |
| varcustomImageFullPath=Path.GetFullPath(CustomBannerImagePath); | |
| _logger.LogInformation("尝试恢复默认背景图片,自定义图片路径: {CustomPath}",customImageFullPath); | |
| // 先切换到默认图片,释放自定义图片的文件锁 | |
| vardefaultBitmap=newBitmapImage(); | |
| defaultBitmap.BeginInit(); | |
| defaultBitmap.UriSource=newUri(DefaultBannerImagePath,UriKind.Absolute); | |
| defaultBitmap.CacheOption=BitmapCacheOption.OnLoad; | |
| defaultBitmap.EndInit(); | |
| BannerImageSource=defaultBitmap; | |
| _logger.LogInformation("已切换到默认背景图片"); | |
| if(File.Exists(customImageFullPath)) | |
| { | |
| File.Delete(customImageFullPath); | |
| _logger.LogInformation("已删除自定义背景图片: {CustomPath}",customImageFullPath); | |
| } | |
| else | |
| { | |
| _logger.LogInformation("自定义背景图片不存在: {CustomPath}",customImageFullPath); | |
| } | |
| Toast.Success("已恢复为默认背景图片!"); | |
| _logger.LogInformation("背景图片已恢复为默认"); | |
| } |
Uh oh!
There was an error while loading.Please reload this page.
Summary by CodeRabbit
发布说明