diff --git a/Assets/Editor/DeveloperMode/DeveloperModeTestSavePanelBuilder.cs b/Assets/Editor/DeveloperMode/DeveloperModeTestSavePanelBuilder.cs
new file mode 100644
index 000000000..8db0a8f31
--- /dev/null
+++ b/Assets/Editor/DeveloperMode/DeveloperModeTestSavePanelBuilder.cs
@@ -0,0 +1,460 @@
+#if UNITY_EDITOR
+using System;
+using System.Linq;
+using AibisDream.UI;
+using TMPro;
+using UnityEditor;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace AibisDream.DeveloperMode.Editor
+{
+ /// 只重建 DeveloperModePanel 的测试存档页,避免覆盖其他页的人工调整。
+ public static class DeveloperModeTestSavePanelBuilder
+ {
+ private const string PrefabPath =
+ "Assets/GameContent/Feature_MainUI/Prefabs/DeveloperModePanel.prefab";
+ private const string FontAssetPath =
+ "Assets/Font/Assets/WenQuanYi Bitmap Song 14px SDF.asset";
+
+ private static readonly Color Surface = new(0.055f, 0.085f, 0.11f, 0.96f);
+ private static readonly Color Accent = new(0.16f, 0.75f, 0.88f, 1f);
+ private static readonly Color TextColor = new(0.88f, 0.96f, 1f, 1f);
+
+ [MenuItem("Tools/AIBIS/Developer Mode/Rebuild Test Save Page")]
+ public static void BuildFromMenu()
+ {
+ Build();
+ Selection.activeObject = AssetDatabase.LoadAssetAtPath(PrefabPath);
+ }
+
+ public static void BuildFromCommandLine()
+ {
+ try
+ {
+ Build();
+ Debug.Log("[DeveloperModeTestSavePanelBuilder] Build completed.");
+ }
+ catch (Exception ex)
+ {
+ Debug.LogException(ex);
+ EditorApplication.Exit(1);
+ }
+ }
+
+ private static void Build()
+ {
+ var root = PrefabUtility.LoadPrefabContents(PrefabPath);
+ try
+ {
+ var panel = root.GetComponent()
+ ?? throw new InvalidOperationException("DeveloperModePanel component not found.");
+ var serialized = new SerializedObject(panel);
+ var pages = serialized.FindProperty("tabPages")
+ ?? throw new MissingFieldException(nameof(DeveloperModePanel), "tabPages");
+ if (pages.arraySize < 4)
+ {
+ throw new InvalidOperationException("DeveloperModePanel requires five tab pages.");
+ }
+
+ var savePage = pages.GetArrayElementAtIndex(3).objectReferenceValue as GameObject
+ ?? throw new InvalidOperationException("Save page reference is missing.");
+ ClearChildren(savePage.transform);
+ ConfigurePageLayout(savePage);
+ BuildSavePage(savePage.transform, serialized);
+ RenameSaveTab(serialized);
+
+ var font = AssetDatabase.LoadAssetAtPath(FontAssetPath)
+ ?? throw new InvalidOperationException($"Font not found: {FontAssetPath}");
+ foreach (var text in root.GetComponentsInChildren(true))
+ {
+ text.font = font;
+ }
+
+ serialized.ApplyModifiedPropertiesWithoutUndo();
+ PrefabUtility.SaveAsPrefabAsset(root, PrefabPath);
+ }
+ finally
+ {
+ PrefabUtility.UnloadPrefabContents(root);
+ }
+
+ AssetDatabase.SaveAssets();
+ }
+
+ private static void BuildSavePage(Transform page, SerializedObject serialized)
+ {
+ var recording = CreateHorizontal("Recording Toolbar", page, 6f);
+ AddLayout(recording, 38f);
+ var recordingToggle = CreateToggle("Record Test Saves", recording.transform, "录制测试存档", 145f);
+ var recordingState = CreateText("Recording State", recording.transform, "○ OFF", 14f, FontStyles.Bold);
+ AddLayout(recordingState.gameObject, 34f);
+ recordingState.rectTransform.sizeDelta = new Vector2(105f, 0f);
+ var search = CreateInput("Test Save Search", recording.transform, "搜索章节、节点或场景...", 250f);
+ var reload = CreateButton("Reload Test Saves", recording.transform, "重新扫描", 92f, 34f);
+ var open = CreateButton("Open Test Saves", recording.transform, "打开目录", 92f, 34f);
+
+ var columns = CreateHorizontal("Library Columns", page, 7f);
+ var columnsLayout = columns.AddComponent();
+ columnsLayout.flexibleHeight = 1f;
+ columnsLayout.minHeight = 420f;
+
+ var chapters = CreateVertical("Chapter Column", columns.transform, 4f);
+ var chapterLayout = chapters.AddComponent();
+ chapterLayout.preferredWidth = 245f;
+ chapterLayout.flexibleWidth = 0f;
+ chapterLayout.flexibleHeight = 1f;
+ var chapterTitle = CreateText("Title", chapters.transform, "章节 / 覆盖率", 16f, FontStyles.Bold);
+ AddLayout(chapterTitle.gameObject, 28f);
+ CreateList(
+ "Chapter List",
+ chapters.transform,
+ out var chapterContent,
+ out var chapterTemplate);
+
+ var entries = CreateVertical("Entry Column", columns.transform, 4f);
+ var entryLayout = entries.AddComponent();
+ entryLayout.flexibleWidth = 1f;
+ entryLayout.flexibleHeight = 1f;
+ var entryTitle = CreateText(
+ "Title",
+ entries.transform,
+ "存档点(● 已录制 / ○ 缺失 / ✕ 无效)",
+ 16f,
+ FontStyles.Bold);
+ AddLayout(entryTitle.gameObject, 28f);
+ CreateList(
+ "Entry List",
+ entries.transform,
+ out var entryContent,
+ out var entryTemplate);
+
+ var actions = CreateHorizontal("Actions", page, 6f);
+ AddLayout(actions, 36f);
+ var jump = CreateButton("Jump", actions.transform, "跳转到选中", 118f, 32f);
+ var deleteSelected = CreateButton("Delete Selected", actions.transform, "删除选中", 105f, 32f);
+ var deleteInvalid = CreateButton("Delete Invalid", actions.transform, "清理无效", 105f, 32f);
+ var clear = CreateButton("Clear Library", actions.transform, "清空存档库", 118f, 32f);
+
+ var status = CreateText(
+ "Save Status",
+ page,
+ "测试存档录制默认关闭;开启后仅复制正式节点自动档。",
+ 14f);
+ AddLayout(status.gameObject, 46f);
+ status.color = new Color(0.45f, 1f, 0.65f);
+ status.alignment = TextAlignmentOptions.TopLeft;
+
+ Set(serialized, "testSaveRecordingToggle", recordingToggle);
+ Set(serialized, "testSaveRecordingStateText", recordingState);
+ Set(serialized, "testSaveSearchInput", search);
+ Set(serialized, "reloadSavesButton", reload.GetComponent