添加持久化保存和日志

This commit is contained in:
limil 2025-12-20 22:29:24 +08:00
parent c3d826991c
commit 89de0e2ebd
7 changed files with 2086 additions and 23 deletions

View File

@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.IO;
using Godot;
using Learn.Models;
using Newtonsoft.Json;
namespace Learn.Component;
@ -9,8 +10,9 @@ namespace Learn.Component;
public partial class MainTreePanel : Tree
{
private readonly HashSet<string> _columns = new();
private readonly HashSet<TreeNode> _selectingNodes = new ();
private readonly HashSet<TreeNode> _selectingNodes = new();
private readonly Dictionary<TreeItem, TreeNode> _mapper = new();
private readonly Dictionary<string, Item> _items = new();
public HashSet<TreeNode> SelectingNodes => _selectingNodes;
@ -80,21 +82,57 @@ public partial class MainTreePanel : Tree
private TreeItem CreateNode(TreeItem father, Item item)
{
var node = CreateItem(father);
node.SetText(0, item.Info["Name"]);
var name = Path.GetFileName(item.MainInfo["Path"]);
node.SetText(0, name);
return node;
}
private Item InitItem(string path, bool isDir)
{
var name = Path.GetFileName(path);
var item = new Item();
item.Info["Name"] = name;
item.Info["IsDir"] = isDir ? "True" : "False";
item.Info["Path"] = path;
if (_items.TryGetValue(path, out var item))
{
return item;
}
item = new Item
{
MainInfo =
{
["IsDir"] = isDir ? "True" : "False",
["Path"] = path
}
};
_items.Add(path, item);
return item;
}
public void Build(string path)
public void ClearData()
{
foreach (var item in _items.Values)
{
item.Info.Clear();
}
UpdateColumns();
}
public void LoadData(string dataPath)
{
var items = JsonConvert.DeserializeObject<Dictionary<string, Item>>(File.ReadAllText(dataPath));
foreach (var kv in items)
{
if (string.IsNullOrEmpty(kv.Key)) continue;
_items[kv.Key] = kv.Value;
}
UpdateColumns();
}
public void SaveData(string dataPath)
{
File.WriteAllText(dataPath, JsonConvert.SerializeObject(_items, Formatting.Indented));
}
public void Scan(string path)
{
Clear();
_mapper.Clear();

View File

@ -78,7 +78,7 @@ public partial class NodeInfoEditPanel : Tree
OnNodesChanged();
}
private void OnNodesChanged()
public void OnNodesChanged()
{
Clear();
_nodeKeys.Clear();
@ -96,6 +96,7 @@ public partial class NodeInfoEditPanel : Tree
node.SetEditable(ValueColumn, true);
_nodeKeys.Add(node, key);
}
OnNodeInfoEdited?.Invoke();
}
public void AddKeyValue()

View File

@ -4,4 +4,7 @@
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net9.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>
</Project>

48
Main.cs
View File

@ -1,3 +1,4 @@
using System.IO;
using Godot;
using System.Linq;
using Learn.Component;
@ -5,9 +6,12 @@ using Learn.Component;
public partial class Main : Node
{
[ExportGroup("文件夹操作")][Export] private FileDirSelector _dirSelector;
[ExportGroup("操作面板")][Export] private RichTextLabel _console;
[ExportGroup("操作面板")][Export] private Button _openDirButton;
[ExportGroup("操作面板")][Export] private Button _doParseButton;
[ExportGroup("操作面板")][Export] private Button _saveButton;
[ExportGroup("操作面板")][Export] private Button _resetButton;
[ExportGroup("编辑面板")][Export] private NodeInfoEditPanel _nodeInfoEditPanel;
[ExportGroup("编辑面板")][Export] private Button _addKeyButton;
@ -21,6 +25,18 @@ public partial class Main : Node
[ExportGroup("主展示面板")][Export] private Button _removeColumnButton;
private bool _refreshPanels;
private void Log(string log)
{
var time = Time.GetTimeDictFromSystem();
string timestamp = $"[{time["hour"]:D2}:{time["minute"]:D2}:{time["second"]:D2}]";
string bbcode = $"[color=#888888]{timestamp}[/color] " +
$"{log}\n";
_console.AppendText(bbcode);
_console.ScrollToLine(_console.GetLineCount());
}
public override void _Ready()
{
@ -33,8 +49,17 @@ public partial class Main : Node
_removeColumnButton.Pressed += () => _mainTreePanel.RemoveColumn(_columnText.Text);
// 功能区
_openDirButton.Pressed += OpenDir;
_openDirButton.Pressed += ScanDir;
_doParseButton.Pressed += DoParse;
_saveButton.Pressed += DoSave;
_resetButton.Pressed += DoReset;
// 先加载保存的数据
if (File.Exists(DataPath))
{
_mainTreePanel.LoadData(DataPath);
Log("加载成功:" + DataPath);
}
}
@ -49,14 +74,14 @@ public partial class Main : Node
}
#region Commands
private async void OpenDir()
private async void ScanDir()
{
var path = await _dirSelector.SelectFolderAsync();
if (string.IsNullOrEmpty(path))
{
return;
}
_mainTreePanel.Build(path);
_mainTreePanel.Scan(path);
_refreshPanels = true;
}
@ -64,6 +89,21 @@ public partial class Main : Node
{
// todo;
}
private const string DataPath = "data.json";
private void DoSave()
{
_mainTreePanel.SaveData(DataPath);
Log("保存成功");
}
private void DoReset()
{
_mainTreePanel.ClearData();
_nodeInfoEditPanel.OnNodesChanged();
Log("清空成功");
}
#endregion
}

View File

@ -17,11 +17,14 @@ grow_vertical = 2
[node name="FileDirDialog" type="FileDialog" parent="."]
script = ExtResource("1_d2g23")
[node name="Main" type="Node" parent="." node_paths=PackedStringArray("_dirSelector", "_openDirButton", "_doParseButton", "_nodeInfoEditPanel", "_addKeyButton", "_removeKeyButton", "_parsedInfoPanel", "_mainTreePanel", "_columnText", "_addColumnButton", "_removeColumnButton")]
[node name="Main" type="Node" parent="." node_paths=PackedStringArray("_dirSelector", "_console", "_openDirButton", "_doParseButton", "_saveButton", "_resetButton", "_nodeInfoEditPanel", "_addKeyButton", "_removeKeyButton", "_parsedInfoPanel", "_mainTreePanel", "_columnText", "_addColumnButton", "_removeColumnButton")]
script = ExtResource("2_0727o")
_dirSelector = NodePath("../FileDirDialog")
_openDirButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/HFlowContainer/OpenDir")
_doParseButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/HFlowContainer/DoParse")
_console = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer/RichTextLabel")
_openDirButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer/HFlowContainer/ScanDir")
_doParseButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer/HFlowContainer/DoParse")
_saveButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer/HFlowContainer/Save")
_resetButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer/HFlowContainer/Reset")
_nodeInfoEditPanel = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/NodeEditPanel")
_addKeyButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer/AddKey")
_removeKeyButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer/RemoveKey")
@ -64,23 +67,37 @@ size_flags_horizontal = 3
[node name="FoldableContainer4" type="FoldableContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2"]
layout_mode = 2
folded = true
title = "功能操作"
[node name="HFlowContainer" type="HFlowContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4"]
visible = false
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4"]
layout_mode = 2
[node name="OpenDir" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/HFlowContainer"]
[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer"]
custom_minimum_size = Vector2(0, 200)
layout_mode = 2
bbcode_enabled = true
[node name="HFlowContainer" type="HFlowContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer"]
layout_mode = 2
[node name="ScanDir" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer/HFlowContainer"]
layout_mode = 2
size_flags_vertical = 4
text = "打开文件夹"
text = "扫描文件夹"
[node name="DoParse" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/HFlowContainer"]
[node name="DoParse" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer/HFlowContainer"]
layout_mode = 2
size_flags_vertical = 4
text = "开始解析"
[node name="Save" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer/HFlowContainer"]
layout_mode = 2
text = "保存"
[node name="Reset" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer/HFlowContainer"]
layout_mode = 2
text = "重置"
[node name="FoldableContainer3" type="FoldableContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2"]
layout_mode = 2
folded = true

View File

@ -4,5 +4,7 @@ namespace Learn.Models;
public class Item
{
public Dictionary<string, string> Info { get; } = new ();
public Dictionary<string, string> MainInfo { get; set; } = new();
public Dictionary<string, string> Info { get; set; } = new();
}

1962
data.json Normal file

File diff suppressed because it is too large Load Diff