From 752f09a7e401c0142f1238680f8610ca2d102161 Mon Sep 17 00:00:00 2001 From: home-PC Date: Sat, 9 May 2026 20:34:36 +0800 Subject: [PATCH] Phase 1: data models and local storage service - Add Models: Category, ToolItem (IsValid runtime-only, not stored), AppConfig - Add Services: IDataService + JsonDataService (JSON load/save) - Path validation on Load(): File.Exists check, logs warning for missing paths - Startup: auto-calls dataService.Load() to load config --- PersonalToolBox/App.xaml.cs | 7 ++ PersonalToolBox/Models/AppConfig.cs | 27 ++++++ PersonalToolBox/Models/Category.cs | 17 ++++ PersonalToolBox/Models/ToolItem.cs | 50 +++++++++++ PersonalToolBox/Services/IDataService.cs | 24 +++++ PersonalToolBox/Services/JsonDataService.cs | 97 +++++++++++++++++++++ 6 files changed, 222 insertions(+) create mode 100644 PersonalToolBox/Models/AppConfig.cs create mode 100644 PersonalToolBox/Models/Category.cs create mode 100644 PersonalToolBox/Models/ToolItem.cs create mode 100644 PersonalToolBox/Services/IDataService.cs create mode 100644 PersonalToolBox/Services/JsonDataService.cs diff --git a/PersonalToolBox/App.xaml.cs b/PersonalToolBox/App.xaml.cs index c958f89..0236c89 100644 --- a/PersonalToolBox/App.xaml.cs +++ b/PersonalToolBox/App.xaml.cs @@ -20,6 +20,10 @@ public partial class App : Application ConfigureServices(services); Services = services.BuildServiceProvider(); + // 启动时加载配置文件(含路径验证与容错) + var dataService = Services.GetRequiredService(); + dataService.Load(); + var mainWindow = Services.GetRequiredService(); mainWindow.Show(); } @@ -32,6 +36,9 @@ public partial class App : Application // 日志服务 services.AddSingleton(); + // 数据持久化服务 + services.AddSingleton(); + // 主窗口 services.AddSingleton(); } diff --git a/PersonalToolBox/Models/AppConfig.cs b/PersonalToolBox/Models/AppConfig.cs new file mode 100644 index 0000000..e9d4a1a --- /dev/null +++ b/PersonalToolBox/Models/AppConfig.cs @@ -0,0 +1,27 @@ +namespace PersonalToolBox.Models; + +/// +/// 应用全局配置,对应 config.json 的顶层结构 +/// +public class AppConfig +{ + /// + /// 主题模式 (Dark / Light) + /// + public string Theme { get; set; } = "Dark"; + + /// + /// 是否开机自启动 + /// + public bool AutoStart { get; set; } = false; + + /// + /// 工具分类列表 + /// + public List Categories { get; set; } = new(); + + /// + /// 工具项列表 + /// + public List Tools { get; set; } = new(); +} diff --git a/PersonalToolBox/Models/Category.cs b/PersonalToolBox/Models/Category.cs new file mode 100644 index 0000000..56d5a34 --- /dev/null +++ b/PersonalToolBox/Models/Category.cs @@ -0,0 +1,17 @@ +namespace PersonalToolBox.Models; + +/// +/// 工具标签页分类 +/// +public class Category +{ + /// + /// 分类唯一标识 + /// + public string Id { get; set; } = Guid.NewGuid().ToString(); + + /// + /// 分类显示名称(如:开发工具、常用脚本) + /// + public string Name { get; set; } = string.Empty; +} diff --git a/PersonalToolBox/Models/ToolItem.cs b/PersonalToolBox/Models/ToolItem.cs new file mode 100644 index 0000000..01c8603 --- /dev/null +++ b/PersonalToolBox/Models/ToolItem.cs @@ -0,0 +1,50 @@ +using System.Text.Json.Serialization; + +namespace PersonalToolBox.Models; + +/// +/// 工具项模型,表示用户添加的一个可执行工具 +/// +public class ToolItem +{ + /// + /// 工具唯一标识 (UUID) + /// + public string Id { get; set; } = Guid.NewGuid().ToString(); + + /// + /// 工具显示名称 + /// + public string Name { get; set; } = string.Empty; + + /// + /// 内置图标库的字符编码 + /// + public string IconCode { get; set; } = string.Empty; + + /// + /// 可执行文件路径或 URL + /// + public string ExecutablePath { get; set; } = string.Empty; + + /// + /// 运行参数(选填) + /// + public string Arguments { get; set; } = string.Empty; + + /// + /// 所属分类 ID + /// + public string CategoryId { get; set; } = string.Empty; + + /// + /// 全局快捷键(如 Ctrl+Alt+T),选填 + /// + public string HotKey { get; set; } = string.Empty; + + /// + /// 路径是否有效(仅运行时计算,不存入 JSON) + /// + [JsonIgnore] + public bool IsValid { get; set; } = true; +} diff --git a/PersonalToolBox/Services/IDataService.cs b/PersonalToolBox/Services/IDataService.cs new file mode 100644 index 0000000..fd44d95 --- /dev/null +++ b/PersonalToolBox/Services/IDataService.cs @@ -0,0 +1,24 @@ +using PersonalToolBox.Models; + +namespace PersonalToolBox.Services; + +/// +/// 数据持久化服务接口,负责配置的加载和保存 +/// +public interface IDataService +{ + /// + /// 当前加载的配置数据 + /// + AppConfig Config { get; } + + /// + /// 从 config.json 加载配置,验证工具路径有效性 + /// + void Load(); + + /// + /// 保存当前配置到 config.json + /// + void Save(); +} diff --git a/PersonalToolBox/Services/JsonDataService.cs b/PersonalToolBox/Services/JsonDataService.cs new file mode 100644 index 0000000..a924772 --- /dev/null +++ b/PersonalToolBox/Services/JsonDataService.cs @@ -0,0 +1,97 @@ +using System.IO; +using System.Text.Json; +using PersonalToolBox.Models; + +namespace PersonalToolBox.Services; + +/// +/// 基于 JSON 文件的数据持久化服务 +/// 配置文件路径: 可执行程序目录/config.json +/// +public class JsonDataService : IDataService +{ + private readonly ILogService _logService; + private readonly string _filePath; + + private static readonly JsonSerializerOptions JsonOptions = new() + { + WriteIndented = true, + PropertyNameCaseInsensitive = true + }; + + public AppConfig Config { get; private set; } = new(); + + public JsonDataService(ILogService logService) + { + _logService = logService; + _filePath = Path.Combine(AppContext.BaseDirectory, "config.json"); + } + + public void Load() + { + if (!File.Exists(_filePath)) + { + _logService.Info("配置文件不存在,使用默认配置"); + Config = new AppConfig(); + Save(); + return; + } + + try + { + var json = File.ReadAllText(_filePath); + var config = JsonSerializer.Deserialize(json, JsonOptions); + + if (config == null) + { + _logService.Warning("配置文件解析结果为空,使用默认配置"); + Config = new AppConfig(); + return; + } + + Config = config; + + // 核心容错逻辑:验证所有工具路径是否有效 + foreach (var tool in Config.Tools) + { + if (string.IsNullOrWhiteSpace(tool.ExecutablePath)) + continue; + + // URL 格式的路径(如 https://...)不需要检查本地文件是否存在 + if (Uri.TryCreate(tool.ExecutablePath, UriKind.Absolute, out var uri) && + (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)) + { + tool.IsValid = true; + continue; + } + + if (!File.Exists(tool.ExecutablePath)) + { + tool.IsValid = false; + _logService.Warning($"工具 \"{tool.Name}\" 路径失效,找不到文件: {tool.ExecutablePath}"); + } + } + + _logService.Info($"配置加载完成: {Config.Categories.Count} 个分类, {Config.Tools.Count} 个工具"); + } + catch (JsonException ex) + { + _logService.Error($"配置文件 JSON 解析失败: {ex.Message}"); + Config = new AppConfig(); + } + } + + public void Save() + { + try + { + var json = JsonSerializer.Serialize(Config, JsonOptions); + File.WriteAllText(_filePath, json); + _logService.Info("配置已保存"); + } + catch (Exception ex) + { + _logService.Error($"配置保存失败: {ex.Message}"); + } + } +}