增强应用程序异常处理机制,新增未处理异常日志记录功能,确保在启动和运行期间捕获并记录异常信息。同时,重构配置文件加载逻辑,支持用户目录覆盖默认配置,优化 SQLite 数据库连接字符串处理,确保在不同环境下的兼容性和稳定性。

This commit is contained in:
geht
2026-05-15 17:30:30 +08:00
parent cea4781397
commit 1b280af9e2
23 changed files with 584 additions and 68 deletions

View File

@@ -1,6 +1,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using YY.Admin.Core.Util;
namespace YY.Admin.Helper
{
@@ -11,6 +12,37 @@ namespace YY.Admin.Helper
{
private const string DefaultWebSocketPath = "/websocket/scada-sync";
/// <summary>
/// 安装目录随包发布的默认配置(只读)。
/// </summary>
public static string GetBundledAppSettingsPath()
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configuration", "appsettings.json");
}
/// <summary>
/// 用户覆盖配置(可写),仅覆盖 JeecgIntegration 节点时使用。
/// </summary>
public static string GetUserAppSettingsPath()
{
var dir = AppWritablePaths.EnsureDirectoryExists(AppWritablePaths.ConfigurationDirectory);
return Path.Combine(dir, "appsettings.json");
}
/// <summary>
/// 兼容旧调用:优先返回用于读取的实际路径(存在用户覆盖则用用户文件)。
/// </summary>
public static string GetConfigPath()
{
var user = GetUserAppSettingsPath();
if (File.Exists(user))
{
return user;
}
return GetBundledAppSettingsPath();
}
public class ServerSettingsModel
{
public string Ip { get; set; } = "127.0.0.1";
@@ -25,22 +57,35 @@ namespace YY.Admin.Helper
public bool DisconnectConnection { get; set; } = false;
}
public static string GetConfigPath()
private static JObject LoadMergedRoot()
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configuration", "appsettings.json");
var bundledPath = GetBundledAppSettingsPath();
if (!File.Exists(bundledPath))
{
throw new FileNotFoundException("未找到安装目录默认配置文件 appsettings.json", bundledPath);
}
var root = JObject.Parse(File.ReadAllText(bundledPath));
var userPath = GetUserAppSettingsPath();
if (!File.Exists(userPath))
{
return root;
}
var userRoot = JObject.Parse(File.ReadAllText(userPath));
var userJeecg = userRoot["JeecgIntegration"] as JObject;
if (userJeecg != null)
{
root["JeecgIntegration"] = userJeecg;
}
return root;
}
public static ServerSettingsModel Load()
{
var model = new ServerSettingsModel();
var path = GetConfigPath();
if (!File.Exists(path))
{
return model;
}
var content = File.ReadAllText(path);
var root = JObject.Parse(content);
var root = LoadMergedRoot();
var jeecg = root["JeecgIntegration"] as JObject;
if (jeecg == null)
{
@@ -64,14 +109,7 @@ namespace YY.Admin.Helper
public static void Save(ServerSettingsModel model)
{
var path = GetConfigPath();
if (!File.Exists(path))
{
throw new FileNotFoundException("未找到配置文件 appsettings.json", path);
}
var content = File.ReadAllText(path);
var root = JObject.Parse(content);
var root = LoadMergedRoot();
var jeecg = root["JeecgIntegration"] as JObject;
if (jeecg == null)
{
@@ -95,7 +133,9 @@ namespace YY.Admin.Helper
jeecg["WebSocketPath"] = webSocketPath;
jeecg["DisconnectConnection"] = model.DisconnectConnection;
File.WriteAllText(path, root.ToString(Formatting.Indented));
var userPath = GetUserAppSettingsPath();
var outRoot = new JObject { ["JeecgIntegration"] = jeecg };
File.WriteAllText(userPath, outRoot.ToString(Formatting.Indented));
}
public static string BuildDefaultWebSocketUrl(string baseScheme, string ip, int port, string basePath, string webSocketPath = DefaultWebSocketPath)
@@ -106,6 +146,7 @@ namespace YY.Admin.Helper
{
safeBasePath = "/" + safeBasePath;
}
var safeWsPath = NormalizeWebSocketPath(webSocketPath);
return $"{safeScheme}://{ip}:{port}{safeBasePath}{safeWsPath}";
}
@@ -117,6 +158,7 @@ namespace YY.Admin.Helper
{
value = "/" + value;
}
return value;
}
}

View File

@@ -0,0 +1,23 @@
using System.IO;
using Microsoft.Web.WebView2.Wpf;
using YY.Admin.Core.Util;
namespace YY.Admin.Helper;
/// <summary>
/// WebView2 默认将用户数据目录放在宿主 exe 旁边;安装在 Program Files 时目录只读会导致初始化失败、预览白屏。
/// 统一到当前用户 LocalAppData 下的可写路径。
/// </summary>
public static class WebView2UserDataFolder
{
/// <summary>
/// 为控件创建 CreationProperties须在首次 EnsureCoreWebView2Async 之前赋值)。
/// </summary>
/// <param name="subFolder">子目录名,避免不同场景争用同一 profile。</param>
public static CoreWebView2CreationProperties CreateCreationProperties(string subFolder)
{
var folder = AppWritablePaths.EnsureDirectoryExists(
Path.Combine(AppWritablePaths.LocalApplicationRoot, "WebView2", subFolder));
return new CoreWebView2CreationProperties { UserDataFolder = folder };
}
}