添加项目文件。
This commit is contained in:
21
Acdiu.AspNetCore.Mvc.Commons.csproj
Normal file
21
Acdiu.AspNetCore.Mvc.Commons.csproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="favicon.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="2.3.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Runtime" Version="2.3.0" />
|
||||
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.7" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
38
Constants/UIConstants.cs
Normal file
38
Constants/UIConstants.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Acdiu.AspNetCore.Mvc.Commons.Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局 UI 常量定义
|
||||
/// </summary>
|
||||
public static class UIConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源路径常量
|
||||
/// </summary>
|
||||
public static class Paths
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认 Bootstrap Icons SVG Sprite 文件路径
|
||||
/// </summary>
|
||||
public const string DefaultIconSprite = "/lib/bootstrap-icons-1.13.1/bootstrap-icons.svg";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BS SVG 图标默认需要添加的 CSS 类名
|
||||
/// </summary>
|
||||
public static class Classes
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认宽度类名,适配响应式根字号(1rem)。如果用户未指定宽度,则默认添加这些类名以确保图标大小适中且响应式。用户可以通过添加其他类名覆盖这些默认值。
|
||||
/// </summary>
|
||||
public const string DefaultWidth = "w-1r";
|
||||
/// <summary>
|
||||
/// 默认高度类名,适配响应式根字号(1rem)。如果用户未指定高度,则默认添加这些类名以确保图标大小适中且响应式。用户可以通过添加其他类名覆盖这些默认值。
|
||||
/// </summary>
|
||||
public const string DefaultHeight = "h-1r";
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Extensions/StringExtensions.cs
Normal file
34
Extensions/StringExtensions.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Acdiu.AspNetCore.Mvc.Commons.Constants;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Acdiu.AspNetCore.Mvc.Commons.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 字符串扩展方法类,提供与 UI 相关的字符串处理功能。
|
||||
/// </summary>
|
||||
public static class StringExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 转换为响应式类名,默认包含默认宽高 "w-1r h-1r" 类名,并且用户可以添加其他类名,最终返回一个包含所有不重复的类名的字符串。
|
||||
/// </summary>
|
||||
/// <remarks>一个包含所有不重复的类名的字符串</remarks>
|
||||
public static string ToResponsiveClass(this string userClassName)
|
||||
{
|
||||
var classes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
UIConstants.Classes.DefaultWidth,
|
||||
UIConstants.Classes.DefaultHeight
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(userClassName))
|
||||
{
|
||||
var userParts = userClassName.Split([' '], StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var item in userParts) classes.Add(item);
|
||||
}
|
||||
|
||||
return string.Join(" ", classes);
|
||||
}
|
||||
}
|
||||
}
|
||||
166
TagHelpers/BsIconTagHelper.cs
Normal file
166
TagHelpers/BsIconTagHelper.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using Acdiu.AspNetCore.Mvc.Commons.Constants;
|
||||
using Acdiu.AspNetCore.Mvc.Commons.Extensions;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using Microsoft.VisualBasic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Acdiu.AspNetCore.Mvc.Commons.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// <see langword="Bootstrap Icons"/> SVG Sprite 封装标签。
|
||||
/// <para>支持自动缩放逻辑:若未指定宽高,则默认添加 w-1r/h-1r 类名以适配响应式根字号。</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// 用法: <bsicon i="heart-fill" w="20" f="red" />
|
||||
/// 或: <bsicon icon="alarm" width="1rem" cn="my-style" />
|
||||
/// </example>
|
||||
[HtmlTargetElement("bsicon")]
|
||||
public class BsIconTagHelper : TagHelper
|
||||
{
|
||||
// 内部逻辑变量
|
||||
private string _iconName = string.Empty;
|
||||
private string _width = string.Empty;
|
||||
private string _height = string.Empty;
|
||||
private string _fill = "currentColor";
|
||||
private string _className = string.Empty;
|
||||
private string _customPath = string.Empty;
|
||||
|
||||
#region 属性定义 (支持别名)
|
||||
|
||||
/// <summary>
|
||||
/// 图标名称 (必填)。对应 SVG 中的 ID。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("i")]
|
||||
public string I { get => _iconName; set => _iconName = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标名称 (别名)。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("icon")]
|
||||
public string Icon { get => _iconName; set => _iconName = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 宽度。支持数字或 CSS 单位(如 16, 1rem)。
|
||||
/// <remarks>若为空则尝试使用高度值,若均为空则添加默认响应式类名。</remarks>
|
||||
/// </summary>
|
||||
[HtmlAttributeName("w")]
|
||||
public string W { get => _width; set => _width = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 宽度 (别名)。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("width")]
|
||||
public string Width { get => _width; set => _width = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 高度。支持数字或 CSS 单位。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("h")]
|
||||
public string H { get => _height; set => _height = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 高度 (别名)。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("height")]
|
||||
public string Height { get => _height; set => _height = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 填充颜色。默认为 <c>currentColor</c>。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("f")]
|
||||
public string F { get => _fill; set => _fill = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 填充颜色 (别名)。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("fill")]
|
||||
public string Fill { get => _fill; set => _fill = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义 CSS 类名。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("c")]
|
||||
public string C { get => _className; set => _className = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义 CSS 类名 (别名)。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("cn")]
|
||||
public string CN { get => _className; set => _className = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义 CSS 类名 (别名)。
|
||||
/// </summary>
|
||||
[HtmlAttributeName("class")]
|
||||
public string ClassName { get => _className; set => _className = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义 SVG Sprite 路径。
|
||||
/// <remarks>不填则使用系统默认常量路径。</remarks>
|
||||
/// </summary>
|
||||
[HtmlAttributeName("p")]
|
||||
public string P { get => _customPath; set => _customPath = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义 SVG Sprite 路径。
|
||||
/// <remarks>不填则使用系统默认常量路径。</remarks>
|
||||
/// </summary>
|
||||
[HtmlAttributeName("path")]
|
||||
public string Path { get => _customPath; set => _customPath = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义 SVG Sprite 路径。
|
||||
/// <remarks>不填则使用系统默认常量路径。</remarks>
|
||||
/// </summary>
|
||||
[HtmlAttributeName("path")]
|
||||
public string CustomPath { get => _customPath; set => _customPath = value; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 处理标签渲染逻辑
|
||||
/// </summary>
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_iconName))
|
||||
{
|
||||
output.SuppressOutput();
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 设置基础标签属性
|
||||
output.TagName = "svg";
|
||||
output.TagMode = TagMode.StartTagAndEndTag;
|
||||
output.Attributes.SetAttribute("fill", _fill);
|
||||
output.Attributes.SetAttribute("viewBox", "0 0 16 16");
|
||||
|
||||
// 2. 处理宽高与类名逻辑
|
||||
bool hasW = !string.IsNullOrWhiteSpace(_width);
|
||||
bool hasH = !string.IsNullOrWhiteSpace(_height);
|
||||
|
||||
if (hasW || hasH)
|
||||
{
|
||||
// 只要设置了任意一个,就手动赋值 width/height 属性
|
||||
output.Attributes.SetAttribute("width", hasW ? _width : _height);
|
||||
output.Attributes.SetAttribute("height", hasH ? _height : _width);
|
||||
|
||||
// 设置类名(不添加默认响应式类)
|
||||
output.Attributes.SetAttribute("class", _className.ToResponsiveClass());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 均未设置,则应用响应式默认类名并去重
|
||||
output.Attributes.SetAttribute("class", _className.ToResponsiveClass());
|
||||
}
|
||||
|
||||
// 3. 构建内部内容
|
||||
string finalPath = string.IsNullOrWhiteSpace(_customPath)
|
||||
? UIConstants.Paths.DefaultIconSprite
|
||||
: _customPath;
|
||||
|
||||
output.Content.SetHtmlContent($@"<use xlink:href=""{finalPath}#{_iconName}""></use>");
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
Reference in New Issue
Block a user