feat: 添加游戏资源链接管理工具 - #71
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
Reviewer's Guide引入一个新的游戏资源链接管理工具,通过 Windows junction 让用户在多份 maimai 安装之间共享 AssetBundleImages/MovieData/SoundData 目录,并包含后端服务、HTTP API、前端弹窗、本地化、文档和测试,且受严格安全规则约束,并支持按会话选择资源源目录和目标目录。 游戏资源 junction 管理流程时序图sequenceDiagram
actor User
participant ResourceJunctionModal
participant ApiClient as Api
participant ResourceJunctionController
participant ResourceJunctionService
User->>ResourceJunctionModal: trigger()
ResourceJunctionModal->>ApiClient: AutoSelectResourceJunctionSource
ApiClient->>ResourceJunctionController: AutoSelectResourceJunctionSource
ResourceJunctionController->>ResourceJunctionService: AutoSelectSource
ResourceJunctionService-->>ResourceJunctionController: ResourceJunctionOverview
ResourceJunctionController-->>ApiClient: ResourceJunctionOverview
ApiClient-->>ResourceJunctionModal: overview
User->>ResourceJunctionModal: click selectSource
ResourceJunctionModal->>ApiClient: SelectResourceJunctionSource
ApiClient->>ResourceJunctionController: SelectResourceJunctionSource
ResourceJunctionController->>ResourceJunctionService: SelectManualSource
ResourceJunctionService-->>ResourceJunctionController: ResourceJunctionOverview
ResourceJunctionController-->>ApiClient: ResourceJunctionOverview
ApiClient-->>ResourceJunctionModal: overview
User->>ResourceJunctionModal: confirm create
ResourceJunctionModal->>ApiClient: CreateResourceJunctions
ApiClient->>ResourceJunctionController: CreateResourceJunctions
ResourceJunctionController->>ResourceJunctionService: CreateLinks
ResourceJunctionService-->>ResourceJunctionController: ResourceJunctionItem[]
ResourceJunctionController-->>ApiClient: ResourceJunctionOverview(items)
ApiClient-->>ResourceJunctionModal: updated overview
User->>ResourceJunctionModal: confirm remove
ResourceJunctionModal->>ApiClient: RemoveResourceJunctions
ApiClient->>ResourceJunctionController: RemoveResourceJunctions
ResourceJunctionController->>ResourceJunctionService: RemoveLinks
ResourceJunctionService-->>ResourceJunctionController: ResourceJunctionItem[]
ResourceJunctionController-->>ApiClient: ResourceJunctionOverview(items)
ApiClient-->>ResourceJunctionModal: updated overview
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your Experience访问你的 dashboard,可以:
Getting HelpOriginal review guide in EnglishReviewer's GuideIntroduce a new game resource link management tool that lets users share AssetBundleImages/MovieData/SoundData directories between maimai installs via Windows junctions, with a backend service, HTTP APIs, a frontend modal, localization, documentation, and tests, all constrained by strict safety rules and per-session source/target selection. Sequence diagram for game resource junction management flowsequenceDiagram
actor User
participant ResourceJunctionModal
participant ApiClient as Api
participant ResourceJunctionController
participant ResourceJunctionService
User->>ResourceJunctionModal: trigger()
ResourceJunctionModal->>ApiClient: AutoSelectResourceJunctionSource
ApiClient->>ResourceJunctionController: AutoSelectResourceJunctionSource
ResourceJunctionController->>ResourceJunctionService: AutoSelectSource
ResourceJunctionService-->>ResourceJunctionController: ResourceJunctionOverview
ResourceJunctionController-->>ApiClient: ResourceJunctionOverview
ApiClient-->>ResourceJunctionModal: overview
User->>ResourceJunctionModal: click selectSource
ResourceJunctionModal->>ApiClient: SelectResourceJunctionSource
ApiClient->>ResourceJunctionController: SelectResourceJunctionSource
ResourceJunctionController->>ResourceJunctionService: SelectManualSource
ResourceJunctionService-->>ResourceJunctionController: ResourceJunctionOverview
ResourceJunctionController-->>ApiClient: ResourceJunctionOverview
ApiClient-->>ResourceJunctionModal: overview
User->>ResourceJunctionModal: confirm create
ResourceJunctionModal->>ApiClient: CreateResourceJunctions
ApiClient->>ResourceJunctionController: CreateResourceJunctions
ResourceJunctionController->>ResourceJunctionService: CreateLinks
ResourceJunctionService-->>ResourceJunctionController: ResourceJunctionItem[]
ResourceJunctionController-->>ApiClient: ResourceJunctionOverview(items)
ApiClient-->>ResourceJunctionModal: updated overview
User->>ResourceJunctionModal: confirm remove
ResourceJunctionModal->>ApiClient: RemoveResourceJunctions
ApiClient->>ResourceJunctionController: RemoveResourceJunctions
ResourceJunctionController->>ResourceJunctionService: RemoveLinks
ResourceJunctionService-->>ResourceJunctionController: ResourceJunctionItem[]
ResourceJunctionController-->>ApiClient: ResourceJunctionOverview(items)
ApiClient-->>ResourceJunctionModal: updated overview
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - 我发现了 1 个问题,并给出了一些整体反馈:
- ResourceJunctionController 中的文件夹选择提示(“Select a source game directory or Package directory” / “Select a target game directory or Package directory”)是直接硬编码为英文的;建议把它们移到现有的 i18n/本地化系统中,以便与其他 UI 文本保持一致。
- 使用
mklink的连接创建逻辑在 ResourceJunctionService 和 ResourceJunctionServiceTests 中都有重复;建议将这部分逻辑集中到一个共享的辅助方法中,避免实现出现差异,并让后续调整实现更容易(例如,如果以后不再通过调用cmd来完成)。
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- ResourceJunctionController 中的文件夹选择提示(“Select a source game directory or Package directory” / “Select a target game directory or Package directory”)是直接硬编码为英文的;建议把它们移到现有的 i18n/本地化系统中,以便与其他 UI 文本保持一致。
- 使用 `mklink` 的连接创建逻辑在 ResourceJunctionService 和 ResourceJunctionServiceTests 中都有重复;建议将这部分逻辑集中到一个共享的辅助方法中,避免实现出现差异,并让后续调整实现更容易(例如,如果以后不再通过调用 `cmd` 来完成)。
## Individual Comments
### Comment 1
<location path="MaiChartManager/Services/ResourceJunctionService.cs" line_range="384-393" />
<code_context>
+ Directory.Delete(root, true);
+ }
+
+ private static void CreateJunction(string source, string target)
+ {
+ var startInfo = new System.Diagnostics.ProcessStartInfo
+ {
+ FileName = Environment.GetEnvironmentVariable("ComSpec") ?? "cmd.exe",
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ };
+ startInfo.ArgumentList.Add("/d");
+ startInfo.ArgumentList.Add("/c");
+ startInfo.ArgumentList.Add("mklink");
+ startInfo.ArgumentList.Add("/J");
+ startInfo.ArgumentList.Add(target);
+ startInfo.ArgumentList.Add(source);
+ using var process = System.Diagnostics.Process.Start(startInfo)!;
+ process.WaitForExit();
</code_context>
<issue_to_address>
**issue (bug_risk):** 在使用 `cmd.exe mklink` 创建连接时,如果不对路径进行引号包裹,包含空格或特殊字符的路径会导致失败。
由于 `ArgumentList` 传递给 `mklink` 的参数没有加引号,`source` 或 `target` 中的任何空格或特殊字符都会让 `cmd` 错误解析这些参数,进而导致连接创建失败。请在构造命令时确保两个路径都经过适当的引号包裹/转义,或者用直接的 Win32 实现(通过 `CreateFile` + `DeviceIoControl` 调用 `FSCTL_SET_REPARSE_POINT`)或托管辅助方法来替代 `cmd mklink` 调用。至少需要保证在诸如 `Program Files` 和用户配置文件等典型路径位置下,连接创建是健壮可靠的。
</issue_to_address>Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Original comment in English
Hey - I've found 1 issue, and left some high level feedback:
- The folder selection prompts in ResourceJunctionController ("Select a source game directory or Package directory" / "Select a target game directory or Package directory") are hardcoded in English; consider moving them into the existing i18n/localization system so they match the rest of the UI.
- The junction-creation logic using
mklinkis duplicated in both ResourceJunctionService and ResourceJunctionServiceTests; consider centralizing this into a shared helper to avoid divergence and make it easier to adjust the implementation (e.g., if you later switch away from shelling out tocmd).
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The folder selection prompts in ResourceJunctionController ("Select a source game directory or Package directory" / "Select a target game directory or Package directory") are hardcoded in English; consider moving them into the existing i18n/localization system so they match the rest of the UI.
- The junction-creation logic using `mklink` is duplicated in both ResourceJunctionService and ResourceJunctionServiceTests; consider centralizing this into a shared helper to avoid divergence and make it easier to adjust the implementation (e.g., if you later switch away from shelling out to `cmd`).
## Individual Comments
### Comment 1
<location path="MaiChartManager/Services/ResourceJunctionService.cs" line_range="384-393" />
<code_context>
+ Directory.Delete(root, true);
+ }
+
+ private static void CreateJunction(string source, string target)
+ {
+ var startInfo = new System.Diagnostics.ProcessStartInfo
+ {
+ FileName = Environment.GetEnvironmentVariable("ComSpec") ?? "cmd.exe",
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ };
+ startInfo.ArgumentList.Add("/d");
+ startInfo.ArgumentList.Add("/c");
+ startInfo.ArgumentList.Add("mklink");
+ startInfo.ArgumentList.Add("/J");
+ startInfo.ArgumentList.Add(target);
+ startInfo.ArgumentList.Add(source);
+ using var process = System.Diagnostics.Process.Start(startInfo)!;
+ process.WaitForExit();
</code_context>
<issue_to_address>
**issue (bug_risk):** Creating junctions via `cmd.exe mklink` without quoting paths will break for paths with spaces or special characters.
Because `ArgumentList` passes `mklink` arguments without quoting, any spaces or special characters in `source` or `target` will cause `cmd` to parse them incorrectly and the junction creation to fail. Please either ensure both paths are properly quoted/escaped when constructing the command, or replace the `cmd mklink` call with a direct Win32-based implementation (`FSCTL_SET_REPARSE_POINT` via `CreateFile` + `DeviceIoControl`) or a managed helper. At minimum, junction creation must be robust for paths under typical locations like `Program Files` and user profiles.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| private static void CreateJunction(string source, string target) | ||
| { | ||
| var startInfo = new ProcessStartInfo | ||
| { | ||
| FileName = Environment.GetEnvironmentVariable("ComSpec") ?? "cmd.exe", | ||
| UseShellExecute = false, | ||
| CreateNoWindow = true, | ||
| RedirectStandardOutput = true, | ||
| RedirectStandardError = true, | ||
| }; |
There was a problem hiding this comment.
issue (bug_risk): 在使用 cmd.exe mklink 创建连接时,如果不对路径进行引号包裹,包含空格或特殊字符的路径会导致失败。
由于 ArgumentList 传递给 mklink 的参数没有加引号,source 或 target 中的任何空格或特殊字符都会让 cmd 错误解析这些参数,进而导致连接创建失败。请在构造命令时确保两个路径都经过适当的引号包裹/转义,或者用直接的 Win32 实现(通过 CreateFile + DeviceIoControl 调用 FSCTL_SET_REPARSE_POINT)或托管辅助方法来替代 cmd mklink 调用。至少需要保证在诸如 Program Files 和用户配置文件等典型路径位置下,连接创建是健壮可靠的。
Original comment in English
issue (bug_risk): Creating junctions via cmd.exe mklink without quoting paths will break for paths with spaces or special characters.
Because ArgumentList passes mklink arguments without quoting, any spaces or special characters in source or target will cause cmd to parse them incorrectly and the junction creation to fail. Please either ensure both paths are properly quoted/escaped when constructing the command, or replace the cmd mklink call with a direct Win32-based implementation (FSCTL_SET_REPARSE_POINT via CreateFile + DeviceIoControl) or a managed helper. At minimum, junction creation must be robust for paths under typical locations like Program Files and user profiles.
|
不如 PR 正文写一下你的提示词和使用的模型,还有 harness 和装了哪些 skills,这样我审核的更快 |
There was a problem hiding this comment.
Pull request overview
This PR adds a new “Game Resource Links” tool to MaiChartManager to share large maimai resource folders across multiple game installs by creating/removing Windows Junctions, with a front-end modal + backend API/service, safety checks, localization, docs, and unit tests.
Changes:
- Introduce
ResourceJunctionService+ResourceJunctionControllerto inspect/auto-select source/target roots and create/remove Junctions forAssetBundleImages,MovieData,SoundData. - Add a new Tools modal entry in the Vue UI to show selection info, file counts, Junction status, and to run create/remove with confirmation.
- Update generated client types/endpoints, add i18n strings, add user documentation, and add unit tests for selection + Junction behavior.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| MaiChartManager/Services/ResourceJunctionService.cs | Core logic: candidate discovery, file counting, Junction inspection/create/remove, and safety checks. |
| MaiChartManager/ServerManager.cs | Registers ResourceJunctionService in DI. |
| MaiChartManager/Front/src/views/Tools/ResourceJunctionModal.tsx | New modal UI for selecting source/target and managing Junctions. |
| MaiChartManager/Front/src/views/Tools/index.tsx | Adds the new tool entry to the Tools panel and mounts the modal. |
| MaiChartManager/Front/src/locales/zh.yaml | Adds Simplified Chinese strings for the new tool. |
| MaiChartManager/Front/src/locales/zh-TW.yaml | Adds Traditional Chinese strings for the new tool. |
| MaiChartManager/Front/src/locales/en.yaml | Adds English strings for the new tool. |
| MaiChartManager/Front/src/client/apiGen.ts | Updates generated API client types/endpoints (resource junction APIs + store purchase enum change). |
| MaiChartManager/Controllers/Tools/ResourceJunctionController.cs | New HTTP API endpoints for status/auto/manual select/create/remove, including local-action header gating for POSTs. |
| MaiChartManager.Tests/Services/ResourceJunctionServiceTests.cs | Adds unit tests for source selection logic and Junction create/remove safety behavior. |
| MaiChartManager.Tests/MaiChartManager.Tests.csproj | Updates test target framework to Windows TFM. |
| docs/resource-junction-manager.md | User-facing documentation describing selection rules, scope, and safety boundaries. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var directory = new DirectoryInfo(Path.Combine(root, name)); | ||
| if (!directory.Exists || (directory.Attributes & FileAttributes.ReparsePoint) != 0) | ||
| throw new IOException($"{name} is missing or is a reparse point."); | ||
| return new ResourceDirectoryFileCount(name, directory.EnumerateFiles("*", SearchOption.AllDirectories).LongCount()); | ||
| }).ToArray(); |
| export interface RequestPurchaseResult { | ||
| errorMessage?: string | null; | ||
| /** @format int32 */ | ||
| status?: number; | ||
| status?: StorePurchaseStatus; | ||
| } |
| const statusClass = (status?: ResourceJunctionStatus) => { | ||
| if (['Created', 'AlreadyLinked', 'Removed'].includes(status)) return 'text-green-700'; | ||
| if (status === 'Ready') return 'text-blue-700'; | ||
| return 'text-red-700'; | ||
| }; |
There was a problem hiding this comment.
3 issues found across 12 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="MaiChartManager/Services/ResourceJunctionService.cs">
<violation number="1" location="MaiChartManager/Services/ResourceJunctionService.cs:208">
P1: Removal is vulnerable to a filesystem race: a verified junction can be swapped after `Inspect` and before this path-based delete, causing an ordinary replacement (including an empty directory) to be removed. An opened reparse-point handle with an atomic, identity-checked delete would preserve the no-wrong-target deletion guarantee.</violation>
</file>
<file name="MaiChartManager.Tests/MaiChartManager.Tests.csproj">
<violation number="1" location="MaiChartManager.Tests/MaiChartManager.Tests.csproj:3">
P3: Changing the test project to a Windows-only TFM (net10.0-windows10.0.17763.0) makes `dotnet test`/`dotnet build` of this project fail on non-Windows machines/CI unless the Windows targeting pack is available. The main project deliberately keeps a net10.0 Linux configuration, but the test project now has no such escape hatch, so a Linux `dotnet test MaiChartManager.Tests` no longer works. Consider adding `<EnableWindowsTargeting>true</EnableWindowsTargeting>` so the project (and any future Linux CI) can still restore/build the Windows reference assemblies — this only affects build-time downloads and does not change runtime behavior.</violation>
</file>
<file name="MaiChartManager/ServerManager.cs">
<violation number="1" location="MaiChartManager/ServerManager.cs:107">
P2: ResourceJunctionService is registered as a singleton but stores the whole interactive selection session in mutable instance fields (`selectedSourceRoot`, `selectedTargetRoot`, `selectionMode`, ...). Since the local Kestrel services requests on the thread pool, two concurrent requests (a status poll racing a Create/Remove, or the tool opened in two tabs) can interleave mutations of these shared fields mid-operation, so the create/remove/verify sequence can observe another request's selection values. Either keep the per-request selection out of the singleton (pass source/target explicitly to the mutating methods), add synchronization, or register it scoped so each request owns its own state.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
|
||
| try | ||
| { | ||
| Directory.Delete(item.Target, false); |
There was a problem hiding this comment.
P1: Removal is vulnerable to a filesystem race: a verified junction can be swapped after Inspect and before this path-based delete, causing an ordinary replacement (including an empty directory) to be removed. An opened reparse-point handle with an atomic, identity-checked delete would preserve the no-wrong-target deletion guarantee.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At MaiChartManager/Services/ResourceJunctionService.cs, line 208:
<comment>Removal is vulnerable to a filesystem race: a verified junction can be swapped after `Inspect` and before this path-based delete, causing an ordinary replacement (including an empty directory) to be removed. An opened reparse-point handle with an atomic, identity-checked delete would preserve the no-wrong-target deletion guarantee.</comment>
<file context>
@@ -0,0 +1,457 @@
+
+ try
+ {
+ Directory.Delete(item.Target, false);
+ var verified = Inspect(name, sourceRoot, targetRoot);
+ return verified.Status == ResourceJunctionStatus.Ready
</file context>
| .AddSingleton<MaidataImportService>() | ||
| .AddSingleton<MuModService>() | ||
| .AddSingleton<ModConfigService>() | ||
| .AddSingleton<MaiChartManager.Services.ResourceJunctionService>() |
There was a problem hiding this comment.
P2: ResourceJunctionService is registered as a singleton but stores the whole interactive selection session in mutable instance fields (selectedSourceRoot, selectedTargetRoot, selectionMode, ...). Since the local Kestrel services requests on the thread pool, two concurrent requests (a status poll racing a Create/Remove, or the tool opened in two tabs) can interleave mutations of these shared fields mid-operation, so the create/remove/verify sequence can observe another request's selection values. Either keep the per-request selection out of the singleton (pass source/target explicitly to the mutating methods), add synchronization, or register it scoped so each request owns its own state.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At MaiChartManager/ServerManager.cs, line 107:
<comment>ResourceJunctionService is registered as a singleton but stores the whole interactive selection session in mutable instance fields (`selectedSourceRoot`, `selectedTargetRoot`, `selectionMode`, ...). Since the local Kestrel services requests on the thread pool, two concurrent requests (a status poll racing a Create/Remove, or the tool opened in two tabs) can interleave mutations of these shared fields mid-operation, so the create/remove/verify sequence can observe another request's selection values. Either keep the per-request selection out of the singleton (pass source/target explicitly to the mutating methods), add synchronization, or register it scoped so each request owns its own state.</comment>
<file context>
@@ -104,6 +104,7 @@ public static Task StartApp(bool export, Action<string>? onStart = null, bool se
.AddSingleton<MaidataImportService>()
.AddSingleton<MuModService>()
.AddSingleton<ModConfigService>()
+ .AddSingleton<MaiChartManager.Services.ResourceJunctionService>()
.AddEndpointsApiExplorer()
.AddSwaggerGen(options => { options.CustomSchemaIds(type => type.Name == "Config" ? type.FullName : type.Name); })
</file context>
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <PropertyGroup> | ||
| <TargetFramework>net10.0</TargetFramework> | ||
| <TargetFramework>net10.0-windows10.0.17763.0</TargetFramework> |
There was a problem hiding this comment.
P3: Changing the test project to a Windows-only TFM (net10.0-windows10.0.17763.0) makes dotnet test/dotnet build of this project fail on non-Windows machines/CI unless the Windows targeting pack is available. The main project deliberately keeps a net10.0 Linux configuration, but the test project now has no such escape hatch, so a Linux dotnet test MaiChartManager.Tests no longer works. Consider adding <EnableWindowsTargeting>true</EnableWindowsTargeting> so the project (and any future Linux CI) can still restore/build the Windows reference assemblies — this only affects build-time downloads and does not change runtime behavior.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At MaiChartManager.Tests/MaiChartManager.Tests.csproj, line 3:
<comment>Changing the test project to a Windows-only TFM (net10.0-windows10.0.17763.0) makes `dotnet test`/`dotnet build` of this project fail on non-Windows machines/CI unless the Windows targeting pack is available. The main project deliberately keeps a net10.0 Linux configuration, but the test project now has no such escape hatch, so a Linux `dotnet test MaiChartManager.Tests` no longer works. Consider adding `<EnableWindowsTargeting>true</EnableWindowsTargeting>` so the project (and any future Linux CI) can still restore/build the Windows reference assemblies — this only affects build-time downloads and does not change runtime behavior.</comment>
<file context>
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
- <TargetFramework>net10.0</TargetFramework>
+ <TargetFramework>net10.0-windows10.0.17763.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</file context>
| <TargetFramework>net10.0-windows10.0.17763.0</TargetFramework> | |
| <TargetFramework>net10.0-windows10.0.17763.0</TargetFramework> | |
| <EnableWindowsTargeting>true</EnableWindowsTargeting> |
|
已按一次集中提交 已修复:
核实后未改动:
验证:
PR 正文也已补充模型、harness、实际工具、skills 使用情况和用户提示词摘要。 |
There was a problem hiding this comment.
0 issues found across 7 files (changes from recent commits).
Requires human review: Auto-approval blocked by 3 unresolved issues from previous reviews.
Re-trigger cubic
|
你是什么模型 |
5.6sol捏,思考深度是中 |
There was a problem hiding this comment.
Hey - 我发现了 1 个问题,并给出了一些整体性的反馈:
- 目前控制器方法中重复进行了
Export/LocalAction头部检查;可以考虑提取一个小的辅助函数或过滤器来集中处理这些校验,从而减少在各个 ResourceJunction 端点之间的重复代码。 ResourceJunctionController中的文件夹选择提示目前是硬编码的英文字符串;如果能通过现有的本地化系统来传递这些文案,可以与其他 UI 保持一致,避免出现混合语言的对话框。
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The controller methods currently repeat the `Export`/`LocalAction` header checks; consider extracting a small helper or filter to centralize this validation and reduce duplication across the ResourceJunction endpoints.
- Folder selection prompts in `ResourceJunctionController` are hard-coded English strings; wiring these through your existing localization system would keep them consistent with the rest of the UI and avoid mixed-language dialogs.
## Individual Comments
### Comment 1
<location path="MaiChartManager/Front/src/views/Tools/ResourceJunctionModal.tsx" line_range="22-31" />
<code_context>
+ const request = async (action: 'auto' | 'status' | 'manual' | 'manualTarget' | 'create' | 'remove') => {
</code_context>
<issue_to_address>
**suggestion:** Client-side error handling discards specific server error messages, which could be surfaced to improve UX.
The API returns BadRequest with a plain string for validation issues (e.g., invalid source/target), but Axios errors are always mapped to a generic `requestFailed` toast. Please read the response payload (e.g., `error.response?.data`) and include that message in the toast when available, so users see the specific validation error instead of a generic failure.
Suggested implementation:
```typescript
} catch (error) {
let detail: string | undefined;
// Try to surface server-side validation / error messages when available
if (axios.isAxiosError(error)) {
const payload = error.response?.data;
if (typeof payload === 'string') {
// API returns plain string for validation issues
detail = payload;
} else if (payload && typeof payload === 'object') {
// Fallback for common structured error shapes
const { message, error: errorMessage } = payload as { message?: string; error?: string };
detail = message ?? errorMessage;
}
}
toast.add({
severity: 'error',
summary: t('tools.resourceJunction.requestFailed'),
detail,
life: 5000,
});
} finally {
loading.value = false;
}
```
1. Ensure `axios` is imported at the top of this file, for example:
`import axios from 'axios';`
2. If your toast implementation uses a different property than `detail` for the message body, adjust the `toast.add` call to match the existing convention (e.g., `message` or `description`).
</issue_to_address>Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Original comment in English
Hey - I've found 1 issue, and left some high level feedback:
- The controller methods currently repeat the
Export/LocalActionheader checks; consider extracting a small helper or filter to centralize this validation and reduce duplication across the ResourceJunction endpoints. - Folder selection prompts in
ResourceJunctionControllerare hard-coded English strings; wiring these through your existing localization system would keep them consistent with the rest of the UI and avoid mixed-language dialogs.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The controller methods currently repeat the `Export`/`LocalAction` header checks; consider extracting a small helper or filter to centralize this validation and reduce duplication across the ResourceJunction endpoints.
- Folder selection prompts in `ResourceJunctionController` are hard-coded English strings; wiring these through your existing localization system would keep them consistent with the rest of the UI and avoid mixed-language dialogs.
## Individual Comments
### Comment 1
<location path="MaiChartManager/Front/src/views/Tools/ResourceJunctionModal.tsx" line_range="22-31" />
<code_context>
+ const request = async (action: 'auto' | 'status' | 'manual' | 'manualTarget' | 'create' | 'remove') => {
</code_context>
<issue_to_address>
**suggestion:** Client-side error handling discards specific server error messages, which could be surfaced to improve UX.
The API returns BadRequest with a plain string for validation issues (e.g., invalid source/target), but Axios errors are always mapped to a generic `requestFailed` toast. Please read the response payload (e.g., `error.response?.data`) and include that message in the toast when available, so users see the specific validation error instead of a generic failure.
Suggested implementation:
```typescript
} catch (error) {
let detail: string | undefined;
// Try to surface server-side validation / error messages when available
if (axios.isAxiosError(error)) {
const payload = error.response?.data;
if (typeof payload === 'string') {
// API returns plain string for validation issues
detail = payload;
} else if (payload && typeof payload === 'object') {
// Fallback for common structured error shapes
const { message, error: errorMessage } = payload as { message?: string; error?: string };
detail = message ?? errorMessage;
}
}
toast.add({
severity: 'error',
summary: t('tools.resourceJunction.requestFailed'),
detail,
life: 5000,
});
} finally {
loading.value = false;
}
```
1. Ensure `axios` is imported at the top of this file, for example:
`import axios from 'axios';`
2. If your toast implementation uses a different property than `detail` for the message body, adjust the `toast.add` call to match the existing convention (e.g., `message` or `description`).
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
Addressed the latest Sourcery review in
Validation:
|
There was a problem hiding this comment.
0 issues found across 6 files (changes from recent commits).
Requires human review: Auto-approval blocked by 3 unresolved issues from previous reviews.
Re-trigger cubic
功能说明
新增“游戏资源链接”工具,用 Windows Junction 在多个 maimai 游戏目录之间共享体积较大的资源文件。
AssetBundleImages、MovieData、SoundData安全边界
验证
dotnet test MaiChartManager.Tests/MaiChartManager.Tests.csproj -c Debug --no-restore:18 项通过pnpm build:通过dotnet build MaiChartManager/MaiChartManager.csproj -c LinuxDebugBackend:通过测试覆盖目录归一化、自动候选排名、并列处理、直接
Sinmai_Data布局、嵌套重解析点跳过、手动源/目标覆盖、固定范围不可变、源目标重合保护、现有目录冲突、错误 Junction 拒绝,以及包含空格与&的临时路径下真实 Junction 的建立、读取和移除。Summary by Sourcery
引入一个游戏资源链接管理工具,通过 Windows 目录联接(junction)在多个 maimai 游戏安装之间共享大型资源目录,并提供严格的安全检查以及按会话选择资源源目录/目标目录的功能。
New Features:
添加后端服务和 HTTP API,用于检查、自动选择和管理用于游戏资源目录的 Windows 目录联接。
暴露一个新的前端工具弹窗,用于查看资源链接状态、选择源/目标游戏目录以及创建或移除目录联接。
扩展客户端 API 类型和枚举,以表示资源联接总览、条目和状态,并将该工具集成到主工具面板中。
为新的游戏资源链接管理工具添加英语、简体中文和繁体中文的本地化 UI 字符串。
Documentation:
Tests:
Original summary in English
Summary by Sourcery
Introduce a game resource link management tool that shares large resource directories between maimai game installs via Windows junctions, with strict safety checks and per-session source/target selection.
New Features:
Enhancements:
Documentation:
Tests:
本 PR 使用 AI 辅助实现,供审核参考:
AssetBundleImages、MovieData、SoundData;目标默认使用当前游戏目录且可按会话单独选择;源目录打开工具时自动按三类资源文件总数选择,同时保留手动选择;切换目标不触发游戏数据重载;源目录只读,不覆盖普通目录或错误链接;补测试、文档,并提交官方 PR。未在正文复制系统提示词或仓库代理指令;实现过程遵循仓库
AGENTS.md。工具的作用为:在例如SDGA,SDGB游戏文件的A000目录下建立符号链接,指向SDEZ的AssetBundleImages,MovieData和SoundData,实现复用SDEZ的主要资源文件,减少磁盘空间占用,已在本地和多台电脑上验证可用。
第一次传pr,可能有不当的操作打扰到各位了,抱歉捏
Summary by Sourcery
引入一个游戏资源链接管理工具,通过 Windows 连接点在多个 maimai 游戏安装之间共享大型资源目录,并支持按会话选择来源/目标目录以及严格的安全检查。
New Features:
Documentation:
Tests:
Original summary in English
Summary by Sourcery
Introduce a game resource link management tool that shares large resource directories between maimai game installs via Windows junctions, with per-session source/target selection and strict safety checks.
New Features:
Documentation:
Tests: