修复主题切换持久化问题

- 新增 UiPreferencesService 服务用于管理UI配置
- 主题选择自动保存到 appsettings.local.json
- 刷新页面后自动恢复用户的主题偏好
- 无需额外的设置选项,点击切换按钮即可

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
meoacgxandClaude committed 2025-12-20 19:15:13 +08:00
1 parent 5b8187e12a
commit 449e4d1358
3 files changed
+103 -1

No files matched your search

@@ -26,6 +26,9 @@
</MudMainContent>
</MudLayout>
@using TelegramPanel.Web.Services
@inject UiPreferencesService UiPreferences
@code {
private bool _drawerOpen = true;
private bool _isDarkMode = true;
@@ -48,13 +51,21 @@
}
};
protected override async Task OnInitializedAsync()
{
// 从配置文件读取用户的主题偏好
_isDarkMode = await UiPreferences.GetIsDarkModeAsync();
}
private void ToggleDrawer()
{
_drawerOpen = !_drawerOpen;
}
private void ToggleDarkMode()
private async Task ToggleDarkMode()
{
_isDarkMode = !_isDarkMode;
// 保存主题偏好到配置文件
await UiPreferences.SetIsDarkModeAsync(_isDarkMode);
}
}
+1
View File
@@ -291,6 +291,7 @@ builder.Services.AddTelegramPanelData(connectionString);
builder.Services.AddTelegramPanelCore();
builder.Services.AddScoped<AccountExportService>();
builder.Services.AddScoped<DataSyncService>();
builder.Services.AddScoped<UiPreferencesService>();
builder.Services.AddHostedService<BatchTaskBackgroundService>();
builder.Services.AddHostedService<AccountDataAutoSyncBackgroundService>();
builder.Services.AddHostedService<BotAutoSyncBackgroundService>();
@@ -0,0 +1,90 @@
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.Hosting;
namespace TelegramPanel.Web.Services;
/// <summary>
/// UI 偏好设置服务,用于管理用户界面相关的配置(如主题模式)
/// </summary>
public class UiPreferencesService
{
private readonly IConfiguration _configuration;
private readonly IWebHostEnvironment _environment;
private readonly string _configFilePath;
private readonly SemaphoreSlim _writeLock = new(1, 1);
public UiPreferencesService(IConfiguration configuration, IWebHostEnvironment environment)
{
_configuration = configuration;
_environment = environment;
_configFilePath = LocalConfigFile.ResolvePath(configuration, environment);
}
/// <summary>
/// 获取当前的深色模式设置
/// </summary>
public async Task<bool> GetIsDarkModeAsync()
{
try
{
if (!File.Exists(_configFilePath))
return true; // 默认使用深色模式
var json = await File.ReadAllTextAsync(_configFilePath);
var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("UI", out var uiSection) &&
uiSection.TryGetProperty("IsDarkMode", out var isDarkModeValue))
{
return isDarkModeValue.GetBoolean();
}
return true; // 默认使用深色模式
}
catch
{
return true; // 出错时默认使用深色模式
}
}
/// <summary>
/// 设置深色模式
/// </summary>
public async Task SetIsDarkModeAsync(bool isDarkMode)
{
await _writeLock.WaitAsync();
try
{
// 确保配置文件存在
await LocalConfigFile.EnsureExistsAsync(_configFilePath);
// 读取现有配置
var json = await File.ReadAllTextAsync(_configFilePath);
var jsonObj = JsonNode.Parse(json)?.AsObject() ?? new JsonObject();
// 更新 UI 配置
if (!jsonObj.ContainsKey("UI"))
{
jsonObj["UI"] = new JsonObject();
}
var uiSection = jsonObj["UI"]!.AsObject();
uiSection["IsDarkMode"] = isDarkMode;
// 写入配置文件
var options = new JsonSerializerOptions
{
WriteIndented = true,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
var updatedJson = JsonSerializer.Serialize(jsonObj, options);
await LocalConfigFile.WriteJsonAtomicallyAsync(_configFilePath, updatedJson);
}
finally
{
_writeLock.Release();
}
}
}