添加项目文件。
This commit is contained in:
84
TagHelpers/ActiveLinkTagHelper.cs
Normal file
84
TagHelpers/ActiveLinkTagHelper.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using System;
|
||||
|
||||
namespace AcdiuTools.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// 自动为当前激活的导航链接添加 'active' 类和 'aria-current="page"' 属性。
|
||||
/// <para>
|
||||
/// 用法示例:
|
||||
/// <a asp-active-link="true" asp-controller="Home" asp-action="Index" class="nav-link">首页</a>
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[HtmlTargetElement("a", Attributes = "asp-active-link")]
|
||||
public class ActiveLinkTagHelper : TagHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置当前视图的上下文,用于读取路由数据。
|
||||
/// </summary>
|
||||
[ViewContext]
|
||||
[HtmlAttributeNotBound]
|
||||
public ViewContext ViewContext { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用自动激活检测。对应 HTML 属性: asp-active-link
|
||||
/// </summary>
|
||||
[HtmlAttributeName("asp-active-link")]
|
||||
public bool IsActiveLink { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标控制器名称。映射自内置的 asp-controller 属性。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("asp-controller")]
|
||||
public string? Controller { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标 Action 名称。映射自内置的 asp-action 属性。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("asp-action")]
|
||||
public string? Action { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行 TagHelper 逻辑。
|
||||
/// </summary>
|
||||
/// <param name="context">TagHelper 上下文。</param>
|
||||
/// <param name="output">TagHelper 输出内容。</param>
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
// 如果未设置 asp-active-link="true",则不执行逻辑
|
||||
if (!IsActiveLink) return;
|
||||
|
||||
// 1. 获取当前路由中的 Controller 和 Action
|
||||
var routeData = ViewContext.RouteData.Values;
|
||||
string? currentController = routeData["controller"]?.ToString();
|
||||
string? currentAction = routeData["action"]?.ToString();
|
||||
|
||||
// 2. 确定目标 Controller 和 Action (如果未指定,则默认为当前页面或 Index)
|
||||
string targetController = Controller ?? currentController ?? string.Empty;
|
||||
string targetAction = Action ?? "Index";
|
||||
|
||||
// 3. 忽略大小写进行匹配
|
||||
bool isActive = string.Equals(currentController, targetController, StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(currentAction, targetAction, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (isActive)
|
||||
{
|
||||
// 4. 合并 Class 属性,确保不覆盖原有样式
|
||||
var existingClasses = output.Attributes["class"]?.Value?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(existingClasses))
|
||||
{
|
||||
output.Attributes.SetAttribute("class", "active");
|
||||
}
|
||||
else if (!existingClasses.Contains("active"))
|
||||
{
|
||||
output.Attributes.SetAttribute("class", $"{existingClasses} active");
|
||||
}
|
||||
|
||||
// 5. 增强无障碍支持
|
||||
output.Attributes.SetAttribute("aria-current", "page");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
46
TagHelpers/ThemeToggleTagHelper.cs
Normal file
46
TagHelpers/ThemeToggleTagHelper.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using AcdiuTools.Services;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AcdiuTools.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// 主题切换按钮 Tag Helper
|
||||
/// 用法: <theme-toggle />
|
||||
/// </summary>
|
||||
[HtmlTargetElement("theme-toggle")]
|
||||
public class ThemeToggleTagHelper(IThemeService themeService) : TagHelper
|
||||
{
|
||||
private readonly IThemeService _themeService = themeService;
|
||||
|
||||
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
// 获取当前主题
|
||||
var currentTheme = await _themeService.GetUserThemeAsync();
|
||||
bool isDark = currentTheme == "dark";
|
||||
|
||||
// 设置标签名为 button
|
||||
output.TagName = "button";
|
||||
output.TagMode = TagMode.StartTagAndEndTag;
|
||||
|
||||
// 添加基础 CSS 类 (Bootstrap)
|
||||
output.Attributes.Add("class", "btn btn-outline-secondary border-0");
|
||||
output.Attributes.Add("id", "theme-toggle-btn");
|
||||
output.Attributes.Add("type", "button");
|
||||
output.Attributes.Add("aria-label", "Toggle Theme");
|
||||
|
||||
// 添加 Tooltip (Bootstrap data-bs-toggle)
|
||||
output.Attributes.Add("data-bs-toggle", "tooltip");
|
||||
output.Attributes.Add("data-bs-placement", "bottom");
|
||||
output.Attributes.Add("title", isDark ? "切换到浅色模式" : "切换到深色模式");
|
||||
|
||||
// 根据当前主题设置图标内容
|
||||
// 使用 Bootstrap Icons 或 FontAwesome
|
||||
string iconHtml = isDark
|
||||
? "<i class=\"bi bi-sun-fill\"></i>" // 深色模式下显示太阳图标(暗示切换到亮)
|
||||
: "<i class=\"bi bi-moon-stars-fill\"></i>"; // 浅色模式下显示月亮图标
|
||||
|
||||
output.Content.SetHtmlContent(iconHtml);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user