添加项目文件。

This commit is contained in:
2026-04-25 00:29:16 +08:00
parent 1850fdc75d
commit 2c56c7f04d
2177 changed files with 97211 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
using AcdiuTools.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace AcdiuTools.Controllers
{
/// <summary>
/// 基础控制器
/// 所有需要主题功能的控制器应继承此类
/// </summary>
public class BaseController(IThemeService themeService) : Controller
{
private readonly IThemeService _themeService = themeService;
/// <summary>
/// 在执行 Action 之前加载主题配置并注入 ViewBag
/// </summary>
public override async void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
// 异步操作在 OnActionExecuting 中处理需小心,通常建议在 Action 内部或中间件中处理
// 这里为了演示简单,使用同步等待或改为中间件方案更佳
// 更好的方式:使用 ViewComponent 或 TagHelper
var theme = await _themeService.GetUserThemeAsync();
ViewBag.CurrentTheme = theme;
}
}
}

View File

@@ -0,0 +1,84 @@
using AcdiuTools.Models;
using AcdiuTools.Services;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Security.Claims;
namespace AcdiuTools.Controllers
{
public class HomeController(IThemeService themeService) : BaseController(themeService)
{
private readonly IThemeService _themeService = themeService;
[Route("")]
public IActionResult Index()
{
return View();
}
[Route("privacy")]
public IActionResult Privacy()
{
return View();
}
[Route("err")]
[Route("error")]
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
/// <summary>
/// API 端点:用于前端 AJAX 调用以切换主题
/// </summary>
[HttpPost]
public async Task<IActionResult> SetTheme([FromBody] ThemeRequest model)
{
// 获取用户 ID
string? claimUserId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
?? User.FindFirst("sub")?.Value;
string userId;
if (!string.IsNullOrEmpty(claimUserId))
{
// 已登录用户
userId = claimUserId;
}
else
{
// 匿名用户:尝试使用 Session ID
// 注意:访问 HttpContext.Session 会触发 Session 创建/加载
try
{
userId = HttpContext.Session.Id;
}
catch (InvalidOperationException)
{
// 如果 Session 未配置(防御性编程),回退到匿名标识
userId = "anonymous_" + HttpContext.Connection.RemoteIpAddress?.ToString()?.Replace(".", "_") ?? "unknown";
}
}
await _themeService.SaveUserThemeAsync(userId, model.Theme);
return Json(new { success = true, theme = model.Theme });
}
}
/// <summary>
/// 主题请求模型
/// </summary>
public class ThemeRequest
{
/// <summary>
/// 主题名称
/// 修复 CS8618: 使用 required 修饰符,确保反序列化时必须存在该字段
/// </summary>
[Required]
public required string Theme { get; set; }
}
}