diff --git a/Util.sln b/Util.sln
index 1df835ea9..9475258d6 100644
--- a/Util.sln
+++ b/Util.sln
@@ -235,7 +235,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "05-Util.Security", "src\Uti
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Security.Tests", "test\Util.Security.Tests\Util.Security.Tests.csproj", "{B25D3B7A-AEAA-4EFB-9839-7C6E3F7C24BB}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "07-Images", "07-Images", "{1F5EE147-BD88-4B6D-BA84-35B4F3BE4A4E}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "07-Tools", "07-Tools", "{1F5EE147-BD88-4B6D-BA84-35B4F3BE4A4E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Images.ImageSharp", "src\Util.Images.ImageSharp\01-Util.Images.ImageSharp.csproj", "{22305349-51C7-4D80-A538-C7C0F4495895}"
EndProject
@@ -247,7 +247,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03-EntityFrameworkCore", "0
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01-Core", "01-Core", "{2864196E-3044-4FEC-B92A-D1D3C521C567}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "07-Images", "07-Images", "{96DFADC5-FAE8-4860-A57A-93F0534B1B7A}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "07-Tools", "07-Tools", "{96DFADC5-FAE8-4860-A57A-93F0534B1B7A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Images.ImageSharp.Tests.Integration", "test\Util.Images.ImageSharp.Tests.Integration\Util.Images.ImageSharp.Tests.Integration.csproj", "{5921A7FA-8C70-49A9-82E1-BE3FA5B50C33}"
EndProject
@@ -345,6 +345,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.FileStorage.Aliyun.Tes
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.FileStorage.Abstractions", "src\Util.FileStorage.Abstractions\01-Util.FileStorage.Abstractions.csproj", "{814E42E9-508E-487F-BCD3-0F07AE7D1492}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.QrCode.ZXing", "src\Util.QrCode.ZXing\03-Util.QrCode.ZXing.csproj", "{3F5120A6-9CA4-4B25-9507-86E9E5571DB6}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.QrCode.ZXing.Tests.Integration", "test\Util.QrCode.ZXing.Tests.Integration\Util.QrCode.ZXing.Tests.Integration.csproj", "{79A40AC0-A182-49D0-AED9-DF8B6835432A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -863,6 +867,14 @@ Global
{814E42E9-508E-487F-BCD3-0F07AE7D1492}.Debug|Any CPU.Build.0 = Debug|Any CPU
{814E42E9-508E-487F-BCD3-0F07AE7D1492}.Release|Any CPU.ActiveCfg = Release|Any CPU
{814E42E9-508E-487F-BCD3-0F07AE7D1492}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3F5120A6-9CA4-4B25-9507-86E9E5571DB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3F5120A6-9CA4-4B25-9507-86E9E5571DB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3F5120A6-9CA4-4B25-9507-86E9E5571DB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3F5120A6-9CA4-4B25-9507-86E9E5571DB6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {79A40AC0-A182-49D0-AED9-DF8B6835432A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {79A40AC0-A182-49D0-AED9-DF8B6835432A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {79A40AC0-A182-49D0-AED9-DF8B6835432A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {79A40AC0-A182-49D0-AED9-DF8B6835432A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1034,6 +1046,8 @@ Global
{4938D59D-CF50-4090-B936-36DB29EBE344} = {E069CEB0-8092-4907-BC9D-C6B8BDE20AD2}
{58C01936-5D8F-4077-8663-EE0E35776D65} = {16175228-03CA-414A-8786-E5BA844110C4}
{814E42E9-508E-487F-BCD3-0F07AE7D1492} = {E069CEB0-8092-4907-BC9D-C6B8BDE20AD2}
+ {3F5120A6-9CA4-4B25-9507-86E9E5571DB6} = {1F5EE147-BD88-4B6D-BA84-35B4F3BE4A4E}
+ {79A40AC0-A182-49D0-AED9-DF8B6835432A} = {96DFADC5-FAE8-4860-A57A-93F0534B1B7A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {94347832-A36D-4C42-9C4D-B848BD4F5DA9}
diff --git a/build/version.props b/build/version.props
index e3c985d5b..fab4cbb6d 100644
--- a/build/version.props
+++ b/build/version.props
@@ -2,7 +2,7 @@
8
0
- 11
+ 12
$(VersionMajor).$(VersionMinor).$(VersionPatch)
diff --git a/src/Util.Core/Helpers/File.cs b/src/Util.Core/Helpers/File.cs
index db9f3f332..704501804 100644
--- a/src/Util.Core/Helpers/File.cs
+++ b/src/Util.Core/Helpers/File.cs
@@ -1,4 +1,4 @@
-namespace Util.Helpers;
+namespace Util.Helpers;
///
/// 文件流操作
@@ -33,7 +33,7 @@ public static byte[] ToBytes( string data ) {
/// 字符编码
public static byte[] ToBytes( string data, Encoding encoding ) {
if ( string.IsNullOrWhiteSpace( data ) )
- return new byte[] { };
+ return Array.Empty();
return encoding.GetBytes( data );
}
@@ -136,7 +136,7 @@ public static string ReadToString( string filePath ) {
/// 文件绝对路径
/// 字符编码
public static string ReadToString( string filePath, Encoding encoding ) {
- if( System.IO.File.Exists( filePath ) == false )
+ if ( System.IO.File.Exists( filePath ) == false )
return string.Empty;
using var reader = new StreamReader( filePath, encoding );
return reader.ReadToEnd();
@@ -182,7 +182,7 @@ public static async Task ReadToStringAsync( string filePath ) {
/// 文件绝对路径
/// 字符编码
public static async Task ReadToStringAsync( string filePath, Encoding encoding ) {
- if( System.IO.File.Exists( filePath ) == false )
+ if ( System.IO.File.Exists( filePath ) == false )
return string.Empty;
using var reader = new StreamReader( filePath, encoding );
return await reader.ReadToEndAsync();
@@ -295,18 +295,34 @@ public static byte[] ReadToBytes( Stream stream ) {
/// 文件绝对路径
/// 内容
public static void Write( string filePath, string content ) {
+ if ( content.IsEmpty() )
+ return;
Write( filePath, Convert.ToBytes( content ) );
}
+ ///
+ /// 将流写入文件
+ ///
+ /// 文件绝对路径
+ /// 内容
+ public static void Write( string filePath, Stream content ) {
+ if ( content == null )
+ return;
+ using ( content ) {
+ var bytes = ToBytes( content );
+ Write( filePath, bytes );
+ }
+ }
+
///
/// 将字节流写入文件
///
/// 文件绝对路径
/// 内容
public static void Write( string filePath, byte[] content ) {
- if( string.IsNullOrWhiteSpace( filePath ) )
+ if ( string.IsNullOrWhiteSpace( filePath ) )
return;
- if( content == null )
+ if ( content == null )
return;
CreateDirectory( filePath );
System.IO.File.WriteAllBytes( filePath, content );
@@ -323,6 +339,8 @@ public static void Write( string filePath, byte[] content ) {
/// 内容
/// 取消令牌
public static async Task WriteAsync( string filePath, string content, CancellationToken cancellationToken = default ) {
+ if ( content.IsEmpty() )
+ return;
await WriteAsync( filePath, Convert.ToBytes( content ), cancellationToken );
}
@@ -333,8 +351,12 @@ public static void Write( string filePath, byte[] content ) {
/// 内容
/// 取消令牌
public static async Task WriteAsync( string filePath, Stream content, CancellationToken cancellationToken = default ) {
- var bytes = await ToBytesAsync( content, cancellationToken );
- await WriteAsync( filePath, bytes, cancellationToken );
+ if ( content == null )
+ return;
+ await using ( content ) {
+ var bytes = await ToBytesAsync( content, cancellationToken );
+ await WriteAsync( filePath, bytes, cancellationToken );
+ }
}
///
@@ -344,9 +366,9 @@ public static void Write( string filePath, byte[] content ) {
/// 内容
/// 取消令牌
public static async Task WriteAsync( string filePath, byte[] content, CancellationToken cancellationToken = default ) {
- if( string.IsNullOrWhiteSpace( filePath ) )
+ if ( string.IsNullOrWhiteSpace( filePath ) )
return;
- if( content == null )
+ if ( content == null )
return;
CreateDirectory( filePath );
await System.IO.File.WriteAllBytesAsync( filePath, content, cancellationToken );
@@ -361,7 +383,7 @@ public static void Write( string filePath, byte[] content ) {
///
/// 文件绝对路径集合
public static void Delete( IEnumerable filePaths ) {
- foreach( var filePath in filePaths )
+ foreach ( var filePath in filePaths )
Delete( filePath );
}
@@ -370,9 +392,9 @@ public static void Delete( IEnumerable filePaths ) {
///
/// 文件绝对路径
public static void Delete( string filePath ) {
- if( string.IsNullOrWhiteSpace( filePath ) )
+ if ( string.IsNullOrWhiteSpace( filePath ) )
return;
- if( System.IO.File.Exists( filePath ) )
+ if ( System.IO.File.Exists( filePath ) )
System.IO.File.Delete( filePath );
}
@@ -385,7 +407,7 @@ public static void Delete( string filePath ) {
///
/// 目录路径
/// 搜索模式
- public static List GetAllFiles( string path,string searchPattern ) {
+ public static List GetAllFiles( string path, string searchPattern ) {
return Directory.GetFiles( path, searchPattern, SearchOption.AllDirectories )
.Select( filePath => new FileInfo( filePath ) ).ToList();
}
@@ -400,10 +422,10 @@ public static List GetAllFiles( string path,string searchPattern ) {
/// 源文件绝对路径
/// 目标文件绝对路径
/// 目标文件存在时是否覆盖,默认值: false
- public static void Copy( string sourceFilePath,string destinationFilePath, bool overwrite = false ) {
+ public static void Copy( string sourceFilePath, string destinationFilePath, bool overwrite = false ) {
if ( sourceFilePath.IsEmpty() || destinationFilePath.IsEmpty() )
return;
- if( FileExists( sourceFilePath ) == false )
+ if ( FileExists( sourceFilePath ) == false )
return;
CreateDirectory( destinationFilePath );
System.IO.File.Copy( sourceFilePath, destinationFilePath, overwrite );
@@ -420,9 +442,9 @@ public static void Copy( string sourceFilePath,string destinationFilePath, bool
/// 目标文件绝对路径
/// 目标文件存在时是否覆盖,默认值: false
public static void Move( string sourceFilePath, string destinationFilePath, bool overwrite = false ) {
- if( sourceFilePath.IsEmpty() || destinationFilePath.IsEmpty() )
+ if ( sourceFilePath.IsEmpty() || destinationFilePath.IsEmpty() )
return;
- if( FileExists( sourceFilePath ) == false )
+ if ( FileExists( sourceFilePath ) == false )
return;
CreateDirectory( destinationFilePath );
System.IO.File.Move( sourceFilePath, destinationFilePath, overwrite );
diff --git a/src/Util.Core/Helpers/Json.cs b/src/Util.Core/Helpers/Json.cs
index 7b41f9e7b..645764ab8 100644
--- a/src/Util.Core/Helpers/Json.cs
+++ b/src/Util.Core/Helpers/Json.cs
@@ -1,6 +1,6 @@
using Util.SystemTextJson;
-namespace Util.Helpers;
+namespace Util.Helpers;
///
/// Json操作
@@ -23,6 +23,11 @@ public static string ToJson( T value, JsonOptions options ) {
///
private static JsonSerializerOptions ToJsonSerializerOptions( JsonOptions options ) {
var jsonSerializerOptions = new JsonSerializerOptions();
+ if ( options.IgnoreEmptyString ) {
+ jsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver {
+ Modifiers = { IgnoreEmptyString }
+ };
+ }
if ( options.IgnoreNullValues )
jsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
if ( options.IgnoreCase )
@@ -37,6 +42,19 @@ private static JsonSerializerOptions ToJsonSerializerOptions( JsonOptions option
return jsonSerializerOptions;
}
+ ///
+ /// 忽略空字符串
+ ///
+ private static void IgnoreEmptyString( JsonTypeInfo jsonTypeInfo ) {
+ if ( jsonTypeInfo.Kind != JsonTypeInfoKind.Object )
+ return;
+ foreach ( JsonPropertyInfo jsonPropertyInfo in jsonTypeInfo.Properties ) {
+ if ( jsonPropertyInfo.PropertyType == typeof( string ) ) {
+ jsonPropertyInfo.ShouldSerialize = static ( _, value ) => value.SafeString().IsEmpty() == false;
+ }
+ }
+ }
+
///
/// 将对象转换为Json字符串
///
@@ -44,14 +62,14 @@ private static JsonSerializerOptions ToJsonSerializerOptions( JsonOptions option
/// 序列化配置
/// 是否移除双引号
/// 是否将双引号转成单引号
- public static string ToJson( T value, JsonSerializerOptions options = null,bool removeQuotationMarks = false, bool toSingleQuotes = false ) {
- return ToJson( value, options, removeQuotationMarks, toSingleQuotes,true );
+ public static string ToJson( T value, JsonSerializerOptions options = null, bool removeQuotationMarks = false, bool toSingleQuotes = false ) {
+ return ToJson( value, options, removeQuotationMarks, toSingleQuotes, true );
}
///
/// 将对象转换为Json字符串
///
- private static string ToJson( T value, JsonSerializerOptions options, bool removeQuotationMarks, bool toSingleQuotes,bool ignoreInterface ) {
+ private static string ToJson( T value, JsonSerializerOptions options, bool removeQuotationMarks, bool toSingleQuotes, bool ignoreInterface ) {
if ( value == null )
return string.Empty;
options = GetToJsonOptions( options );
@@ -87,7 +105,7 @@ private static JsonSerializerOptions GetToJsonOptions( JsonSerializerOptions opt
private static string Serialize( T value, JsonSerializerOptions options, bool ignoreInterface ) {
if ( ignoreInterface ) {
object instance = value;
- if( instance != null )
+ if ( instance != null )
return JsonSerializer.Serialize( instance, options );
}
return JsonSerializer.Serialize( value, options );
diff --git a/src/Util.Core/JsonOptions.cs b/src/Util.Core/JsonOptions.cs
index d482fc893..df495358f 100644
--- a/src/Util.Core/JsonOptions.cs
+++ b/src/Util.Core/JsonOptions.cs
@@ -9,6 +9,7 @@ public class JsonOptions {
///
public JsonOptions() {
IgnoreNullValues = true;
+ IgnoreEmptyString = true;
IgnoreCase = true;
IgnoreInterface = true;
}
@@ -26,6 +27,10 @@ public JsonOptions() {
///
public bool IgnoreNullValues { get; set; }
///
+ /// 是否忽略空字符串,默认值: true
+ ///
+ public bool IgnoreEmptyString { get; set; }
+ ///
/// 转换为Json时,属性名是否使用驼峰形式
///
public bool ToCamelCase { get; set; }
diff --git a/src/Util.Core/Usings.cs b/src/Util.Core/Usings.cs
index 689e28fa2..d0e96760f 100644
--- a/src/Util.Core/Usings.cs
+++ b/src/Util.Core/Usings.cs
@@ -22,6 +22,7 @@
global using System.Net.Http;
global using System.Xml;
global using System.Xml.Linq;
+global using System.Text.Json.Serialization.Metadata;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
diff --git a/src/Util.Images.ImageSharp/ImageSharpExtensions.cs b/src/Util.Images.ImageSharp/ImageSharpExtensions.cs
new file mode 100644
index 000000000..281086331
--- /dev/null
+++ b/src/Util.Images.ImageSharp/ImageSharpExtensions.cs
@@ -0,0 +1,69 @@
+using SixLabors.ImageSharp.Drawing;
+
+namespace Util.Images;
+
+///
+/// ImageSharp扩展
+///
+public static class ImageSharpExtensions {
+ ///
+ /// 转换颜色类型
+ ///
+ /// 颜色
+ public static Color ToImageSharpColor( this System.Drawing.Color color ) {
+ return Color.FromRgba( color.R, color.G, color.B, color.A );
+ }
+
+ ///
+ /// 图片缩放
+ ///
+ /// 图片
+ /// 缩放比例
+ public static Image Zoom( this Image image, double scale ) {
+ var width = Util.Helpers.Convert.ToInt( image.Width * scale );
+ var height = Util.Helpers.Convert.ToInt( image.Height * scale );
+ image.Mutate( t => {
+ t.Resize( new Size( width, height ) );
+ } );
+ return image;
+ }
+
+ ///
+ /// 设置圆角
+ ///
+ /// 图片
+ /// 角度
+ public static Image RoundCorners( this Image image, int cornerRadius ) {
+ image.Mutate( context => RoundCorners( context, cornerRadius ) );
+ return image;
+ }
+
+ ///
+ /// 设置圆角
+ ///
+ /// 图片处理上下文
+ /// 角度
+ private static void RoundCorners( IImageProcessingContext context, int cornerRadius ) {
+ var size = context.GetCurrentSize();
+ var corners = BuildCorners( size.Width, size.Height, cornerRadius );
+ context.SetGraphicsOptions( new GraphicsOptions { AlphaCompositionMode = PixelAlphaCompositionMode.DestOut } );
+ context.Fill( Color.Red, corners );
+ }
+
+ ///
+ /// 构建圆角
+ ///
+ /// 图片宽度
+ /// 图片高度
+ /// 角度
+ private static IPathCollection BuildCorners( int imageWidth, int imageHeight, float cornerRadius ) {
+ var rect = new RectangularPolygon( -0.5f, -0.5f, cornerRadius, cornerRadius );
+ var cornerTopLeft = rect.Clip( new EllipsePolygon( cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius ) );
+ var rightPos = imageWidth - cornerTopLeft.Bounds.Width + 1;
+ var bottomPos = imageHeight - cornerTopLeft.Bounds.Height + 1;
+ var cornerTopRight = cornerTopLeft.RotateDegree( 90 ).Translate( rightPos, 0 );
+ var cornerBottomLeft = cornerTopLeft.RotateDegree( -90 ).Translate( 0, bottomPos );
+ var cornerBottomRight = cornerTopLeft.RotateDegree( 180 ).Translate( rightPos, bottomPos );
+ return new PathCollection( cornerTopLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight );
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Images.ImageSharp/ImageWrapper.cs b/src/Util.Images.ImageSharp/ImageWrapper.cs
index 666b1463d..9adccfa47 100644
--- a/src/Util.Images.ImageSharp/ImageWrapper.cs
+++ b/src/Util.Images.ImageSharp/ImageWrapper.cs
@@ -1,6 +1,6 @@
using Util.Images.Commands;
-namespace Util.Images;
+namespace Util.Images;
///
/// 图片操作包装器
@@ -175,18 +175,7 @@ protected Color GetColor( string color ) {
/// 获取图片编码器
///
private IImageEncoder GetImageEncoder() {
- switch ( _imageType ) {
- case Images.ImageType.Png:
- return new PngEncoder();
- case Images.ImageType.Gif:
- return new GifEncoder();
- case Images.ImageType.Bmp:
- return new BmpEncoder();
- case Images.ImageType.Jpg:
- return new JpegEncoder();
- default:
- return new PngEncoder();
- }
+ return GetImageEncoder( _imageType );
}
#endregion
@@ -199,7 +188,7 @@ private IImageEncoder GetImageEncoder() {
using var stream = new MemoryStream();
_commands.ForEach( command => command.Invoke( image ) );
await image.SaveAsync( stream, GetImageEncoder(), cancellationToken );
- return await Util.Helpers.File.ToBytesAsync( stream ) ;
+ return await Util.Helpers.File.ToBytesAsync( stream, cancellationToken );
}
#endregion
@@ -217,7 +206,40 @@ public string ToBase64() {
/// 获取图片格式
///
private IImageFormat GetImageFormat() {
- switch ( _imageType ) {
+ return GetImageFormat( _imageType );
+ }
+
+ #endregion
+
+ #region GetImageEncoder
+
+ ///
+ /// 获取图片编码器
+ ///
+ public static IImageEncoder GetImageEncoder( ImageType type ) {
+ switch ( type ) {
+ case Images.ImageType.Png:
+ return new PngEncoder();
+ case Images.ImageType.Gif:
+ return new GifEncoder();
+ case Images.ImageType.Bmp:
+ return new BmpEncoder();
+ case Images.ImageType.Jpg:
+ return new JpegEncoder();
+ default:
+ return new PngEncoder();
+ }
+ }
+
+ #endregion
+
+ #region GetImageFormat
+
+ ///
+ /// 获取图片格式
+ ///
+ public static IImageFormat GetImageFormat( ImageType type ) {
+ switch ( type ) {
case Images.ImageType.Png:
return PngFormat.Instance;
case Images.ImageType.Gif:
diff --git a/src/Util.Localization/StringLocalizer.cs b/src/Util.Localization/StringLocalizer.cs
index 2e54f5fce..3626d2e44 100644
--- a/src/Util.Localization/StringLocalizer.cs
+++ b/src/Util.Localization/StringLocalizer.cs
@@ -14,8 +14,8 @@ internal class StringLocalizer : IStringLocalizer {
///
/// 本地化资源查找器工厂
public StringLocalizer( IStringLocalizerFactory factory ) {
- var assemblyName = new AssemblyName( GetType().Assembly.FullName );
- _localizer = factory.Create( null, assemblyName.FullName );
+ var assemblyName = new AssemblyName( GetType().Assembly.FullName! );
+ _localizer = factory.Create( string.Empty, assemblyName.FullName );
}
///
diff --git a/src/Util.QrCode.ZXing/03-Util.QrCode.ZXing.csproj b/src/Util.QrCode.ZXing/03-Util.QrCode.ZXing.csproj
new file mode 100644
index 000000000..6878773e7
--- /dev/null
+++ b/src/Util.QrCode.ZXing/03-Util.QrCode.ZXing.csproj
@@ -0,0 +1,38 @@
+
+
+
+ $(NetTargetFramework)
+ icon.jpg
+ Util.QrCode.ZXing
+ Util.QrCode
+ Util.QrCode.ZXing是Util应用框架基于ZXing.Net的条形码操作类库,用于二维码生成
+
+
+
+
+ .\obj\Debug\$(NetTargetFramework)\Util.QrCode.ZXing.xml
+
+
+
+
+ .\obj\Release\$(NetTargetFramework)\Util.QrCode.ZXing.xml
+
+
+
+
+ True
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Util.QrCode.ZXing/ErrorCorrectionLevel.cs b/src/Util.QrCode.ZXing/ErrorCorrectionLevel.cs
new file mode 100644
index 000000000..16fcb3a16
--- /dev/null
+++ b/src/Util.QrCode.ZXing/ErrorCorrectionLevel.cs
@@ -0,0 +1,23 @@
+namespace Util.QrCode;
+
+///
+/// 容错级别
+///
+public enum ErrorCorrectionLevel {
+ ///
+ /// 可以纠正最大7%的错误
+ ///
+ L,
+ ///
+ /// 可以纠正最大15%的错误
+ ///
+ M,
+ ///
+ /// 可以纠正最大25%的错误
+ ///
+ Q,
+ ///
+ /// 可以纠正最大30%的错误
+ ///
+ H
+}
\ No newline at end of file
diff --git a/src/Util.QrCode.ZXing/IQrCodeService.cs b/src/Util.QrCode.ZXing/IQrCodeService.cs
new file mode 100644
index 000000000..bfc278fc1
--- /dev/null
+++ b/src/Util.QrCode.ZXing/IQrCodeService.cs
@@ -0,0 +1,86 @@
+using Util.Images;
+
+namespace Util.QrCode;
+
+///
+/// 二维码服务
+///
+public interface IQrCodeService : ITransientDependency {
+ ///
+ /// 设置二维码内容
+ ///
+ /// 二维码内容
+ IQrCodeService Content( string content );
+ ///
+ /// 设置二维码尺寸
+ ///
+ /// 二维码尺寸
+ IQrCodeService Size( QrSize size );
+ ///
+ /// 设置二维码尺寸
+ ///
+ /// 二维码尺寸
+ IQrCodeService Size( int size );
+ ///
+ /// 容错处理
+ ///
+ /// 容错级别
+ IQrCodeService Correction( ErrorCorrectionLevel level );
+ ///
+ /// 设置图片类型
+ ///
+ /// 图片类型
+ IQrCodeService ImageType( ImageType type );
+ ///
+ /// 设置前景色
+ ///
+ /// 前景色
+ IQrCodeService Color( Color color );
+ ///
+ /// 设置背景色
+ ///
+ /// 背景色
+ IQrCodeService BgColor( Color color );
+ ///
+ /// 设置边距
+ ///
+ /// 边距,单位:像素
+ IQrCodeService Margin( int margin );
+ ///
+ /// 设置图标
+ ///
+ /// 图标绝对路径
+ IQrCodeService Icon( string path );
+ ///
+ /// 获取二维码流
+ ///
+ Stream ToStream();
+ ///
+ /// 获取二维码字节流
+ ///
+ byte[] ToBytes();
+ ///
+ /// 获取二维码Base64字符串
+ ///
+ string ToBase64();
+ ///
+ /// 保存二维码图片
+ ///
+ /// 文件绝对路径
+ void Save( string path );
+ ///
+ /// 获取二维码流
+ ///
+ /// 取消令牌
+ Task ToStreamAsync( CancellationToken cancellationToken = default );
+ ///
+ /// 获取二维码字节流
+ ///
+ Task ToBytesAsync( CancellationToken cancellationToken = default );
+ ///
+ /// 保存二维码图片
+ ///
+ /// 文件绝对路径
+ /// 取消令牌
+ Task SaveAsync( string path, CancellationToken cancellationToken = default );
+}
\ No newline at end of file
diff --git a/src/Util.QrCode.ZXing/QrSize.cs b/src/Util.QrCode.ZXing/QrSize.cs
new file mode 100644
index 000000000..eeea34713
--- /dev/null
+++ b/src/Util.QrCode.ZXing/QrSize.cs
@@ -0,0 +1,19 @@
+namespace Util.QrCode;
+
+///
+/// 二维码尺寸
+///
+public enum QrSize {
+ ///
+ /// 小
+ ///
+ Small = 100,
+ ///
+ /// 中
+ ///
+ Middle = 200,
+ ///
+ /// 大
+ ///
+ Large = 300
+}
\ No newline at end of file
diff --git a/src/Util.QrCode.ZXing/Usings.cs b/src/Util.QrCode.ZXing/Usings.cs
new file mode 100644
index 000000000..f7ef8bbe2
--- /dev/null
+++ b/src/Util.QrCode.ZXing/Usings.cs
@@ -0,0 +1,12 @@
+global using System;
+global using System.Threading.Tasks;
+global using System.Threading;
+global using System.Drawing;
+global using System.IO;
+global using SixLabors.ImageSharp.Formats;
+global using SixLabors.ImageSharp.Processing;
+global using ZXing;
+global using ZXing.QrCode;
+global using ZXing.ImageSharp.Rendering;
+global using SixLabors.ImageSharp.PixelFormats;
+global using Util.Dependency;
\ No newline at end of file
diff --git a/src/Util.QrCode.ZXing/ZXing/ZXingQrCodeService.cs b/src/Util.QrCode.ZXing/ZXing/ZXingQrCodeService.cs
new file mode 100644
index 000000000..0641a5f46
--- /dev/null
+++ b/src/Util.QrCode.ZXing/ZXing/ZXingQrCodeService.cs
@@ -0,0 +1,228 @@
+using Util.Images;
+using SixLabors.ImageSharp;
+using CorrectionLevel = ZXing.QrCode.Internal.ErrorCorrectionLevel;
+
+namespace Util.QrCode.ZXing;
+
+///
+/// ZXing二维码服务
+///
+public class ZXingQrCodeService : IQrCodeService {
+ ///
+ /// 内容
+ ///
+ private string _content;
+ ///
+ /// 二维码尺寸
+ ///
+ private int _size;
+ ///
+ /// 容错级别
+ ///
+ private CorrectionLevel _level;
+ ///
+ /// 图片类型
+ ///
+ private ImageType _imageType;
+ ///
+ /// 前景色
+ ///
+ private System.Drawing.Color _foreground;
+ ///
+ /// 背景色
+ ///
+ private System.Drawing.Color _background;
+ ///
+ /// 边距
+ ///
+ private int _margin;
+ ///
+ /// 图标路径
+ ///
+ private string _iconPath;
+
+ ///
+ /// 初始化二维码服务
+ ///
+ public ZXingQrCodeService() {
+ _level = CorrectionLevel.L;
+ _imageType = Images.ImageType.Png;
+ _foreground = System.Drawing.Color.Black;
+ _background = System.Drawing.Color.White;
+ _margin = 0;
+ Size( 160 );
+ }
+
+ ///
+ public IQrCodeService Content( string content ) {
+ _content = content;
+ return this;
+ }
+
+ ///
+ public IQrCodeService Size( QrSize size ) {
+ return Size( size.Value().SafeValue() );
+ }
+
+ ///
+ public IQrCodeService Size( int size ) {
+ _size = size;
+ return this;
+ }
+
+ ///
+ public IQrCodeService Correction( ErrorCorrectionLevel level ) {
+ switch ( level ) {
+ case ErrorCorrectionLevel.L:
+ _level = CorrectionLevel.L;
+ break;
+ case ErrorCorrectionLevel.M:
+ _level = CorrectionLevel.M;
+ break;
+ case ErrorCorrectionLevel.Q:
+ _level = CorrectionLevel.Q;
+ break;
+ case ErrorCorrectionLevel.H:
+ _level = CorrectionLevel.H;
+ break;
+ }
+ return this;
+ }
+
+ ///
+ public IQrCodeService ImageType( ImageType type ) {
+ _imageType = type;
+ return this;
+ }
+
+ ///
+ public IQrCodeService Color( System.Drawing.Color color ) {
+ _foreground = color;
+ return this;
+ }
+
+ ///
+ public IQrCodeService BgColor( System.Drawing.Color color ) {
+ _background = color;
+ return this;
+ }
+
+ ///
+ public IQrCodeService Margin( int margin ) {
+ _margin = margin;
+ return this;
+ }
+
+ ///
+ public IQrCodeService Icon( string path ) {
+ _iconPath = path;
+ return this;
+ }
+
+ ///
+ public Stream ToStream() {
+ var bytes = ToBytes();
+ return new MemoryStream( bytes );
+ }
+
+ ///
+ public byte[] ToBytes() {
+ using var image = GetImage();
+ using var stream = new MemoryStream();
+ image.Save( stream, GetImageEncoder() );
+ return stream.ToArray();
+ }
+
+ ///
+ public string ToBase64() {
+ using var image = GetImage();
+ return image.ToBase64String( GetImageFormat() );
+ }
+
+ ///
+ /// 获取图片格式
+ ///
+ private IImageFormat GetImageFormat() {
+ return ImageWrapper.GetImageFormat( _imageType );
+ }
+
+ ///
+ public void Save( string path ) {
+ if ( path.IsEmpty() )
+ return;
+ Util.Helpers.File.CreateDirectory( path );
+ using var image = GetImage();
+ image.Save( path, GetImageEncoder() );
+ }
+
+ ///
+ public async Task ToStreamAsync( CancellationToken cancellationToken = default ) {
+ var bytes = await ToBytesAsync( cancellationToken );
+ return new MemoryStream( bytes );
+ }
+
+ ///
+ public async Task ToBytesAsync( CancellationToken cancellationToken = default ) {
+ using var image = GetImage();
+ using var stream = new MemoryStream();
+ await image.SaveAsync( stream, GetImageEncoder(), cancellationToken );
+ return stream.ToArray();
+ }
+
+ ///
+ /// 获取二维码图片
+ ///
+ private Image GetImage() {
+ if ( _content.IsEmpty() )
+ throw new ArgumentException( "必须设置内容" );
+ var writer = new BarcodeWriter> {
+ Format = BarcodeFormat.QR_CODE,
+ Options = new QrCodeEncodingOptions {
+ CharacterSet = "UTF-8",
+ ErrorCorrection = _level,
+ Margin = _margin,
+ Width = _size,
+ Height = _size
+ },
+ Renderer = new ImageSharpRenderer {
+ Foreground = _foreground.ToImageSharpColor(),
+ Background = _background.ToImageSharpColor()
+ }
+ };
+ var result = writer.Write( _content );
+ return _iconPath.IsEmpty() ? result : MergeImage( result, Image.Load( _iconPath ) );
+ }
+
+ ///
+ /// 合并图片
+ ///
+ private Image MergeImage( Image image, Image icon ) {
+ var margin = 10 - _margin;
+ if ( margin <= 0 )
+ margin = 5;
+ var width = ( image.Width * margin - 46 * margin ) * 1.0f / 46;
+ icon.Zoom( width / icon.Width );
+ icon.RoundCorners( 7 );
+ image.RoundCorners( 7 );
+ image.Mutate( x => {
+ x.DrawImage( icon, new SixLabors.ImageSharp.Point( ( image.Width - icon.Width ) / 2, ( image.Height - icon.Height ) / 2 ), 1 );
+ } );
+ return image;
+ }
+
+ ///
+ /// 获取图片编码器
+ ///
+ private IImageEncoder GetImageEncoder() {
+ return ImageWrapper.GetImageEncoder( _imageType );
+ }
+
+ ///
+ public async Task SaveAsync( string path, CancellationToken cancellationToken = default ) {
+ if ( path.IsEmpty() )
+ return;
+ Util.Helpers.File.CreateDirectory( path );
+ using var image = GetImage();
+ await image.SaveAsync( path, GetImageEncoder(), cancellationToken );
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Security/05-Util.Security.csproj b/src/Util.Security/05-Util.Security.csproj
index c8ac19085..ba3d83f4e 100644
--- a/src/Util.Security/05-Util.Security.csproj
+++ b/src/Util.Security/05-Util.Security.csproj
@@ -27,7 +27,7 @@
-
+
diff --git a/src/Util.Templates.Handlebars/03-Util.Templates.Handlebars.csproj b/src/Util.Templates.Handlebars/03-Util.Templates.Handlebars.csproj
index 6aa5a6503..dd501c6bf 100644
--- a/src/Util.Templates.Handlebars/03-Util.Templates.Handlebars.csproj
+++ b/src/Util.Templates.Handlebars/03-Util.Templates.Handlebars.csproj
@@ -27,7 +27,7 @@
-
+
diff --git a/src/Util.Ui.Angular/Configs/AngularConst.cs b/src/Util.Ui.Angular/Configs/AngularConst.cs
index 289e6352c..64e3a112b 100644
--- a/src/Util.Ui.Angular/Configs/AngularConst.cs
+++ b/src/Util.Ui.Angular/Configs/AngularConst.cs
@@ -45,14 +45,46 @@ public static class AngularConst {
///
public const string BindLink = "bind-link";
///
+ /// 可见高度
+ ///
+ public const string BindVisibilityHeight = "bind-visibility-height";
+ ///
+ /// 持续时间
+ ///
+ public const string BindDuration = "bind-duration";
+ ///
+ /// Logo
+ ///
+ public const string BindLogo = "bind-logo";
+ ///
+ /// 等级
+ ///
+ public const string BindLevel = "bind-level";
+ ///
+ /// 图片
+ ///
+ public const string BindImage = "bind-image";
+ ///
+ /// 填充
+ ///
+ public const string BindPadding = "bind-padding";
+ ///
/// Html
///
public const string BindHtml = "bind-html";
///
+ /// 背景色
+ ///
+ public const string BindBgColor = "bind-bg-color";
+ ///
/// 访问控制
///
public const string BindAcl = "bind-acl";
///
+ /// 标签文本
+ ///
+ public const string BindLabelText = "bind-label-text";
+ ///
/// 触发器
///
public const string BindTrigger = "bind-trigger";
@@ -461,6 +493,10 @@ public static class AngularConst {
///
public const string BindIcon = "bind-icon";
///
+ /// 图标尺寸
+ ///
+ public const string BindIconSize = "bind-icon-size";
+ ///
/// href
///
public const string BindHref = "bind-href";
diff --git a/src/Util.Ui.NgAlain/Components/Tinymce/Builders/TinymceBuilder.cs b/src/Util.Ui.NgAlain/Components/Tinymce/Builders/TinymceBuilder.cs
index 0de2b6fe2..b3ec27c78 100644
--- a/src/Util.Ui.NgAlain/Components/Tinymce/Builders/TinymceBuilder.cs
+++ b/src/Util.Ui.NgAlain/Components/Tinymce/Builders/TinymceBuilder.cs
@@ -133,7 +133,7 @@ private void ConfigConfig() {
///
public override void Config() {
base.ConfigBase( _config );
- NgModel().FormControl().SpaceItem().OnModelChange()
+ NgModel().FormControl().OnModelChange()
.Required().RequiredMessage()
.TableEdit().ValidationExtend()
.Name().Branding().PasteDataImages()
diff --git a/src/Util.Ui.NgZorro/Components/Affixes/AffixTagHelper.cs b/src/Util.Ui.NgZorro/Components/Affixes/AffixTagHelper.cs
index fdb669059..00d0c3700 100644
--- a/src/Util.Ui.NgZorro/Components/Affixes/AffixTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/Affixes/AffixTagHelper.cs
@@ -1,6 +1,5 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using Util.Ui.Angular.TagHelpers;
-using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Affixes.Renders;
using Util.Ui.Renders;
diff --git a/src/Util.Ui.NgZorro/Components/Affixes/Builders/AffixBuilder.cs b/src/Util.Ui.NgZorro/Components/Affixes/Builders/AffixBuilder.cs
index 575c21971..fd9372c05 100644
--- a/src/Util.Ui.NgZorro/Components/Affixes/Builders/AffixBuilder.cs
+++ b/src/Util.Ui.NgZorro/Components/Affixes/Builders/AffixBuilder.cs
@@ -1,6 +1,5 @@
using Util.Ui.Angular.Builders;
using Util.Ui.Angular.Configs;
-using Util.Ui.Configs;
namespace Util.Ui.NgZorro.Components.Affixes.Builders;
diff --git a/src/Util.Ui.NgZorro/Components/Affixes/Renders/AffixRender.cs b/src/Util.Ui.NgZorro/Components/Affixes/Renders/AffixRender.cs
index 78deabf9a..fff7992f2 100644
--- a/src/Util.Ui.NgZorro/Components/Affixes/Renders/AffixRender.cs
+++ b/src/Util.Ui.NgZorro/Components/Affixes/Renders/AffixRender.cs
@@ -1,5 +1,4 @@
using Util.Ui.Builders;
-using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Affixes.Builders;
using Util.Ui.Renders;
diff --git a/src/Util.Ui.NgZorro/Components/BackTops/BackTopTagHelper.cs b/src/Util.Ui.NgZorro/Components/BackTops/BackTopTagHelper.cs
new file mode 100644
index 000000000..b16c26a4e
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/BackTops/BackTopTagHelper.cs
@@ -0,0 +1,47 @@
+using Microsoft.AspNetCore.Razor.TagHelpers;
+using Util.Ui.Angular.TagHelpers;
+using Util.Ui.NgZorro.Components.BackTops.Renders;
+using Util.Ui.Renders;
+
+namespace Util.Ui.NgZorro.Components.BackTops;
+
+///
+/// 回到顶部,生成的标签为<nz-back-top></nz-back-top>
+///
+[HtmlTargetElement( "util-back-top" )]
+public class BackTopTagHelper : AngularTagHelperBase {
+ ///
+ /// [nzTemplate],自定义内容, 类型: TemplateRef<void>
+ ///
+ public string Template { get; set; }
+ ///
+ /// [nzVisibilityHeight],滚动高度达到该值才显示回到顶部按钮, 默认值: 400
+ ///
+ public double VisibilityHeight { get; set; }
+ ///
+ /// [nzVisibilityHeight],滚动高度达到该值才显示回到顶部按钮, 默认值: 400
+ ///
+ public string BindVisibilityHeight { get; set; }
+ ///
+ /// [nzTarget],设置监听目标元素, 类型: string | Element, 默认值: window
+ ///
+ public string Target { get; set; }
+ ///
+ /// [nzDuration],回到顶部所需时间,单位: 毫秒, 默认值: 450
+ ///
+ public double Duration { get; set; }
+ ///
+ /// [nzDuration],回到顶部所需时间,单位: 毫秒, 默认值: 450
+ ///
+ public string BindDuration { get; set; }
+ ///
+ /// (nzClick), 单击回到顶部按钮事件,类型: EventEmitter<boolean>
+ ///
+ public string OnClick { get; set; }
+
+ ///
+ protected override IRender GetRender( TagHelperContext context, TagHelperOutput output, TagHelperContent content ) {
+ var config = new Config( context, output, content );
+ return new BackTopRender( config );
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/BackTops/Builders/BackTopBuilder.cs b/src/Util.Ui.NgZorro/Components/BackTops/Builders/BackTopBuilder.cs
new file mode 100644
index 000000000..188c4d972
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/BackTops/Builders/BackTopBuilder.cs
@@ -0,0 +1,72 @@
+using Util.Ui.Angular.Builders;
+using Util.Ui.Angular.Configs;
+
+namespace Util.Ui.NgZorro.Components.BackTops.Builders;
+
+///
+/// 回到顶部标签生成器
+///
+public class BackTopBuilder : AngularTagBuilder {
+ ///
+ /// 配置
+ ///
+ private readonly Config _config;
+
+ ///
+ /// 初始化回到顶部标签生成器
+ ///
+ /// 配置
+ public BackTopBuilder( Config config ) : base( config, "nz-back-top" ) {
+ _config = config;
+ }
+
+ ///
+ /// 配置自定义内容
+ ///
+ public BackTopBuilder Template() {
+ AttributeIfNotEmpty( "[nzTemplate]", _config.GetValue( UiConst.Template ) );
+ return this;
+ }
+
+ ///
+ /// 配置可见高度
+ ///
+ public BackTopBuilder VisibilityHeight() {
+ AttributeIfNotEmpty( "[nzVisibilityHeight]", _config.GetValue( UiConst.VisibilityHeight ) );
+ AttributeIfNotEmpty( "[nzVisibilityHeight]", _config.GetValue( AngularConst.BindVisibilityHeight ) );
+ return this;
+ }
+
+ ///
+ /// 配置监听目标
+ ///
+ public BackTopBuilder Target() {
+ AttributeIfNotEmpty( "[nzTarget]", _config.GetValue( UiConst.Target ) );
+ return this;
+ }
+
+ ///
+ /// 配置持续时间
+ ///
+ public BackTopBuilder Duration() {
+ AttributeIfNotEmpty( "[nzDuration]", _config.GetValue( UiConst.Duration ) );
+ AttributeIfNotEmpty( "[nzDuration]", _config.GetValue( AngularConst.BindDuration ) );
+ return this;
+ }
+
+ ///
+ /// 配置事件
+ ///
+ public BackTopBuilder Events() {
+ AttributeIfNotEmpty( "(nzClick)", _config.GetValue( UiConst.OnClick ) );
+ return this;
+ }
+
+ ///
+ /// 配置
+ ///
+ public override void Config() {
+ base.Config();
+ Template().VisibilityHeight().Target().Duration().Events();
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/BackTops/Renders/BackTopRender.cs b/src/Util.Ui.NgZorro/Components/BackTops/Renders/BackTopRender.cs
new file mode 100644
index 000000000..e468e80f0
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/BackTops/Renders/BackTopRender.cs
@@ -0,0 +1,37 @@
+using Util.Ui.Builders;
+using Util.Ui.NgZorro.Components.BackTops.Builders;
+using Util.Ui.Renders;
+
+namespace Util.Ui.NgZorro.Components.BackTops.Renders;
+
+///
+/// 回到顶部渲染器
+///
+public class BackTopRender : RenderBase {
+ ///
+ /// 配置
+ ///
+ private readonly Config _config;
+
+ ///
+ /// 初始化回到顶部渲染器
+ ///
+ /// 配置
+ public BackTopRender( Config config ) {
+ _config = config;
+ }
+
+ ///
+ /// 获取标签生成器
+ ///
+ protected override TagBuilder GetTagBuilder() {
+ var builder = new BackTopBuilder( _config );
+ builder.Config();
+ return builder;
+ }
+
+ ///
+ public override IHtmlContent Clone() {
+ return new BackTopRender( _config.Copy() );
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/Base/FormControlBuilderBase.cs b/src/Util.Ui.NgZorro/Components/Base/FormControlBuilderBase.cs
index e2a70b3f2..cd85424cb 100644
--- a/src/Util.Ui.NgZorro/Components/Base/FormControlBuilderBase.cs
+++ b/src/Util.Ui.NgZorro/Components/Base/FormControlBuilderBase.cs
@@ -81,14 +81,6 @@ public TBuilder FormControl() {
return (TBuilder)this;
}
- ///
- /// 配置间距项
- ///
- public TBuilder SpaceItem() {
- this.SpaceItem( _config );
- return (TBuilder)this;
- }
-
///
/// 配置模型变更事件
///
@@ -163,7 +155,7 @@ public virtual TBuilder Pattern() {
/// 配置表单属性
///
protected TBuilder ConfigForm() {
- return NgModel().FormControl().SpaceItem().OnModelChange()
+ return NgModel().FormControl().OnModelChange()
.Required().RequiredMessage()
.MinLength().MinLengthMessage()
.MaxLength().EmailMessage()
diff --git a/src/Util.Ui.NgZorro/Components/Base/FormControlContainerTagHelperBase.cs b/src/Util.Ui.NgZorro/Components/Base/FormControlContainerTagHelperBase.cs
index 67578d54c..28c6a657b 100644
--- a/src/Util.Ui.NgZorro/Components/Base/FormControlContainerTagHelperBase.cs
+++ b/src/Util.Ui.NgZorro/Components/Base/FormControlContainerTagHelperBase.cs
@@ -9,6 +9,10 @@ public abstract class FormControlContainerTagHelperBase : FormContainerTagHelper
///
public string LabelText { get; set; }
///
+ /// 标签文本,自动创建nz-form-label,nz-form-control,nz-form-item容器标签,并设置nz-form-label的内容
+ ///
+ public string BindLabelText { get; set; }
+ ///
/// 标签宽度
///
public string LabelWidth { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/Base/FormControlRenderBase.cs b/src/Util.Ui.NgZorro/Components/Base/FormControlRenderBase.cs
index c6eaedff8..1839e0622 100644
--- a/src/Util.Ui.NgZorro/Components/Base/FormControlRenderBase.cs
+++ b/src/Util.Ui.NgZorro/Components/Base/FormControlRenderBase.cs
@@ -8,7 +8,7 @@
using Util.Ui.NgZorro.Extensions;
using Util.Ui.Renders;
-namespace Util.Ui.NgZorro.Components.Base;
+namespace Util.Ui.NgZorro.Components.Base;
///
/// 表单控件渲染器基类
@@ -66,7 +66,7 @@ public void WriteTo( TextWriter writer, HtmlEncoder encoder ) {
var formLabel = GetFormLabel();
var formControl = GetFormControl();
formItem.AppendContent( formLabel ).AppendContent( formControl );
- formItem.WriteTo( writer,encoder );
+ formItem.WriteTo( writer, encoder );
}
///
@@ -79,7 +79,7 @@ protected virtual void Init() {
/// 设置控件Id
///
protected void SetControlId() {
- if( _shareConfig.AutoLabelFor != true )
+ if ( _shareConfig.AutoLabelFor != true )
return;
_config.SetAttribute( AngularConst.RawId, _shareConfig.ControlId );
}
@@ -103,6 +103,7 @@ protected virtual TagBuilder GetFormLabel() {
var builder = new FormLabelBuilder( GetFormLabelConfig() );
builder.Config();
SetLabelText( builder );
+ SetBindLabelText( builder );
return builder;
}
return new EmptyContainerTagBuilder();
@@ -121,6 +122,8 @@ protected Config GetFormLabelConfig() {
/// 设置表单标签文本
///
protected virtual void SetLabelText( FormLabelBuilder builder ) {
+ if ( _shareConfig.LabelText.IsEmpty() )
+ return;
var options = NgZorroOptionsService.GetOptions();
if ( options.EnableI18n ) {
builder.AppendContentByI18n( _shareConfig.LabelText );
@@ -129,16 +132,25 @@ protected virtual void SetLabelText( FormLabelBuilder builder ) {
builder.SetContent( _shareConfig.LabelText );
}
+ ///
+ /// 设置表单标签文本
+ ///
+ protected virtual void SetBindLabelText( FormLabelBuilder builder ) {
+ if ( _shareConfig.BindLabelText.IsEmpty() )
+ return;
+ builder.SetContent( "{{" + _shareConfig.BindLabelText + "}}" );
+ }
+
///
/// 获取表单控件
///
protected virtual TagBuilder GetFormControl() {
TagBuilder builder = new EmptyContainerTagBuilder();
- if( _config.Id == _shareConfig.Id && _shareConfig.AutoCreateFormControl == true )
+ if ( _config.Id == _shareConfig.Id && _shareConfig.AutoCreateFormControl == true )
builder = new FormControlBuilder( _config.CopyRemoveAttributes() );
builder.Config();
AppendControl( builder );
- if( IsAppendValidationTempalte() )
+ if ( IsAppendValidationTempalte() )
AppendValidationTempalte( builder );
return builder;
}
diff --git a/src/Util.Ui.NgZorro/Components/Base/FormControlTagHelperBase.cs b/src/Util.Ui.NgZorro/Components/Base/FormControlTagHelperBase.cs
index e87bc483e..023fd697e 100644
--- a/src/Util.Ui.NgZorro/Components/Base/FormControlTagHelperBase.cs
+++ b/src/Util.Ui.NgZorro/Components/Base/FormControlTagHelperBase.cs
@@ -42,4 +42,8 @@ public abstract class FormControlTagHelperBase : FormControlContainerTagHelperBa
/// [name],名称
///
public string BindName { get; set; }
+ ///
+ /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
+ ///
+ public bool SpaceItem { get; set; }
}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/Cascaders/CascaderTagHelper.cs b/src/Util.Ui.NgZorro/Components/Cascaders/CascaderTagHelper.cs
index 2cca05be6..a74a549c7 100644
--- a/src/Util.Ui.NgZorro/Components/Cascaders/CascaderTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/Cascaders/CascaderTagHelper.cs
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
-using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Base;
using Util.Ui.NgZorro.Components.Cascaders.Renders;
+using Util.Ui.NgZorro.Components.Selects.Helpers;
using Util.Ui.NgZorro.Enums;
using Util.Ui.Renders;
@@ -12,6 +12,10 @@ namespace Util.Ui.NgZorro.Components.Cascaders;
///
[HtmlTargetElement( "util-cascader" )]
public class CascaderTagHelper : FormControlTagHelperBase {
+ ///
+ /// 配置
+ ///
+ private Config _config;
///
/// [nzAllowClear],是否允许清除,默认值: true
///
@@ -177,10 +181,6 @@ public class CascaderTagHelper : FormControlTagHelperBase {
///
public string BindValueProperty { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// (nzClear),清除事件,清除值时触发
///
public string OnClear { get; set; }
@@ -193,9 +193,16 @@ public class CascaderTagHelper : FormControlTagHelperBase {
///
public string OnSelectionChange { get; set; }
+ ///
+ protected override void ProcessBefore( TagHelperContext context, TagHelperOutput output ) {
+ _config = new Config( context, output );
+ var service = new SelectService( _config );
+ service.Init();
+ }
+
///
protected override IRender GetRender( TagHelperContext context, TagHelperOutput output, TagHelperContent content ) {
- var config = new Config( context, output, content );
- return new CascaderRender( config );
+ _config.Content = content;
+ return new CascaderRender( _config );
}
}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/Cascaders/Renders/CascaderRender.cs b/src/Util.Ui.NgZorro/Components/Cascaders/Renders/CascaderRender.cs
index 453b027fb..217854a35 100644
--- a/src/Util.Ui.NgZorro/Components/Cascaders/Renders/CascaderRender.cs
+++ b/src/Util.Ui.NgZorro/Components/Cascaders/Renders/CascaderRender.cs
@@ -1,5 +1,4 @@
using Util.Ui.Builders;
-using Util.Ui.Configs;
using Util.Ui.Extensions;
using Util.Ui.NgZorro.Components.Base;
using Util.Ui.NgZorro.Components.Cascaders.Builders;
diff --git a/src/Util.Ui.NgZorro/Components/Checkboxes/CheckboxTagHelper.cs b/src/Util.Ui.NgZorro/Components/Checkboxes/CheckboxTagHelper.cs
index 9721be396..ff8c11a0d 100644
--- a/src/Util.Ui.NgZorro/Components/Checkboxes/CheckboxTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/Checkboxes/CheckboxTagHelper.cs
@@ -53,10 +53,6 @@ public class CheckboxTagHelper : FormControlTagHelperBase {
///
public string BindLabel { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// [nzChecked],是否选中
///
public string Checked { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/DatePickers/DatePickerTagHelper.cs b/src/Util.Ui.NgZorro/Components/DatePickers/DatePickerTagHelper.cs
index eb5b78dcf..448f24d3d 100644
--- a/src/Util.Ui.NgZorro/Components/DatePickers/DatePickerTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/DatePickers/DatePickerTagHelper.cs
@@ -187,10 +187,6 @@ public class DatePickerTagHelper : FormControlTagHelperBase {
///
public string BindShowNow { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// (nzOnOpenChange),弹出关闭日历事件
///
public string OnOpenChange { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/DatePickers/RangePickerTagHelper.cs b/src/Util.Ui.NgZorro/Components/DatePickers/RangePickerTagHelper.cs
index 15ab35973..3a928ff24 100644
--- a/src/Util.Ui.NgZorro/Components/DatePickers/RangePickerTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/DatePickers/RangePickerTagHelper.cs
@@ -177,10 +177,6 @@ public class RangePickerTagHelper : FormControlTagHelperBase {
///
public string BindShowTime { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// [(beginDate)],扩展属性, 双向绑定起始日期
///
public string BeginDate { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/Forms/Builders/FormItemBuilder.cs b/src/Util.Ui.NgZorro/Components/Forms/Builders/FormItemBuilder.cs
index 23c3f8313..52ae95f7e 100644
--- a/src/Util.Ui.NgZorro/Components/Forms/Builders/FormItemBuilder.cs
+++ b/src/Util.Ui.NgZorro/Components/Forms/Builders/FormItemBuilder.cs
@@ -1,10 +1,10 @@
using Util.Ui.Angular.Extensions;
-using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Base;
using Util.Ui.NgZorro.Components.Forms.Configs;
using Util.Ui.NgZorro.Components.Tables.Configs;
+using Util.Ui.NgZorro.Extensions;
-namespace Util.Ui.NgZorro.Components.Forms.Builders;
+namespace Util.Ui.NgZorro.Components.Forms.Builders;
///
/// 表单项标签生成器
@@ -61,6 +61,14 @@ public override FormItemBuilder Justify() {
return base.Justify();
}
+ ///
+ /// 配置间距项
+ ///
+ public FormItemBuilder SpaceItem() {
+ this.SpaceItem( _shareConfig.SpaceItem );
+ return this;
+ }
+
///
/// ngIf
///
@@ -75,8 +83,7 @@ public FormItemBuilder AngularIf() {
///
public override void Config() {
base.ConfigBase( _config );
- AngularIf()
- .ConfigRow().TableEdit();
+ SpaceItem().AngularIf().ConfigRow().TableEdit();
}
///
diff --git a/src/Util.Ui.NgZorro/Components/Forms/Configs/FormItemShareConfig.cs b/src/Util.Ui.NgZorro/Components/Forms/Configs/FormItemShareConfig.cs
index 312ac72e1..acc173500 100644
--- a/src/Util.Ui.NgZorro/Components/Forms/Configs/FormItemShareConfig.cs
+++ b/src/Util.Ui.NgZorro/Components/Forms/Configs/FormItemShareConfig.cs
@@ -29,6 +29,14 @@ public class FormItemShareConfig : FormShareConfig {
///
public string LabelText { get; set; }
///
+ /// 标签文本
+ ///
+ public string BindLabelText { get; set; }
+ ///
+ /// 是否间距项
+ ///
+ public bool SpaceItem { get; set; }
+ ///
/// 是否存在额外提示
///
public bool HasExtra { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/Forms/Helpers/FormItemShareService.cs b/src/Util.Ui.NgZorro/Components/Forms/Helpers/FormItemShareService.cs
index 9f60057f7..cabc3e89f 100644
--- a/src/Util.Ui.NgZorro/Components/Forms/Helpers/FormItemShareService.cs
+++ b/src/Util.Ui.NgZorro/Components/Forms/Helpers/FormItemShareService.cs
@@ -1,9 +1,8 @@
using Util.Ui.Angular.Configs;
-using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Forms.Configs;
using Util.Ui.NgZorro.Components.Tables.Configs;
-namespace Util.Ui.NgZorro.Components.Forms.Helpers;
+namespace Util.Ui.NgZorro.Components.Forms.Helpers;
///
/// 表单项共享服务
@@ -72,8 +71,10 @@ public void Init() {
InitFormItemShareConfig();
MapToItemShareConfig();
InitControlId();
+ SetSpaceItem();
SetShowLabel();
SetLabelText();
+ SetBindLabelText();
SetLabelWidth();
SetExtra();
SetSuccessTip();
@@ -139,16 +140,23 @@ private FormShareConfig GetFormShareConfig() {
return _config.GetValueFromItems() ?? new FormShareConfig();
}
+ ///
+ /// 设置间距项
+ ///
+ private void SetSpaceItem() {
+ _shareConfig.SpaceItem = _config.GetValue( UiConst.SpaceItem );
+ }
+
///
/// 设置是否显示标签
///
private void SetShowLabel() {
- if( _shareConfig.ShowLabel == false ) {
+ if ( _shareConfig.ShowLabel == false ) {
_shareConfig.AutoCreateFormLabel = false;
return;
}
var value = _config.GetValueFromAttributes( UiConst.ShowLabel );
- if( value == false )
+ if ( value == false )
_shareConfig.AutoCreateFormLabel = false;
}
@@ -163,6 +171,17 @@ private void SetLabelText() {
AutoCreateFormLabel( true );
}
+ ///
+ /// 设置表单标签文本
+ ///
+ private void SetBindLabelText() {
+ var value = _config.GetValueFromAttributes( AngularConst.BindLabelText );
+ if ( string.IsNullOrWhiteSpace( value ) )
+ return;
+ _shareConfig.BindLabelText = value;
+ AutoCreateFormLabel( true );
+ }
+
///
/// 设置表单标签宽度
///
@@ -229,7 +248,9 @@ private void AutoCreateFormContainer() {
/// 是否自动创建表单控件容器
///
private bool IsAutoCreateFormContainer() {
- if ( string.IsNullOrWhiteSpace( _shareConfig.LabelText ) == false )
+ if ( _shareConfig.LabelText.IsEmpty() == false )
+ return true;
+ if ( _shareConfig.BindLabelText.IsEmpty() == false )
return true;
if ( _shareConfig.Align != null )
return true;
diff --git a/src/Util.Ui.NgZorro/Components/Forms/Helpers/ValidationService.cs b/src/Util.Ui.NgZorro/Components/Forms/Helpers/ValidationService.cs
index dfa8a24b6..5e438f908 100644
--- a/src/Util.Ui.NgZorro/Components/Forms/Helpers/ValidationService.cs
+++ b/src/Util.Ui.NgZorro/Components/Forms/Helpers/ValidationService.cs
@@ -1,5 +1,4 @@
using Util.Ui.Angular.Configs;
-using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Forms.Configs;
using Util.Ui.NgZorro.Enums;
diff --git a/src/Util.Ui.NgZorro/Components/Forms/Renders/FormItemRender.cs b/src/Util.Ui.NgZorro/Components/Forms/Renders/FormItemRender.cs
index 7a9280e45..cf5de4209 100644
--- a/src/Util.Ui.NgZorro/Components/Forms/Renders/FormItemRender.cs
+++ b/src/Util.Ui.NgZorro/Components/Forms/Renders/FormItemRender.cs
@@ -4,7 +4,7 @@
using Util.Ui.NgZorro.Components.Forms.Configs;
using Util.Ui.Renders;
-namespace Util.Ui.NgZorro.Components.Forms.Renders;
+namespace Util.Ui.NgZorro.Components.Forms.Renders;
///
/// 表单项渲染器
@@ -56,7 +56,10 @@ private TagBuilder GetFormLabel() {
_shareConfig.AutoCreateFormLabel = false;
var builder = new FormLabelBuilder( _config );
builder.Config();
- builder.SetContent( _shareConfig.LabelText );
+ if ( _shareConfig.LabelText.IsEmpty() == false )
+ builder.SetContent( _shareConfig.LabelText );
+ if ( _shareConfig.BindLabelText.IsEmpty() == false )
+ builder.SetContent( "{{" + _shareConfig.LabelText + "}}" );
return builder;
}
return new EmptyContainerTagBuilder();
diff --git a/src/Util.Ui.NgZorro/Components/HashCodes/Builders/HashCodeBuilder.cs b/src/Util.Ui.NgZorro/Components/HashCodes/Builders/HashCodeBuilder.cs
new file mode 100644
index 000000000..9451d1dee
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/HashCodes/Builders/HashCodeBuilder.cs
@@ -0,0 +1,84 @@
+using Util.Ui.Angular.Builders;
+using Util.Ui.Angular.Configs;
+using Util.Ui.NgZorro.Enums;
+
+namespace Util.Ui.NgZorro.Components.HashCodes.Builders;
+
+///
+/// 哈希码标签生成器
+///
+public class HashCodeBuilder : AngularTagBuilder {
+ ///
+ /// 配置
+ ///
+ private readonly Config _config;
+
+ ///
+ /// 初始化哈希码标签生成器
+ ///
+ /// 配置
+ public HashCodeBuilder( Config config ) : base( config, "nz-hash-code" ) {
+ _config = config;
+ }
+
+ ///
+ /// 配置值
+ ///
+ public HashCodeBuilder Value() {
+ AttributeIfNotEmpty( "nzValue", _config.GetValue( UiConst.Value ) );
+ AttributeIfNotEmpty( "[nzValue]", _config.GetValue( AngularConst.BindValue ) );
+ return this;
+ }
+
+ ///
+ /// 配置标题
+ ///
+ public HashCodeBuilder Title() {
+ AttributeIfNotEmpty( "nzTitle", _config.GetValue( UiConst.Title ) );
+ AttributeIfNotEmpty( "[nzTitle]", _config.GetValue( AngularConst.BindTitle ) );
+ return this;
+ }
+
+ ///
+ /// 配置标志
+ ///
+ public HashCodeBuilder Logo() {
+ AttributeIfNotEmpty( "nzLogo", _config.GetValue( UiConst.Logo ) );
+ AttributeIfNotEmpty( "[nzLogo]", _config.GetValue( AngularConst.BindLogo ) );
+ return this;
+ }
+
+ ///
+ /// 配置展示模式
+ ///
+ public HashCodeBuilder Mode() {
+ AttributeIfNotEmpty( "nzMode", _config.GetValue( UiConst.Mode )?.Description() );
+ AttributeIfNotEmpty( "[nzMode]", _config.GetValue( AngularConst.BindMode ) );
+ return this;
+ }
+
+ ///
+ /// 配置样式
+ ///
+ public HashCodeBuilder Type() {
+ AttributeIfNotEmpty( "nzType", _config.GetValue( UiConst.Type )?.Description() );
+ AttributeIfNotEmpty( "[nzType]", _config.GetValue( AngularConst.BindType ) );
+ return this;
+ }
+
+ ///
+ /// 配置事件
+ ///
+ public HashCodeBuilder Events() {
+ AttributeIfNotEmpty( "(nzOnCopy)", _config.GetValue( UiConst.OnCopy ) );
+ return this;
+ }
+
+ ///
+ /// 配置
+ ///
+ public override void Config() {
+ base.Config();
+ Value().Title().Logo().Mode().Type().Events();
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/HashCodes/HashCodeTagHelper.cs b/src/Util.Ui.NgZorro/Components/HashCodes/HashCodeTagHelper.cs
new file mode 100644
index 000000000..0340e5098
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/HashCodes/HashCodeTagHelper.cs
@@ -0,0 +1,64 @@
+using Microsoft.AspNetCore.Razor.TagHelpers;
+using Util.Ui.Angular.TagHelpers;
+using Util.Ui.NgZorro.Components.HashCodes.Renders;
+using Util.Ui.NgZorro.Enums;
+using Util.Ui.Renders;
+
+namespace Util.Ui.NgZorro.Components.HashCodes;
+
+///
+/// 哈希码,生成的标签为<nz-hash-code></nz-hash-code>
+///
+[HtmlTargetElement( "util-hash-code" )]
+public class HashCodeTagHelper : AngularTagHelperBase {
+ ///
+ /// nzValue,值
+ ///
+ public string Value { get; set; }
+ ///
+ /// [nzValue],值
+ ///
+ public string BindValue { get; set; }
+ ///
+ /// nzTitle,标题, 默认值: HashCode
+ ///
+ public string Title { get; set; }
+ ///
+ /// [nzTitle],标题, 默认值: HashCode
+ ///
+ public string BindTitle { get; set; }
+ ///
+ /// nzLogo,设置右上角的标志, 类型: TemplateRef<void> | string
+ ///
+ public string Logo { get; set; }
+ ///
+ /// [nzLogo],设置右上角的标志, 类型: TemplateRef<void> | string
+ ///
+ public string BindLogo { get; set; }
+ ///
+ /// nzMode,展示模式, 可选值: single | double | strip | rect , 默认值: double
+ ///
+ public HashCodeMode Mode { get; set; }
+ ///
+ /// [nzMode],展示模式, 可选值: single | double | strip | rect , 默认值: double
+ ///
+ public string BindMode { get; set; }
+ ///
+ /// nzType,样式, 可选值: defalut | primary , 默认值: primary
+ ///
+ public HashCodeType Type { get; set; }
+ ///
+ /// [nzType],样式, 可选值: defalut | primary , 默认值: primary
+ ///
+ public string BindType { get; set; }
+ ///
+ /// (nzOnCopy), 复制事件,类型: EventEmitter<string>
+ ///
+ public string OnCopy { get; set; }
+
+ ///
+ protected override IRender GetRender( TagHelperContext context, TagHelperOutput output, TagHelperContent content ) {
+ var config = new Config( context, output, content );
+ return new HashCodeRender( config );
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/HashCodes/Renders/HashCodeRender.cs b/src/Util.Ui.NgZorro/Components/HashCodes/Renders/HashCodeRender.cs
new file mode 100644
index 000000000..e25adafac
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/HashCodes/Renders/HashCodeRender.cs
@@ -0,0 +1,37 @@
+using Util.Ui.Builders;
+using Util.Ui.NgZorro.Components.HashCodes.Builders;
+using Util.Ui.Renders;
+
+namespace Util.Ui.NgZorro.Components.HashCodes.Renders;
+
+///
+/// 哈希码渲染器
+///
+public class HashCodeRender : RenderBase {
+ ///
+ /// 配置
+ ///
+ private readonly Config _config;
+
+ ///
+ /// 初始化哈希码渲染器
+ ///
+ /// 配置
+ public HashCodeRender( Config config ) {
+ _config = config;
+ }
+
+ ///
+ /// 获取标签生成器
+ ///
+ protected override TagBuilder GetTagBuilder() {
+ var builder = new HashCodeBuilder( _config );
+ builder.Config();
+ return builder;
+ }
+
+ ///
+ public override IHtmlContent Clone() {
+ return new HashCodeRender( _config.Copy() );
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/InputNumbers/InputNumberTagHelper.cs b/src/Util.Ui.NgZorro/Components/InputNumbers/InputNumberTagHelper.cs
index 9f933b5b1..aaacdd651 100644
--- a/src/Util.Ui.NgZorro/Components/InputNumbers/InputNumberTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/InputNumbers/InputNumberTagHelper.cs
@@ -121,10 +121,6 @@ public class InputNumberTagHelper : FormControlTagHelperBase {
///
public string BindPlaceholder { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// (nzFocus),获得焦点事件
///
public string OnFocus { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/Inputs/InputTagHelper.cs b/src/Util.Ui.NgZorro/Components/Inputs/InputTagHelper.cs
index 4935cf955..6625ea63d 100644
--- a/src/Util.Ui.NgZorro/Components/Inputs/InputTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/Inputs/InputTagHelper.cs
@@ -185,10 +185,6 @@ public class InputTagHelper : FormControlTagHelperBase {
///
public bool AutocompleteSearchKeyword { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// (input),输入事件
///
public string OnInput { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/Inputs/TextareaTagHelper.cs b/src/Util.Ui.NgZorro/Components/Inputs/TextareaTagHelper.cs
index 13da40d41..5b2aa389f 100644
--- a/src/Util.Ui.NgZorro/Components/Inputs/TextareaTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/Inputs/TextareaTagHelper.cs
@@ -114,10 +114,6 @@ public class TextareaTagHelper : FormControlTagHelperBase {
///
public bool AllowClear { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// (input),输入事件
///
public string OnInput { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/QrCodes/Builders/QrCodeBuilder.cs b/src/Util.Ui.NgZorro/Components/QrCodes/Builders/QrCodeBuilder.cs
new file mode 100644
index 000000000..eb445fcf9
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/QrCodes/Builders/QrCodeBuilder.cs
@@ -0,0 +1,130 @@
+using Util.Ui.Angular.Builders;
+using Util.Ui.Angular.Configs;
+using Util.Ui.NgZorro.Enums;
+
+namespace Util.Ui.NgZorro.Components.QrCodes.Builders;
+
+///
+/// 二维码标签生成器
+///
+public class QrCodeBuilder : AngularTagBuilder {
+ ///
+ /// 配置
+ ///
+ private readonly Config _config;
+
+ ///
+ /// 初始化二维码标签生成器
+ ///
+ /// 配置
+ public QrCodeBuilder( Config config ) : base( config, "nz-qrcode" ) {
+ _config = config;
+ }
+
+ ///
+ /// 配置值
+ ///
+ public QrCodeBuilder Value() {
+ AttributeIfNotEmpty( "nzValue", _config.GetValue( UiConst.Value ) );
+ AttributeIfNotEmpty( "[nzValue]", _config.GetValue( AngularConst.BindValue ) );
+ return this;
+ }
+
+ ///
+ /// 配置二维码颜色
+ ///
+ public QrCodeBuilder Color() {
+ AttributeIfNotEmpty( "nzColor", _config.GetValue( UiConst.Color ) );
+ AttributeIfNotEmpty( "[nzColor]", _config.GetValue( AngularConst.BindColor ) );
+ return this;
+ }
+
+ ///
+ /// 配置背景色
+ ///
+ public QrCodeBuilder BgColor() {
+ AttributeIfNotEmpty( "nzBgColor", _config.GetValue( UiConst.BgColor ) );
+ AttributeIfNotEmpty( "[nzBgColor]", _config.GetValue( AngularConst.BindBgColor ) );
+ return this;
+ }
+
+ ///
+ /// 配置尺寸
+ ///
+ public QrCodeBuilder Size() {
+ AttributeIfNotEmpty( "nzSize", _config.GetValue( UiConst.Size ) );
+ AttributeIfNotEmpty( "[nzSize]", _config.GetValue( AngularConst.BindSize ) );
+ return this;
+ }
+
+ ///
+ /// 配置填充
+ ///
+ public QrCodeBuilder Padding() {
+ AttributeIfNotEmpty( "[nzPadding]", _config.GetValue( UiConst.Padding ) );
+ return this;
+ }
+
+ ///
+ /// 配置图标地址
+ ///
+ public QrCodeBuilder Icon() {
+ AttributeIfNotEmpty( "nzIcon", _config.GetValue( UiConst.Icon ) );
+ AttributeIfNotEmpty( "[nzIcon]", _config.GetValue( AngularConst.BindIcon ) );
+ return this;
+ }
+
+ ///
+ /// 配置图标尺寸
+ ///
+ public QrCodeBuilder IconSize() {
+ AttributeIfNotEmpty( "nzIconSize", _config.GetValue( UiConst.IconSize ) );
+ AttributeIfNotEmpty( "[nzIconSize]", _config.GetValue( AngularConst.BindIconSize ) );
+ return this;
+ }
+
+ ///
+ /// 配置边框
+ ///
+ public QrCodeBuilder Bordered() {
+ AttributeIfNotEmpty( "[nzBordered]", _config.GetBoolValue( UiConst.Bordered ) );
+ AttributeIfNotEmpty( "[nzBordered]", _config.GetValue( AngularConst.BindBordered ) );
+ return this;
+ }
+
+ ///
+ /// 配置状态
+ ///
+ public QrCodeBuilder Status() {
+ AttributeIfNotEmpty( "nzStatus", _config.GetValue( UiConst.Status ).Description() );
+ AttributeIfNotEmpty( "[nzStatus]", _config.GetValue( AngularConst.BindStatus ) );
+ return this;
+ }
+
+ ///
+ /// 配置容错级别
+ ///
+ public QrCodeBuilder Level() {
+ AttributeIfNotEmpty( "nzLevel", _config.GetValue( UiConst.Level ).Description() );
+ AttributeIfNotEmpty( "[nzLevel]", _config.GetValue( AngularConst.BindLevel ) );
+ return this;
+ }
+
+ ///
+ /// 配置事件
+ ///
+ public QrCodeBuilder Events() {
+ AttributeIfNotEmpty( "(nzRefresh)", _config.GetValue( UiConst.OnRefresh ) );
+ return this;
+ }
+
+ ///
+ /// 配置
+ ///
+ public override void Config() {
+ base.Config();
+ Value().Color().BgColor().Size().Padding().Icon().IconSize()
+ .Bordered().Status().Level()
+ .Events();
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/QrCodes/QrCodeTagHelper.cs b/src/Util.Ui.NgZorro/Components/QrCodes/QrCodeTagHelper.cs
new file mode 100644
index 000000000..d770302c4
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/QrCodes/QrCodeTagHelper.cs
@@ -0,0 +1,100 @@
+using Microsoft.AspNetCore.Razor.TagHelpers;
+using Util.Ui.Angular.TagHelpers;
+using Util.Ui.NgZorro.Components.QrCodes.Renders;
+using Util.Ui.NgZorro.Enums;
+using Util.Ui.Renders;
+
+namespace Util.Ui.NgZorro.Components.QrCodes;
+
+///
+/// 二维码,生成的标签为<nz-qrcode></nz-qrcode>
+///
+[HtmlTargetElement( "util-qrcode" )]
+public class QrCodeTagHelper : AngularTagHelperBase {
+ ///
+ /// nzValue,值
+ ///
+ public string Value { get; set; }
+ ///
+ /// [nzValue],值
+ ///
+ public string BindValue { get; set; }
+ ///
+ /// nzColor,二维码颜色, 默认值: #000
+ ///
+ public string Color { get; set; }
+ ///
+ /// [nzColor],二维码颜色, 默认值: #000
+ ///
+ public string BindColor { get; set; }
+ ///
+ /// nzBgColor,背景色, 默认值: #FFFFFF
+ ///
+ public string BgColor { get; set; }
+ ///
+ /// [nzBgColor],背景色, 默认值: #FFFFFF
+ ///
+ public string BindBgColor { get; set; }
+ ///
+ /// nzSize,尺寸, 默认值: 160
+ ///
+ public double Size { get; set; }
+ ///
+ /// [nzSize],尺寸, 默认值: 160
+ ///
+ public string BindSize { get; set; }
+ ///
+ /// [nzPadding], 填充, 类型: number | number[] , 默认值: 0
+ ///
+ public string Padding { get; set; }
+ ///
+ /// nzIcon,图标地址
+ ///
+ public string Icon { get; set; }
+ ///
+ /// [nzIcon],图标地址
+ ///
+ public string BindIcon { get; set; }
+ ///
+ /// nzIconSize,图标尺寸, 默认值: 40
+ ///
+ public double IconSize { get; set; }
+ ///
+ /// [nzIconSize],图标尺寸, 默认值: 40
+ ///
+ public string BindIconSize { get; set; }
+ ///
+ /// [nzBordered],是否显示边框, 默认值: true
+ ///
+ public bool Bordered { get; set; }
+ ///
+ /// [nzBordered],是否显示边框, 默认值: true
+ ///
+ public string BindBordered { get; set; }
+ ///
+ /// nzStatus,状态, 可选值: 'active'|'expired' |'loading' , 默认值: 'active'
+ ///
+ public QrCodeStatus Status { get; set; }
+ ///
+ /// [nzStatus],状态, 可选值: 'active'|'expired' |'loading' , 默认值: 'active'
+ ///
+ public string BindStatus { get; set; }
+ ///
+ /// nzLevel,容错级别, 可选值: 'L'|'M'|'Q'|'H', 默认值: 'M'
+ ///
+ public QrCodeCorrectionLevel Level { get; set; }
+ ///
+ /// [nzLevel],容错级别, 可选值: 'L'|'M'|'Q'|'H', 默认值: 'M'
+ ///
+ public string BindLevel { get; set; }
+ ///
+ /// (nzRefresh), "点击刷新"链接单击事件,类型: EventEmitter<string>
+ ///
+ public string OnRefresh { get; set; }
+
+ ///
+ protected override IRender GetRender( TagHelperContext context, TagHelperOutput output, TagHelperContent content ) {
+ var config = new Config( context, output, content );
+ return new QrCodeRender( config );
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/QrCodes/Renders/QrCodeRender.cs b/src/Util.Ui.NgZorro/Components/QrCodes/Renders/QrCodeRender.cs
new file mode 100644
index 000000000..e2d0fdead
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/QrCodes/Renders/QrCodeRender.cs
@@ -0,0 +1,37 @@
+using Util.Ui.Builders;
+using Util.Ui.NgZorro.Components.QrCodes.Builders;
+using Util.Ui.Renders;
+
+namespace Util.Ui.NgZorro.Components.QrCodes.Renders;
+
+///
+/// 二维码渲染器
+///
+public class QrCodeRender : RenderBase {
+ ///
+ /// 配置
+ ///
+ private readonly Config _config;
+
+ ///
+ /// 初始化二维码渲染器
+ ///
+ /// 配置
+ public QrCodeRender( Config config ) {
+ _config = config;
+ }
+
+ ///
+ /// 获取标签生成器
+ ///
+ protected override TagBuilder GetTagBuilder() {
+ var builder = new QrCodeBuilder( _config );
+ builder.Config();
+ return builder;
+ }
+
+ ///
+ public override IHtmlContent Clone() {
+ return new QrCodeRender( _config.Copy() );
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/Radios/Builders/RadioBuilder.cs b/src/Util.Ui.NgZorro/Components/Radios/Builders/RadioBuilder.cs
index 0ce81862a..60da1efa3 100644
--- a/src/Util.Ui.NgZorro/Components/Radios/Builders/RadioBuilder.cs
+++ b/src/Util.Ui.NgZorro/Components/Radios/Builders/RadioBuilder.cs
@@ -100,7 +100,7 @@ public RadioBuilder Events() {
///
public override void Config() {
base.ConfigBase( _config );
- NgModel().FormControl().SpaceItem().OnModelChange()
+ NgModel().FormControl().OnModelChange()
.TableEdit()
.Name().AutoFocus().Disabled().Value()
.Label().Events();
diff --git a/src/Util.Ui.NgZorro/Components/Radios/RadioGroupTagHelper.cs b/src/Util.Ui.NgZorro/Components/Radios/RadioGroupTagHelper.cs
index 0df05837c..b79aacf15 100644
--- a/src/Util.Ui.NgZorro/Components/Radios/RadioGroupTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/Radios/RadioGroupTagHelper.cs
@@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
-using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Base;
using Util.Ui.NgZorro.Components.Radios.Helpers;
using Util.Ui.NgZorro.Components.Radios.Renders;
diff --git a/src/Util.Ui.NgZorro/Components/Radios/RadioTagHelper.cs b/src/Util.Ui.NgZorro/Components/Radios/RadioTagHelper.cs
index ea6ac4c89..6bcf5d5c2 100644
--- a/src/Util.Ui.NgZorro/Components/Radios/RadioTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/Radios/RadioTagHelper.cs
@@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
-using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Base;
using Util.Ui.NgZorro.Components.Radios.Helpers;
using Util.Ui.NgZorro.Components.Radios.Renders;
diff --git a/src/Util.Ui.NgZorro/Components/Selects/SelectTagHelper.cs b/src/Util.Ui.NgZorro/Components/Selects/SelectTagHelper.cs
index 403959018..87e87b476 100644
--- a/src/Util.Ui.NgZorro/Components/Selects/SelectTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/Selects/SelectTagHelper.cs
@@ -289,10 +289,6 @@ public class SelectTagHelper : FormControlTagHelperBase {
///
public string BindOptionOverflowSize { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// [nzDropdownRender],设置下拉扩展模板,类型: TemplateRef
///
public string DropdownRender { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/Switches/SwitchTagHelper.cs b/src/Util.Ui.NgZorro/Components/Switches/SwitchTagHelper.cs
index 54e76ab37..fa2aeb96f 100644
--- a/src/Util.Ui.NgZorro/Components/Switches/SwitchTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/Switches/SwitchTagHelper.cs
@@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
-using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Base;
using Util.Ui.NgZorro.Components.Checkboxes.Helpers;
using Util.Ui.NgZorro.Components.Switches.Renders;
@@ -62,10 +61,6 @@ public class SwitchTagHelper : FormControlTagHelperBase {
///
public string BindControl { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// (click),单击事件
///
public string OnClick { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/TimePickers/TimePickerTagHelper.cs b/src/Util.Ui.NgZorro/Components/TimePickers/TimePickerTagHelper.cs
index 93b32576d..677374869 100644
--- a/src/Util.Ui.NgZorro/Components/TimePickers/TimePickerTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/TimePickers/TimePickerTagHelper.cs
@@ -158,10 +158,6 @@ public class TimePickerTagHelper : FormControlTagHelperBase {
///
public string BindSuffixIcon { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// (nzOpenChange),打开关闭面板事件
///
public string OnOpenChange { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/TreeSelects/TreeSelectTagHelper.cs b/src/Util.Ui.NgZorro/Components/TreeSelects/TreeSelectTagHelper.cs
index aa8858841..307430db9 100644
--- a/src/Util.Ui.NgZorro/Components/TreeSelects/TreeSelectTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/TreeSelects/TreeSelectTagHelper.cs
@@ -274,10 +274,6 @@ public class TreeSelectTagHelper : FormControlTagHelperBase {
///
public string BindVirtualMinBufferPx { get; set; }
///
- /// *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
- ///
- public bool SpaceItem { get; set; }
- ///
/// (nzExpandChange),展开收缩节点事件,类型: EventEmitter<NzFormatEmitEvent>
///
public string OnExpandChange { get; set; }
diff --git a/src/Util.Ui.NgZorro/Components/Upload/Builders/UploadBuilder.cs b/src/Util.Ui.NgZorro/Components/Upload/Builders/UploadBuilder.cs
index ea58388fe..7d333a4a5 100644
--- a/src/Util.Ui.NgZorro/Components/Upload/Builders/UploadBuilder.cs
+++ b/src/Util.Ui.NgZorro/Components/Upload/Builders/UploadBuilder.cs
@@ -293,14 +293,6 @@ public UploadBuilder FileListRender() {
return this;
}
- ///
- /// 配置间距项
- ///
- public UploadBuilder SpaceItem() {
- this.SpaceItem( _config );
- return this;
- }
-
///
/// 配置事件
///
@@ -330,7 +322,7 @@ public override void Config() {
.ShowUploadList().ShowButton().WithCredentials().OpenFileDialogOnClick()
.Preview().PreviewFile().PreviewIsImage()
.Remove().Download().TransformFile()
- .IconRender().FileListRender().SpaceItem()
+ .IconRender().FileListRender()
.Events();
Model();
AddButton();
diff --git a/src/Util.Ui.NgZorro/Components/WaterMarks/Builders/WaterMarkBuilder.cs b/src/Util.Ui.NgZorro/Components/WaterMarks/Builders/WaterMarkBuilder.cs
new file mode 100644
index 000000000..237c202d4
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/WaterMarks/Builders/WaterMarkBuilder.cs
@@ -0,0 +1,130 @@
+using Util.Ui.Angular.Builders;
+using Util.Ui.Angular.Configs;
+using Util.Ui.NgZorro.Components.WaterMarks.Helpers;
+
+namespace Util.Ui.NgZorro.Components.WaterMarks.Builders;
+
+///
+/// 水印标签生成器
+///
+public class WaterMarkBuilder : AngularTagBuilder {
+ ///
+ /// 配置
+ ///
+ private readonly Config _config;
+
+ ///
+ /// 初始化水印标签生成器
+ ///
+ /// 配置
+ public WaterMarkBuilder( Config config ) : base( config, "nz-water-mark" ) {
+ _config = config;
+ }
+
+ ///
+ /// 配置水印文字内容
+ ///
+ public WaterMarkBuilder Content() {
+ AttributeIfNotEmpty( "nzContent", _config.GetValue( UiConst.Content ) );
+ AttributeIfNotEmpty( "[nzContent]", _config.GetValue( AngularConst.BindContent ) );
+ return this;
+ }
+
+ ///
+ /// 配置水印宽度
+ ///
+ public WaterMarkBuilder Width() {
+ AttributeIfNotEmpty( "[nzWidth]", _config.GetValue( UiConst.Width ) );
+ AttributeIfNotEmpty( "[nzWidth]", _config.GetValue( AngularConst.BindWidth ) );
+ return this;
+ }
+
+ ///
+ /// 配置水印高度
+ ///
+ public WaterMarkBuilder Height() {
+ AttributeIfNotEmpty( "[nzHeight]", _config.GetValue( UiConst.Height ) );
+ AttributeIfNotEmpty( "[nzHeight]", _config.GetValue( AngularConst.BindHeight ) );
+ return this;
+ }
+
+ ///
+ /// 配置旋转角度
+ ///
+ public WaterMarkBuilder Rotate() {
+ AttributeIfNotEmpty( "[nzRotate]", _config.GetValue( UiConst.Rotate ) );
+ AttributeIfNotEmpty( "[nzRotate]", _config.GetValue( AngularConst.BindRotate ) );
+ return this;
+ }
+
+ ///
+ /// 配置z-index
+ ///
+ public WaterMarkBuilder ZIndex() {
+ AttributeIfNotEmpty( "[nzZIndex]", _config.GetValue( UiConst.ZIndex ) );
+ AttributeIfNotEmpty( "[nzZIndex]", _config.GetValue( AngularConst.BindZIndex ) );
+ return this;
+ }
+
+ ///
+ /// 配置水印图片地址
+ ///
+ public WaterMarkBuilder Image() {
+ AttributeIfNotEmpty( "nzImage", _config.GetValue( UiConst.Image ) );
+ AttributeIfNotEmpty( "[nzImage]", _config.GetValue( AngularConst.BindImage ) );
+ return this;
+ }
+
+ ///
+ /// 配置文字样式
+ ///
+ public WaterMarkBuilder Font() {
+ AttributeIfNotEmpty( "[nzFont]", GetFont() );
+ return this;
+ }
+
+ ///
+ /// 获取字体
+ ///
+ private string GetFont() {
+ var result = _config.GetValue( UiConst.Font );
+ if ( result.IsEmpty() == false )
+ return result;
+ var fontType = new FontType {
+ Color = _config.GetValue( UiConst.FontColor ),
+ FontSize = _config.GetValue( UiConst.FontSize ),
+ FontWeight = _config.GetValue( UiConst.FontWeight ),
+ FontFamily = _config.GetValue( UiConst.FontFamily ),
+ FontStyle = _config.GetValue( UiConst.FontStyle )
+ };
+ result = Util.Helpers.Json.ToJson( fontType, new JsonOptions { ToSingleQuotes = true } );
+ if ( result == "{}" )
+ result = null;
+ return result;
+ }
+
+ ///
+ /// 配置间距
+ ///
+ public WaterMarkBuilder Gap() {
+ AttributeIfNotEmpty( "[nzGap]", _config.GetValue( UiConst.Gap ) );
+ return this;
+ }
+
+ ///
+ /// 配置偏移量
+ ///
+ public WaterMarkBuilder Offset() {
+ AttributeIfNotEmpty( "[nzOffset]", _config.GetValue( UiConst.Offset ) );
+ return this;
+ }
+
+ ///
+ /// 配置
+ ///
+ public override void Config() {
+ base.Config();
+ Content().Width().Height().Rotate()
+ .ZIndex().Image().Font().Gap().Offset();
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/WaterMarks/Helpers/FontType.cs b/src/Util.Ui.NgZorro/Components/WaterMarks/Helpers/FontType.cs
new file mode 100644
index 000000000..180597449
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/WaterMarks/Helpers/FontType.cs
@@ -0,0 +1,32 @@
+namespace Util.Ui.NgZorro.Components.WaterMarks.Helpers;
+
+///
+/// 字体类型
+///
+internal class FontType {
+ ///
+ /// 字体颜色
+ ///
+ [JsonPropertyName("color")]
+ public string Color { get; set; }
+ ///
+ /// 字体大小
+ ///
+ [JsonPropertyName( "fontSize" )]
+ public double? FontSize { get; set; }
+ ///
+ /// 字体粗细
+ ///
+ [JsonPropertyName( "fontWeight" )]
+ public string FontWeight { get; set; }
+ ///
+ /// 字体类型
+ ///
+ [JsonPropertyName( "fontFamily" )]
+ public string FontFamily { get; set; }
+ ///
+ /// 字体样式
+ ///
+ [JsonPropertyName( "fontStyle" )]
+ public string FontStyle { get; set; }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/WaterMarks/Renders/WaterMarkRender.cs b/src/Util.Ui.NgZorro/Components/WaterMarks/Renders/WaterMarkRender.cs
new file mode 100644
index 000000000..3a08282c9
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/WaterMarks/Renders/WaterMarkRender.cs
@@ -0,0 +1,37 @@
+using Util.Ui.Builders;
+using Util.Ui.NgZorro.Components.WaterMarks.Builders;
+using Util.Ui.Renders;
+
+namespace Util.Ui.NgZorro.Components.WaterMarks.Renders;
+
+///
+/// 水印渲染器
+///
+public class WaterMarkRender : RenderBase {
+ ///
+ /// 配置
+ ///
+ private readonly Config _config;
+
+ ///
+ /// 初始化水印渲染器
+ ///
+ /// 配置
+ public WaterMarkRender( Config config ) {
+ _config = config;
+ }
+
+ ///
+ /// 获取标签生成器
+ ///
+ protected override TagBuilder GetTagBuilder() {
+ var builder = new WaterMarkBuilder( _config );
+ builder.Config();
+ return builder;
+ }
+
+ ///
+ public override IHtmlContent Clone() {
+ return new WaterMarkRender( _config.Copy() );
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Components/WaterMarks/WaterMarkTagHelper.cs b/src/Util.Ui.NgZorro/Components/WaterMarks/WaterMarkTagHelper.cs
new file mode 100644
index 000000000..b55423042
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Components/WaterMarks/WaterMarkTagHelper.cs
@@ -0,0 +1,99 @@
+using Microsoft.AspNetCore.Razor.TagHelpers;
+using Util.Ui.Angular.TagHelpers;
+using Util.Ui.NgZorro.Components.WaterMarks.Renders;
+using Util.Ui.Renders;
+
+namespace Util.Ui.NgZorro.Components.WaterMarks;
+
+///
+/// 水印,生成的标签为<nz-water-mark></nz-water-mark>
+///
+[HtmlTargetElement( "util-water-mark" )]
+public class WaterMarkTagHelper : AngularTagHelperBase {
+ ///
+ /// nzContent,水印文字内容, 类型: string | string[]
+ ///
+ public string Content { get; set; }
+ ///
+ /// [nzContent],水印文字内容, 类型: string | string[]
+ ///
+ public string BindContent { get; set; }
+ ///
+ /// [nzWidth],水印宽度, 默认值: 120
+ ///
+ public double Width { get; set; }
+ ///
+ /// [nzWidth],水印宽度, 默认值: 120
+ ///
+ public string BindWidth { get; set; }
+ ///
+ /// [nzHeight],水印高度, 默认值: 64
+ ///
+ public double Height { get; set; }
+ ///
+ /// [nzHeight],水印高度, 默认值: 64
+ ///
+ public string BindHeight { get; set; }
+ ///
+ /// [nzRotate],旋转角度, 默认值: -22
+ ///
+ public double Rotate { get; set; }
+ ///
+ /// [nzRotate],旋转角度, 默认值: -22
+ ///
+ public string BindRotate { get; set; }
+ ///
+ /// [nzZIndex],水印元素的 z-index, 默认值: 9
+ ///
+ public double ZIndex { get; set; }
+ ///
+ /// [nzZIndex],水印元素的 z-index, 默认值: 9
+ ///
+ public string BindZIndex { get; set; }
+ ///
+ /// nzImage,水印图片地址
+ ///
+ public string Image { get; set; }
+ ///
+ /// [nzImage],水印图片地址
+ ///
+ public string BindImage { get; set; }
+ ///
+ /// [nzFont],文字样式
+ ///
+ public string Font { get; set; }
+ ///
+ /// [nzFont],字体颜色, 默认值: rgba(0,0,0,.15)
+ ///
+ public string FontColor { get; set; }
+ ///
+ /// [nzFont],字体大小, 默认值: 16
+ ///
+ public double FontSize { get; set; }
+ ///
+ /// [nzFont],字体粗细, 可选值: normal | light | weight | number, 默认值: normal
+ ///
+ public string FontWeight { get; set; }
+ ///
+ /// [nzFont],字体类型, 默认值: sans-serif
+ ///
+ public string FontFamily { get; set; }
+ ///
+ /// [nzFont],字体样式, 可选值: none | normal | italic | oblique, 默认值: normal
+ ///
+ public string FontStyle { get; set; }
+ ///
+ /// [nzGap],水印之间的间距, 类型: [number, number], 默认值: [100, 100]
+ ///
+ public string Gap { get; set; }
+ ///
+ /// [nzOffset],水印距离容器左上角的偏移量, 类型: [number, number], 默认值: [nzGap[0]/2, nzGap[1]/2]
+ ///
+ public string Offset { get; set; }
+
+ ///
+ protected override IRender GetRender( TagHelperContext context, TagHelperOutput output, TagHelperContent content ) {
+ var config = new Config( context, output, content );
+ return new WaterMarkRender( config );
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Enums/HashCodeMode.cs b/src/Util.Ui.NgZorro/Enums/HashCodeMode.cs
new file mode 100644
index 000000000..fd839d876
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Enums/HashCodeMode.cs
@@ -0,0 +1,27 @@
+namespace Util.Ui.NgZorro.Enums;
+
+///
+/// 哈希码展示模式
+///
+public enum HashCodeMode {
+ ///
+ /// 单行模式
+ ///
+ [Description( "single" )]
+ Single,
+ ///
+ /// 双行模式
+ ///
+ [Description( "double" )]
+ Double,
+ ///
+ /// 长条模式
+ ///
+ [Description( "strip" )]
+ Strip,
+ ///
+ /// 矩形模式
+ ///
+ [Description( "rect" )]
+ Rect
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Enums/HashCodeType.cs b/src/Util.Ui.NgZorro/Enums/HashCodeType.cs
new file mode 100644
index 000000000..f35611888
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Enums/HashCodeType.cs
@@ -0,0 +1,17 @@
+namespace Util.Ui.NgZorro.Enums;
+
+///
+/// 哈希码样式
+///
+public enum HashCodeType {
+ ///
+ /// 默认样式
+ ///
+ [Description( "defalut " )]
+ Defalut,
+ ///
+ /// 主样式
+ ///
+ [Description( "primary" )]
+ Primary
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Enums/QrCodeCorrectionLevel.cs b/src/Util.Ui.NgZorro/Enums/QrCodeCorrectionLevel.cs
new file mode 100644
index 000000000..8c58bfcd2
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Enums/QrCodeCorrectionLevel.cs
@@ -0,0 +1,23 @@
+namespace Util.Ui.NgZorro.Enums;
+
+///
+/// 二维码容错级别
+///
+public enum QrCodeCorrectionLevel {
+ ///
+ /// 可以纠正最大7%的错误
+ ///
+ L,
+ ///
+ /// 可以纠正最大15%的错误
+ ///
+ M,
+ ///
+ /// 可以纠正最大25%的错误
+ ///
+ Q,
+ ///
+ /// 可以纠正最大30%的错误
+ ///
+ H
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Enums/QrCodeStatus.cs b/src/Util.Ui.NgZorro/Enums/QrCodeStatus.cs
new file mode 100644
index 000000000..302c80e6c
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Enums/QrCodeStatus.cs
@@ -0,0 +1,22 @@
+namespace Util.Ui.NgZorro.Enums;
+
+///
+/// 二维码状态
+///
+public enum QrCodeStatus {
+ ///
+ /// active, 正常
+ ///
+ [Description( "active" )]
+ Active,
+ ///
+ /// expired,已过期
+ ///
+ [Description( "expired" )]
+ Expired,
+ ///
+ /// loading, 加载中
+ ///
+ [Description( "loading" )]
+ Loading
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/Extensions/TagBuilderExtensions.cs b/src/Util.Ui.NgZorro/Extensions/TagBuilderExtensions.cs
index e2ddd8dd2..5b20ed25a 100644
--- a/src/Util.Ui.NgZorro/Extensions/TagBuilderExtensions.cs
+++ b/src/Util.Ui.NgZorro/Extensions/TagBuilderExtensions.cs
@@ -1,87 +1,86 @@
-using Util.Ui.Builders;
-using Util.Ui.Configs;
-
-namespace Util.Ui.NgZorro.Extensions;
-
-///
-/// ng-zorro扩展
-///
-public static class TagBuilderExtensions {
- ///
- /// *nzSpaceItem,间距项
- ///
- /// 生成器类型
- /// 生成器实例
- /// 值
- public static TBuilder SpaceItem( this TBuilder builder, bool? value ) where TBuilder : TagBuilder {
- if( value == true )
- builder.Attribute( "*nzSpaceItem" );
- return builder;
- }
-
- ///
- /// *nzSpaceItem,间距项
- ///
- /// 生成器类型
- /// 生成器实例
- /// 配置
- public static TBuilder SpaceItem( this TBuilder builder, Config config ) where TBuilder : TagBuilder {
- builder.SpaceItem( config.GetValue( UiConst.SpaceItem ) );
- return builder;
- }
-
- ///
- /// 宽度
- ///
- /// 生成器类型
- /// 生成器实例
- /// 值
- /// 属性名
- public static TBuilder Width( this TBuilder builder, string value,string attributeName = "nzWidth" ) where TBuilder : TagBuilder {
- builder.AttributeIfNotEmpty( attributeName, GetPixelValue( value ) );
- return builder;
- }
-
- ///
- /// 获取像素值,如果传入数字,后加px,否则按原样返回
- ///
- /// 值
- private static string GetPixelValue( string value ) {
- if ( value.IsEmpty() )
- return null;
- if ( Util.Helpers.Validation.IsNumber( value ) )
- return $"{value}px";
- return value;
- }
-
- ///
- /// 添加到内容,支持i18n管道
- ///
- /// 生成器类型
- /// 生成器实例
- /// 值
- public static TBuilder AppendContentByI18n( this TBuilder builder, string value ) where TBuilder : TagBuilder {
- if ( value.IsEmpty() )
- return builder;
- var result = new StringBuilder();
- result.Append( "{{" );
- result.Append( $"'{value}'|i18n" );
- result.Append( "}}" );
- builder.AppendContent( result.ToString() );
- return builder;
- }
-
- ///
- /// 添加属性,支持i18n管道
- ///
- /// 生成器类型
- /// 生成器实例
- /// 属性名
- /// 值
- public static TBuilder AttributeByI18n( this TBuilder builder, string name, string value ) where TBuilder : TagBuilder {
- if ( value.IsEmpty() )
- return builder;
- builder.Attribute( name, $"'{value}'|i18n" );
- return builder;
- }
+using Util.Ui.Builders;
+
+namespace Util.Ui.NgZorro.Extensions;
+
+///
+/// ng-zorro扩展
+///
+public static class TagBuilderExtensions {
+ ///
+ /// *nzSpaceItem,间距项
+ ///
+ /// 生成器类型
+ /// 生成器实例
+ /// 值
+ public static TBuilder SpaceItem( this TBuilder builder, bool? value ) where TBuilder : TagBuilder {
+ if( value == true )
+ builder.Attribute( "*nzSpaceItem" );
+ return builder;
+ }
+
+ ///
+ /// *nzSpaceItem,间距项
+ ///
+ /// 生成器类型
+ /// 生成器实例
+ /// 配置
+ public static TBuilder SpaceItem( this TBuilder builder, Config config ) where TBuilder : TagBuilder {
+ builder.SpaceItem( config.GetValue( UiConst.SpaceItem ) );
+ return builder;
+ }
+
+ ///
+ /// 宽度
+ ///
+ /// 生成器类型
+ /// 生成器实例
+ /// 值
+ /// 属性名
+ public static TBuilder Width( this TBuilder builder, string value,string attributeName = "nzWidth" ) where TBuilder : TagBuilder {
+ builder.AttributeIfNotEmpty( attributeName, GetPixelValue( value ) );
+ return builder;
+ }
+
+ ///
+ /// 获取像素值,如果传入数字,后加px,否则按原样返回
+ ///
+ /// 值
+ private static string GetPixelValue( string value ) {
+ if ( value.IsEmpty() )
+ return null;
+ if ( Util.Helpers.Validation.IsNumber( value ) )
+ return $"{value}px";
+ return value;
+ }
+
+ ///
+ /// 添加到内容,支持i18n管道
+ ///
+ /// 生成器类型
+ /// 生成器实例
+ /// 值
+ public static TBuilder AppendContentByI18n( this TBuilder builder, string value ) where TBuilder : TagBuilder {
+ if ( value.IsEmpty() )
+ return builder;
+ var result = new StringBuilder();
+ result.Append( "{{" );
+ result.Append( $"'{value}'|i18n" );
+ result.Append( "}}" );
+ builder.AppendContent( result.ToString() );
+ return builder;
+ }
+
+ ///
+ /// 添加属性,支持i18n管道
+ ///
+ /// 生成器类型
+ /// 生成器实例
+ /// 属性名
+ /// 值
+ public static TBuilder AttributeByI18n( this TBuilder builder, string name, string value ) where TBuilder : TagBuilder {
+ if ( value.IsEmpty() )
+ return builder;
+ builder.Attribute( name, $"'{value}'|i18n" );
+ return builder;
+ }
}
\ No newline at end of file
diff --git a/src/Util.Ui/Configs/UiConst.cs b/src/Util.Ui/Configs/UiConst.cs
index b1e21abf7..8a2d30cfa 100644
--- a/src/Util.Ui/Configs/UiConst.cs
+++ b/src/Util.Ui/Configs/UiConst.cs
@@ -25,10 +25,30 @@ public static class UiConst {
///
public const string Color = "color";
///
+ /// 填充
+ ///
+ public const string Padding = "padding";
+ ///
+ /// 等级
+ ///
+ public const string Level = "level";
+ ///
+ /// 图片
+ ///
+ public const string Image = "image";
+ ///
+ /// 持续时间
+ ///
+ public const string Duration = "duration";
+ ///
/// 单元格控件
///
public const string CellControl = "cell-control";
///
+ /// 可见高度
+ ///
+ public const string VisibilityHeight = "visibility-height";
+ ///
/// 启用拖动调整尺寸
///
public const string EnableResizable = "enable-resizable";
@@ -89,6 +109,10 @@ public static class UiConst {
///
public const string BackgroundColor = "background-color";
///
+ /// 背景色
+ ///
+ public const string BgColor = "bg-color";
+ ///
/// 粘贴图片
///
public const string PasteDataImages = "paste-data-images";
@@ -437,6 +461,10 @@ public static class UiConst {
///
public const string OnChange = "on-change";
///
+ /// 刷新事件
+ ///
+ public const string OnRefresh = "on-refresh";
+ ///
/// 获得焦点事件
///
public const string OnFocus = "on-focus";
@@ -445,6 +473,10 @@ public static class UiConst {
///
public const string OnBlur = "on-blur";
///
+ /// 复制事件
+ ///
+ public const string OnCopy = "on-copy";
+ ///
/// 键盘按键事件
///
public const string OnKeyup = "on-keyup";
@@ -493,10 +525,38 @@ public static class UiConst {
///
public const string Icon = "icon";
///
+ /// 图标尺寸
+ ///
+ public const string IconSize = "icon-size";
+ ///
/// 复制到剪贴板
///
public const string CopyToClipboard = "copy-to-clipboard";
///
+ /// 字体
+ ///
+ public const string Font = "font";
+ ///
+ /// 字体颜色
+ ///
+ public const string FontColor = "font-color";
+ ///
+ /// 字体大小
+ ///
+ public const string FontSize = "font-size";
+ ///
+ /// 字体粗细
+ ///
+ public const string FontWeight = "font-weight";
+ ///
+ /// 字体类型
+ ///
+ public const string FontFamily = "font-family";
+ ///
+ /// 字体样式
+ ///
+ public const string FontStyle = "font-style";
+ ///
/// Font Awesome图标
///
public const string FontAwesomeIcon = "font-awesome-icon";
diff --git a/test/Util.Core.Tests/Helpers/JsonTest.cs b/test/Util.Core.Tests/Helpers/JsonTest.cs
index 5b23ef1cb..54f1bab0b 100644
--- a/test/Util.Core.Tests/Helpers/JsonTest.cs
+++ b/test/Util.Core.Tests/Helpers/JsonTest.cs
@@ -223,4 +223,14 @@ public void TestToJson_NullableLong() {
var obj = Json.ToObject( json );
Assert.Equal( 123456789123456789, obj.NullableLong );
}
+
+ ///
+ /// 测试转成Json - 忽略空字符串
+ ///
+ [Fact]
+ public void TestToJson_IgnoreEmpty() {
+ var sample = new JsonTestSample3 { Name = "" };
+ var json = Json.ToJson( sample, new JsonOptions { IgnoreEmptyString = true } );
+ Assert.Equal( "{}", json );
+ }
}
\ No newline at end of file
diff --git a/test/Util.Core.Tests/Samples/JsonTestSample.cs b/test/Util.Core.Tests/Samples/JsonTestSample.cs
index 0c3ed49ec..ca0a9ea5c 100644
--- a/test/Util.Core.Tests/Samples/JsonTestSample.cs
+++ b/test/Util.Core.Tests/Samples/JsonTestSample.cs
@@ -123,4 +123,11 @@ public interface IJsonTestSample {
public enum TestEnum {
Test1 = 1,
Test2 = 2
+}
+
+///
+/// Json测试样例
+///
+public class JsonTestSample3 {
+ public string Name { get; set; }
}
\ No newline at end of file
diff --git a/test/Util.Images.Avatar.Tests.Integration/Tests/AvatarManagerTest.cs b/test/Util.Images.Avatar.Tests.Integration/Tests/AvatarManagerTest.cs
index df7564bbf..3dcf3d2c2 100644
--- a/test/Util.Images.Avatar.Tests.Integration/Tests/AvatarManagerTest.cs
+++ b/test/Util.Images.Avatar.Tests.Integration/Tests/AvatarManagerTest.cs
@@ -15,7 +15,7 @@ public class AvatarManagerTest {
///
/// 输出路径
///
- private const string Path = @"D:\Util.Images.Avatar.Tests\{0}.gif";
+ private const string Path = "./test/{0}.gif";
///
/// 测试初始化
diff --git a/test/Util.Images.ImageSharp.Tests.Integration/Tests/DrawTextTest.cs b/test/Util.Images.ImageSharp.Tests.Integration/Tests/DrawTextTest.cs
index 07ca08fba..5d2d61f63 100644
--- a/test/Util.Images.ImageSharp.Tests.Integration/Tests/DrawTextTest.cs
+++ b/test/Util.Images.ImageSharp.Tests.Integration/Tests/DrawTextTest.cs
@@ -20,7 +20,7 @@ public class DrawTextTest {
///
/// 输出路径
///
- private const string Path = @"D:\Util.Images.ImageSharp.Tests\{0}.gif";
+ private const string Path = "./test/{0}.gif";
///
/// 测试初始化
diff --git a/test/Util.QrCode.ZXing.Tests.Integration/Icons/icon.jpg b/test/Util.QrCode.ZXing.Tests.Integration/Icons/icon.jpg
new file mode 100644
index 000000000..b591214cc
Binary files /dev/null and b/test/Util.QrCode.ZXing.Tests.Integration/Icons/icon.jpg differ
diff --git a/test/Util.QrCode.ZXing.Tests.Integration/Startup.cs b/test/Util.QrCode.ZXing.Tests.Integration/Startup.cs
new file mode 100644
index 000000000..36c7d8891
--- /dev/null
+++ b/test/Util.QrCode.ZXing.Tests.Integration/Startup.cs
@@ -0,0 +1,25 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Xunit.DependencyInjection.Logging;
+
+namespace Util.QrCode;
+
+///
+///
+///
+public class Startup {
+ ///
+ ///
+ ///
+ public void ConfigureHost( IHostBuilder hostBuilder ) {
+ hostBuilder.ConfigureDefaults( null )
+ .AddUtil();
+ }
+
+ ///
+ /// ÷
+ ///
+ public void ConfigureServices( IServiceCollection services ) {
+ services.AddLogging( logBuilder => logBuilder.AddXunitOutput() );
+ }
+}
\ No newline at end of file
diff --git a/test/Util.QrCode.ZXing.Tests.Integration/Tests/ZXingQrCodeServiceTest.cs b/test/Util.QrCode.ZXing.Tests.Integration/Tests/ZXingQrCodeServiceTest.cs
new file mode 100644
index 000000000..c4893c876
--- /dev/null
+++ b/test/Util.QrCode.ZXing.Tests.Integration/Tests/ZXingQrCodeServiceTest.cs
@@ -0,0 +1,151 @@
+using System.Drawing;
+using System.Threading.Tasks;
+using Util.Images;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Util.QrCode.Tests;
+
+///
+/// ZXing二维码服务
+///
+public class ZXingQrCodeServiceTest {
+ ///
+ /// 二维码服务
+ ///
+ private readonly IQrCodeService _service;
+ ///
+ /// 测试输出
+ ///
+ private readonly ITestOutputHelper _output;
+ ///
+ /// 内容
+ ///
+ private readonly string _content;
+
+ ///
+ /// 测试初始化
+ ///
+ public ZXingQrCodeServiceTest( IQrCodeService service, ITestOutputHelper output ) {
+ _service = service;
+ _output = output;
+ _content = "https://gitee.com/util-core/util";
+ }
+
+ ///
+ /// 测试获取二维码流
+ ///
+ [Fact]
+ public void TestToStream() {
+ var result = _service.Content( _content ).ToStream();
+ Util.Helpers.File.Write( "./test/ToStream.png", result );
+ }
+
+ ///
+ /// 测试获取二维码字节流
+ ///
+ [Fact]
+ public void TestToBytes() {
+ var result = _service.Content( _content ).ToBytes();
+ Util.Helpers.File.Write( "./test/ToBytes.png", result );
+ }
+
+ ///
+ /// 测试获取二维码Base64字符串
+ ///
+ [Fact]
+ public void TestToBase64_1() {
+ var result = _service.Content( _content ).ToBase64();
+ string base64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADyklEQVR4nO3dQU4jOxRAUZB6/1vm/0lLPYiaCn7xdaXPGQMp4MqK43L519f/PiDy6wNCAiQlQFICJCVAUgIk9dcAPz8/P07x6NOileu7+vOqT6mu/m7Tf5dp3/39jICkBEhKgKQESOrpAHe8Ka/eRE//bisTiR2Trmk/uT4jICkBkhIgKQGSGgnwpDfHV9+8X131WPm6q9f3yI6J2An/NyMgKQGSEiApAZJ6uwB3TBpW3rxPT1bu7u0C5F4ESEqApARI6tYBrrxRn16RmF5FOWl/yivdOkDuT4CkBEhKgKRGAjxp83Z1u9P0CswOJ0xqjICkBEhKgKQESOrpAE96E33Vjv0fJ33dI6f+34yApARISoCkBEjqrwF+HX77z+mP2b36und8EtYUIyApAZISICkBkho5J2THp/Erb+ivXsvKZGDH5Gfl51W3izknhKMJkJQASQmQ1MtWQnZMYHY89errDTeD/7bjNrDvGAFJCZCUAEkJkNTL9oTsWFXYsUdix8rASXtMph8/bCWEowmQlABJCZDUywLcMeGYvpYdhxWedBvY9MTuJ6sjRkBSAiQlQFICJPV0gNO3J01/Gn9VtRl85fednqxc9coDFo2ApARISoCkBEgqXwl5pPqEfvogwZP2mOzY1P4TRkBSAiQlQFICJJWfE3LSrVcrX7di5ZqrAxGnJiZGQFICJCVAUgIk9bIAp59cNX0tj0yvcOw4J6RabZma6BgBSQmQlABJCZDUyJ6QHSsXK3bsuZh+3WnVOSHfMQKSEiApAZISIKmnDyuc/sT/qunH8e7Yw3H6GSMn7G0xApISICkBkhIgqa2HFZ5+MOHVa1l5jR2rDztWb6ZWeYyApARISoCkBEhqJMAdk4YddjyV61+7ves7RkBSAiQlQFICJPX07VhX7VilqL73dDvOO3E7Fm9BgKQESEqApF52O9aKldu2pl93xzkh1d6M6YMTf8IISEqApARISoCkXrYSMm1lQ/z06z6yY4Kw8r2n3qJlBCQlQFICJCVAUiOP6J1WnZGxY0Vix2b16Sd6rawGfccISEqApARISoCkXrYx/arpSc2OW6Cmr+WRlcnAih0TrD8ZAUkJkJQASQmQ1K0DrPZw7FCtmOzeJ3LrALk/AZISICkBknq7AKc3tZ+0yjP9utMTHSsh3I4ASQmQlABJjQR40mrBCqsjno7FP0aApARISoCkng7wpCdmrTjp5PLqKV+79388YgQkJUBSAiQlQFJHnhNy1fT1nfTzdnxvdX1/MgKSEiApAZISICkBkhIgKQGS+g/OvjqVV+EClwAAAABJRU5ErkJggg==";
+ _output.WriteLine( result );
+ Assert.Equal( base64, result );
+ }
+
+ ///
+ /// 测试获取二维码Base64字符串 - 设置图片类型
+ ///
+ [Fact]
+ public void TestToBase64_2() {
+ var result = _service.Content( _content ).ImageType( ImageType.Jpg ).ToBase64();
+ string base64 = "data:image/jpeg;base64,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";
+ _output.WriteLine( result );
+ Assert.Equal( base64, result );
+ }
+
+ ///
+ /// 测试保存二维码图片
+ ///
+ [Fact]
+ public void TestSave() {
+ _service.Content( _content ).Save( "./test/Save.png" );
+ }
+
+ ///
+ /// 测试获取二维码流
+ ///
+ [Fact]
+ public async Task TestToStreamAsync() {
+ var result = await _service.Content( _content ).ToStreamAsync();
+ await Util.Helpers.File.WriteAsync( "./test/ToStreamAsync.png", result );
+ }
+
+ ///
+ /// 测试获取二维码字节流
+ ///
+ [Fact]
+ public async Task TestToBytesAsync() {
+ var result = await _service.Content( _content ).ToBytesAsync();
+ await Util.Helpers.File.WriteAsync( "./test/ToBytesAsync.png", result );
+ }
+
+ ///
+ /// 测试保存二维码图片
+ ///
+ [Fact]
+ public async Task TestSaveAsync_1() {
+ await _service.Content( _content ).SaveAsync( "./test/SaveAsync_1.png" );
+ }
+
+ ///
+ /// 测试保存二维码图片 - 设置二维码尺寸
+ ///
+ [Fact]
+ public async Task TestSaveAsync_2() {
+ await _service.Content( _content ).Size( QrSize.Small ).SaveAsync( "./test/SaveAsync_Small.png" );
+ await _service.Content( _content ).Size( QrSize.Middle ).SaveAsync( "./test/SaveAsync_Middle.png" );
+ await _service.Content( _content ).Size( QrSize.Large ).SaveAsync( "./test/SaveAsync_Large.png" );
+ }
+
+ ///
+ /// 测试保存二维码图片 - 设置前景色
+ ///
+ [Fact]
+ public async Task TestSaveAsync_3() {
+ await _service.Content( _content ).Color( Color.Red ).SaveAsync( "./test/SaveAsync_3.png" );
+ }
+
+ ///
+ /// 测试保存二维码图片 - 设置背景色
+ ///
+ [Fact]
+ public async Task TestSaveAsync_4() {
+ await _service.Content( _content ).BgColor( Color.Aquamarine ).SaveAsync( "./test/SaveAsync_4.png" );
+ }
+
+ ///
+ /// 测试保存二维码图片 - 设置边距
+ ///
+ [Fact]
+ public async Task TestSaveAsync_5() {
+ await _service.Content( _content ).Margin( 5 ).SaveAsync( "./test/SaveAsync_5.png" );
+ }
+
+ ///
+ /// 测试保存二维码图片 - 设置图标
+ ///
+ [Fact]
+ public async Task TestSaveAsync_6() {
+ var iconPath = Util.Helpers.Common.GetPhysicalPath( "./Icons/icon.jpg" );
+ await _service.Content( _content ).Icon( iconPath ).SaveAsync( "./test/SaveAsync_6.png" );
+ }
+}
\ No newline at end of file
diff --git a/test/Util.QrCode.ZXing.Tests.Integration/Util.QrCode.ZXing.Tests.Integration.csproj b/test/Util.QrCode.ZXing.Tests.Integration/Util.QrCode.ZXing.Tests.Integration.csproj
new file mode 100644
index 000000000..3b061dd2c
--- /dev/null
+++ b/test/Util.QrCode.ZXing.Tests.Integration/Util.QrCode.ZXing.Tests.Integration.csproj
@@ -0,0 +1,35 @@
+
+
+
+ $(NetTargetFramework)
+ false
+ Util.QrCode
+ Util.QrCode.Startup
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
\ No newline at end of file
diff --git a/test/Util.Ui.NgZorro.Tests/BackTops/BackTopTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/BackTops/BackTopTagHelperTest.cs
new file mode 100644
index 000000000..26118409b
--- /dev/null
+++ b/test/Util.Ui.NgZorro.Tests/BackTops/BackTopTagHelperTest.cs
@@ -0,0 +1,138 @@
+using System.Text;
+using Util.Ui.Angular.Configs;
+using Util.Ui.Configs;
+using Util.Ui.NgZorro.Components.BackTops;
+using Util.Ui.TagHelpers;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Util.Ui.NgZorro.Tests.BackTops;
+
+///
+/// 回到顶部测试
+///
+public class BackTopTagHelperTest {
+ ///
+ /// 输出工具
+ ///
+ private readonly ITestOutputHelper _output;
+ ///
+ /// TagHelper包装器
+ ///
+ private readonly TagHelperWrapper _wrapper;
+
+ ///
+ /// 测试初始化
+ ///
+ public BackTopTagHelperTest( ITestOutputHelper output ) {
+ _output = output;
+ _wrapper = new BackTopTagHelper().ToWrapper();
+ }
+
+ ///
+ /// 获取结果
+ ///
+ private string GetResult() {
+ var result = _wrapper.GetResult();
+ _output.WriteLine( result );
+ return result;
+ }
+
+ ///
+ /// 测试默认输出
+ ///
+ [Fact]
+ public void TestDefault() {
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试自定义内容
+ ///
+ [Fact]
+ public void TestTemplate() {
+ _wrapper.SetContextAttribute( UiConst.Template, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试可见高度
+ ///
+ [Fact]
+ public void TestVisibilityHeight() {
+ _wrapper.SetContextAttribute( UiConst.VisibilityHeight, 1 );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试可见高度
+ ///
+ [Fact]
+ public void TestBindVisibilityHeight() {
+ _wrapper.SetContextAttribute( AngularConst.BindVisibilityHeight, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试监听目标
+ ///
+ [Fact]
+ public void TestTarget() {
+ _wrapper.SetContextAttribute( UiConst.Target, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试持续时间
+ ///
+ [Fact]
+ public void TestDuration() {
+ _wrapper.SetContextAttribute( UiConst.Duration, 1 );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试持续时间
+ ///
+ [Fact]
+ public void TestBindDuration() {
+ _wrapper.SetContextAttribute( AngularConst.BindDuration, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试内容
+ ///
+ [Fact]
+ public void TestContent() {
+ _wrapper.AppendContent( "a" );
+ var result = new StringBuilder();
+ result.Append( "a" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试单击事件
+ ///
+ [Fact]
+ public void TestOnClick() {
+ _wrapper.SetContextAttribute( UiConst.OnClick, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+}
\ No newline at end of file
diff --git a/test/Util.Ui.NgZorro.Tests/Cascaders/CascaderTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/Cascaders/CascaderTagHelperTest.cs
index bc2e6066b..4b82f3f30 100644
--- a/test/Util.Ui.NgZorro.Tests/Cascaders/CascaderTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/Cascaders/CascaderTagHelperTest.cs
@@ -1,4 +1,5 @@
using System.Text;
+using Util.Helpers;
using Util.Ui.Angular.Configs;
using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Cascaders;
@@ -27,6 +28,7 @@ public class CascaderTagHelperTest {
public CascaderTagHelperTest( ITestOutputHelper output ) {
_output = output;
_wrapper = new CascaderTagHelper().ToWrapper();
+ Id.SetId( "id" );
}
///
@@ -559,9 +561,19 @@ public void TestContent() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.Required, "true" );
+ _wrapper.SetContextAttribute( AngularConst.NgModel, "model" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "{{v_id.getErrorMessage()}}" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
}
diff --git a/test/Util.Ui.NgZorro.Tests/Checkboxes/CheckboxTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/Checkboxes/CheckboxTagHelperTest.cs
index de6883119..4ab0b57a4 100644
--- a/test/Util.Ui.NgZorro.Tests/Checkboxes/CheckboxTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/Checkboxes/CheckboxTagHelperTest.cs
@@ -234,9 +234,16 @@ public void TestControlSpan() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "a" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
diff --git a/test/Util.Ui.NgZorro.Tests/DatePickers/DatePickerTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/DatePickers/DatePickerTagHelperTest.cs
index 12dc2846f..2a893c4ce 100644
--- a/test/Util.Ui.NgZorro.Tests/DatePickers/DatePickerTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/DatePickers/DatePickerTagHelperTest.cs
@@ -518,9 +518,16 @@ public void TestOnOk() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "a" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
}
diff --git a/test/Util.Ui.NgZorro.Tests/DatePickers/RangePickerTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/DatePickers/RangePickerTagHelperTest.cs
index cd681ab95..145d97e0f 100644
--- a/test/Util.Ui.NgZorro.Tests/DatePickers/RangePickerTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/DatePickers/RangePickerTagHelperTest.cs
@@ -485,9 +485,16 @@ public void TestOnOk() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "a" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
diff --git a/test/Util.Ui.NgZorro.Tests/HashCodes/HashCodeTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/HashCodes/HashCodeTagHelperTest.cs
new file mode 100644
index 000000000..bd10a64d5
--- /dev/null
+++ b/test/Util.Ui.NgZorro.Tests/HashCodes/HashCodeTagHelperTest.cs
@@ -0,0 +1,183 @@
+using System.Text;
+using Util.Ui.Angular.Configs;
+using Util.Ui.Configs;
+using Util.Ui.NgZorro.Components.HashCodes;
+using Util.Ui.NgZorro.Enums;
+using Util.Ui.TagHelpers;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Util.Ui.NgZorro.Tests.HashCodes;
+
+///
+/// 哈希码测试
+///
+public class HashCodeTagHelperTest {
+ ///
+ /// 输出工具
+ ///
+ private readonly ITestOutputHelper _output;
+ ///
+ /// TagHelper包装器
+ ///
+ private readonly TagHelperWrapper _wrapper;
+
+ ///
+ /// 测试初始化
+ ///
+ public HashCodeTagHelperTest( ITestOutputHelper output ) {
+ _output = output;
+ _wrapper = new HashCodeTagHelper().ToWrapper();
+ }
+
+ ///
+ /// 获取结果
+ ///
+ private string GetResult() {
+ var result = _wrapper.GetResult();
+ _output.WriteLine( result );
+ return result;
+ }
+
+ ///
+ /// 测试默认输出
+ ///
+ [Fact]
+ public void TestDefault() {
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试值
+ ///
+ [Fact]
+ public void TestValue() {
+ _wrapper.SetContextAttribute( UiConst.Value, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试值
+ ///
+ [Fact]
+ public void TestBindValue() {
+ _wrapper.SetContextAttribute( AngularConst.BindValue, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试标题
+ ///
+ [Fact]
+ public void TestTitle() {
+ _wrapper.SetContextAttribute( UiConst.Title, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试标题
+ ///
+ [Fact]
+ public void TestBindTitle() {
+ _wrapper.SetContextAttribute( AngularConst.BindTitle, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试标志
+ ///
+ [Fact]
+ public void TestLogo() {
+ _wrapper.SetContextAttribute( UiConst.Logo, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试标志
+ ///
+ [Fact]
+ public void TestBindLogo() {
+ _wrapper.SetContextAttribute( AngularConst.BindLogo, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试展示模式
+ ///
+ [Fact]
+ public void TestMode() {
+ _wrapper.SetContextAttribute( UiConst.Mode, HashCodeMode.Rect );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试展示模式
+ ///
+ [Fact]
+ public void TestBindMode() {
+ _wrapper.SetContextAttribute( AngularConst.BindMode, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试样式
+ ///
+ [Fact]
+ public void TestType() {
+ _wrapper.SetContextAttribute( UiConst.Type, HashCodeType.Primary );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试样式
+ ///
+ [Fact]
+ public void TestBindType() {
+ _wrapper.SetContextAttribute( AngularConst.BindType, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试内容
+ ///
+ [Fact]
+ public void TestContent() {
+ _wrapper.AppendContent( "a" );
+ var result = new StringBuilder();
+ result.Append( "a" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试复制事件
+ ///
+ [Fact]
+ public void TestOnCopy() {
+ _wrapper.SetContextAttribute( UiConst.OnCopy, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+}
\ No newline at end of file
diff --git a/test/Util.Ui.NgZorro.Tests/InputNumbers/InputNumberTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/InputNumbers/InputNumberTagHelperTest.cs
index b4daa25e2..585ad4d5c 100644
--- a/test/Util.Ui.NgZorro.Tests/InputNumbers/InputNumberTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/InputNumbers/InputNumberTagHelperTest.cs
@@ -364,9 +364,16 @@ public void TestOnBlur() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "a" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
}
diff --git a/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.Form.cs b/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.Form.cs
index 252ae094c..b66267c84 100644
--- a/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.Form.cs
+++ b/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.Form.cs
@@ -164,6 +164,39 @@ public void TestLabelText() {
Assert.Equal( result.ToString(), GetResult() );
}
+ ///
+ /// 测试标签文本 - 启用I18n
+ ///
+ [Fact]
+ public void TestLabelText_I18n() {
+ NgZorroOptionsService.SetOptions( new NgZorroOptions { EnableI18n = true } );
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ result.Append( "{{'a'|i18n}}" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试标签文本
+ ///
+ [Fact]
+ public void TestBindLabelText() {
+ _wrapper.SetContextAttribute( AngularConst.BindLabelText, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ result.Append( "{{a}}" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
///
/// 测试是否显示标签
///
diff --git a/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.I18n.cs b/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.I18n.cs
deleted file mode 100644
index 5b0986fcf..000000000
--- a/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.I18n.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System.Text;
-using Util.Ui.Configs;
-using Util.Ui.NgZorro.Configs;
-using Xunit;
-
-namespace Util.Ui.NgZorro.Tests.Inputs {
- ///
- /// 输入框测试 - 国际化
- ///
- public partial class InputTagHelperTest {
- ///
- /// 测试标签文本 - 启用I18n
- ///
- [Fact]
- public void TestLabelText_I18n() {
- NgZorroOptionsService.SetOptions( new NgZorroOptions { EnableI18n = true } );
- _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
- var result = new StringBuilder();
- result.Append( "" );
- result.Append( "{{'a'|i18n}}" );
- result.Append( "" );
- result.Append( "" );
- result.Append( "" );
- result.Append( "" );
- Assert.Equal( result.ToString(), GetResult() );
- }
- }
-}
-
diff --git a/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.Space.cs b/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.Space.cs
index cc3a009a1..3ee383421 100644
--- a/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.Space.cs
+++ b/test/Util.Ui.NgZorro.Tests/Inputs/InputTagHelperTest.Space.cs
@@ -1,4 +1,5 @@
using System.Text;
+using Util.Ui.Angular.Configs;
using Util.Ui.Configs;
using Xunit;
@@ -12,9 +13,19 @@ public partial class InputTagHelperTest {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.Required, "true" );
+ _wrapper.SetContextAttribute( AngularConst.NgModel, "model" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "{{v_id.getErrorMessage()}}" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
}
diff --git a/test/Util.Ui.NgZorro.Tests/QrCodes/QrCodeTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/QrCodes/QrCodeTagHelperTest.cs
new file mode 100644
index 000000000..da2f62e1b
--- /dev/null
+++ b/test/Util.Ui.NgZorro.Tests/QrCodes/QrCodeTagHelperTest.cs
@@ -0,0 +1,282 @@
+using System.Text;
+using Util.Ui.Angular.Configs;
+using Util.Ui.Configs;
+using Util.Ui.NgZorro.Components.QrCodes;
+using Util.Ui.NgZorro.Enums;
+using Util.Ui.TagHelpers;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Util.Ui.NgZorro.Tests.QrCodes;
+
+///
+/// 二维码测试
+///
+public class QrCodeTagHelperTest {
+ ///
+ /// 输出工具
+ ///
+ private readonly ITestOutputHelper _output;
+ ///
+ /// TagHelper包装器
+ ///
+ private readonly TagHelperWrapper _wrapper;
+
+ ///
+ /// 测试初始化
+ ///
+ public QrCodeTagHelperTest( ITestOutputHelper output ) {
+ _output = output;
+ _wrapper = new QrCodeTagHelper().ToWrapper();
+ }
+
+ ///
+ /// 获取结果
+ ///
+ private string GetResult() {
+ var result = _wrapper.GetResult();
+ _output.WriteLine( result );
+ return result;
+ }
+
+ ///
+ /// 测试默认输出
+ ///
+ [Fact]
+ public void TestDefault() {
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试值
+ ///
+ [Fact]
+ public void TestValue() {
+ _wrapper.SetContextAttribute( UiConst.Value, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试值
+ ///
+ [Fact]
+ public void TestBindValue() {
+ _wrapper.SetContextAttribute( AngularConst.BindValue, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试颜色
+ ///
+ [Fact]
+ public void TestColor() {
+ _wrapper.SetContextAttribute( UiConst.Color, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试颜色
+ ///
+ [Fact]
+ public void TestBindColor() {
+ _wrapper.SetContextAttribute( AngularConst.BindColor, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试背景色
+ ///
+ [Fact]
+ public void TestBgColor() {
+ _wrapper.SetContextAttribute( UiConst.BgColor, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试背景色
+ ///
+ [Fact]
+ public void TestBindBgColor() {
+ _wrapper.SetContextAttribute( AngularConst.BindBgColor, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试尺寸
+ ///
+ [Fact]
+ public void TestSize() {
+ _wrapper.SetContextAttribute( UiConst.Size, 1 );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试尺寸
+ ///
+ [Fact]
+ public void TestBindSize() {
+ _wrapper.SetContextAttribute( AngularConst.BindSize, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试填充
+ ///
+ [Fact]
+ public void TestPadding() {
+ _wrapper.SetContextAttribute( UiConst.Padding, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试图标地址
+ ///
+ [Fact]
+ public void TestIcon() {
+ _wrapper.SetContextAttribute( UiConst.Icon, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试图标地址
+ ///
+ [Fact]
+ public void TestBindIcon() {
+ _wrapper.SetContextAttribute( AngularConst.BindIcon, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试图标尺寸
+ ///
+ [Fact]
+ public void TestIconSize() {
+ _wrapper.SetContextAttribute( UiConst.IconSize, 1 );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试图标尺寸
+ ///
+ [Fact]
+ public void TestBindIconSize() {
+ _wrapper.SetContextAttribute( AngularConst.BindIconSize, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试边框
+ ///
+ [Fact]
+ public void TestBordered() {
+ _wrapper.SetContextAttribute( UiConst.Bordered, true );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试边框
+ ///
+ [Fact]
+ public void TestBindBordered() {
+ _wrapper.SetContextAttribute( AngularConst.BindBordered, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试状态
+ ///
+ [Fact]
+ public void TestStatus() {
+ _wrapper.SetContextAttribute( UiConst.Status, QrCodeStatus.Expired );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试状态
+ ///
+ [Fact]
+ public void TestBindStatus() {
+ _wrapper.SetContextAttribute( AngularConst.BindStatus, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试容错级别
+ ///
+ [Fact]
+ public void TestLevel() {
+ _wrapper.SetContextAttribute( UiConst.Level, QrCodeCorrectionLevel.H );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试容错级别
+ ///
+ [Fact]
+ public void TestBindLevel() {
+ _wrapper.SetContextAttribute( AngularConst.BindLevel, 'a' );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试内容
+ ///
+ [Fact]
+ public void TestContent() {
+ _wrapper.AppendContent( "a" );
+ var result = new StringBuilder();
+ result.Append( "a" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试刷新事件
+ ///
+ [Fact]
+ public void TestOnRefresh() {
+ _wrapper.SetContextAttribute( UiConst.OnRefresh, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+}
\ No newline at end of file
diff --git a/test/Util.Ui.NgZorro.Tests/Selects/SelectTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/Selects/SelectTagHelperTest.cs
index e271eb816..e23421988 100644
--- a/test/Util.Ui.NgZorro.Tests/Selects/SelectTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/Selects/SelectTagHelperTest.cs
@@ -781,9 +781,16 @@ public void TestOnBlur() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "a" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
}
diff --git a/test/Util.Ui.NgZorro.Tests/Switches/SwitchTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/Switches/SwitchTagHelperTest.cs
index d4c98f856..45addcea9 100644
--- a/test/Util.Ui.NgZorro.Tests/Switches/SwitchTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/Switches/SwitchTagHelperTest.cs
@@ -252,9 +252,16 @@ public void TestOnClick() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "a" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
}
diff --git a/test/Util.Ui.NgZorro.Tests/Textareas/TextareaTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/Textareas/TextareaTagHelperTest.cs
index 2a3a321ff..5bf6335e7 100644
--- a/test/Util.Ui.NgZorro.Tests/Textareas/TextareaTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/Textareas/TextareaTagHelperTest.cs
@@ -276,9 +276,16 @@ public void TestMentionTrigger() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "a" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
}
diff --git a/test/Util.Ui.NgZorro.Tests/TimePickers/TimePickerTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/TimePickers/TimePickerTagHelperTest.cs
index 747f243a2..cebe9ba70 100644
--- a/test/Util.Ui.NgZorro.Tests/TimePickers/TimePickerTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/TimePickers/TimePickerTagHelperTest.cs
@@ -474,9 +474,16 @@ public void TestOnOpenChange() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "a" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
}
diff --git a/test/Util.Ui.NgZorro.Tests/TreeSelects/TreeSelectTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/TreeSelects/TreeSelectTagHelperTest.cs
index a15c6ebfc..938b2bc78 100644
--- a/test/Util.Ui.NgZorro.Tests/TreeSelects/TreeSelectTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/TreeSelects/TreeSelectTagHelperTest.cs
@@ -695,9 +695,16 @@ public void TestOnOpenChange() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( "" );
+ result.Append( "" );
+ result.Append( "a" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
}
diff --git a/test/Util.Ui.NgZorro.Tests/Upload/UploadTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/Upload/UploadTagHelperTest.cs
index 215629004..a58961a1c 100644
--- a/test/Util.Ui.NgZorro.Tests/Upload/UploadTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/Upload/UploadTagHelperTest.cs
@@ -571,9 +571,16 @@ public void TestOnChange() {
///
[Fact]
public void TestSpaceItem() {
+ _wrapper.SetContextAttribute( UiConst.LabelText, "a" );
_wrapper.SetContextAttribute( UiConst.SpaceItem, true );
+
var result = new StringBuilder();
- result.Append( $"{GetButton()}" );
+ result.Append( "" );
+ result.Append( "a" );
+ result.Append( "" );
+ result.Append( $"{GetButton()}" );
+ result.Append( "" );
+ result.Append( "" );
Assert.Equal( result.ToString(), GetResult() );
}
diff --git a/test/Util.Ui.NgZorro.Tests/WaterMarks/WaterMarkTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/WaterMarks/WaterMarkTagHelperTest.cs
new file mode 100644
index 000000000..09e6fe97e
--- /dev/null
+++ b/test/Util.Ui.NgZorro.Tests/WaterMarks/WaterMarkTagHelperTest.cs
@@ -0,0 +1,282 @@
+using System.Text;
+using Util.Ui.Angular.Configs;
+using Util.Ui.Configs;
+using Util.Ui.NgZorro.Components.WaterMarks;
+using Util.Ui.NgZorro.Enums;
+using Util.Ui.TagHelpers;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Util.Ui.NgZorro.Tests.WaterMarks;
+
+///
+/// 水印测试
+///
+public class WaterMarkTagHelperTest {
+ ///
+ /// 输出工具
+ ///
+ private readonly ITestOutputHelper _output;
+ ///
+ /// TagHelper包装器
+ ///
+ private readonly TagHelperWrapper _wrapper;
+
+ ///
+ /// 测试初始化
+ ///
+ public WaterMarkTagHelperTest( ITestOutputHelper output ) {
+ _output = output;
+ _wrapper = new WaterMarkTagHelper().ToWrapper();
+ }
+
+ ///
+ /// 获取结果
+ ///
+ private string GetResult() {
+ var result = _wrapper.GetResult();
+ _output.WriteLine( result );
+ return result;
+ }
+
+ ///
+ /// 测试默认输出
+ ///
+ [Fact]
+ public void TestDefault() {
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试水印文字内容
+ ///
+ [Fact]
+ public void TestContent() {
+ _wrapper.SetContextAttribute( UiConst.Content, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试水印文字内容
+ ///
+ [Fact]
+ public void TestBindContent() {
+ _wrapper.SetContextAttribute( AngularConst.BindContent, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试水印宽度
+ ///
+ [Fact]
+ public void TestWidth() {
+ _wrapper.SetContextAttribute( UiConst.Width, 1 );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试水印宽度
+ ///
+ [Fact]
+ public void TestBindWidth() {
+ _wrapper.SetContextAttribute( AngularConst.BindWidth, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试水印高度
+ ///
+ [Fact]
+ public void TestHeight() {
+ _wrapper.SetContextAttribute( UiConst.Height, 1 );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试水印高度
+ ///
+ [Fact]
+ public void TestBindHeight() {
+ _wrapper.SetContextAttribute( AngularConst.BindHeight, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试旋转角度
+ ///
+ [Fact]
+ public void TestRotate() {
+ _wrapper.SetContextAttribute( UiConst.Rotate, 1 );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试旋转角度
+ ///
+ [Fact]
+ public void TestBindRotate() {
+ _wrapper.SetContextAttribute( AngularConst.BindRotate, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试z-index
+ ///
+ [Fact]
+ public void TestZIndex() {
+ _wrapper.SetContextAttribute( UiConst.ZIndex, 1 );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试z-index
+ ///
+ [Fact]
+ public void TestBindZIndex() {
+ _wrapper.SetContextAttribute( AngularConst.BindZIndex, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试水印图片地址
+ ///
+ [Fact]
+ public void TestImage() {
+ _wrapper.SetContextAttribute( UiConst.Image, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试水印图片地址
+ ///
+ [Fact]
+ public void TestBindImage() {
+ _wrapper.SetContextAttribute( AngularConst.BindImage, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试文字样式
+ ///
+ [Fact]
+ public void TestFont() {
+ _wrapper.SetContextAttribute( UiConst.Font, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试字体颜色
+ ///
+ [Fact]
+ public void TestFontColor() {
+ _wrapper.SetContextAttribute( UiConst.FontColor, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试字体大小
+ ///
+ [Fact]
+ public void TestFontSize() {
+ _wrapper.SetContextAttribute( UiConst.FontSize, 1 );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试字体粗细
+ ///
+ [Fact]
+ public void TestFontWeight() {
+ _wrapper.SetContextAttribute( UiConst.FontWeight, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试字体类型
+ ///
+ [Fact]
+ public void TestFontFamily() {
+ _wrapper.SetContextAttribute( UiConst.FontFamily, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试字体样式
+ ///
+ [Fact]
+ public void TestFontStyle() {
+ _wrapper.SetContextAttribute( UiConst.FontStyle, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试间距
+ ///
+ [Fact]
+ public void TestGap() {
+ _wrapper.SetContextAttribute( UiConst.Gap, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试偏移量
+ ///
+ [Fact]
+ public void TestOffset() {
+ _wrapper.SetContextAttribute( UiConst.Offset, "a" );
+ var result = new StringBuilder();
+ result.Append( "" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
+ ///
+ /// 测试内容
+ ///
+ [Fact]
+ public void TestAppendContent() {
+ _wrapper.AppendContent( "a" );
+ var result = new StringBuilder();
+ result.Append( "a" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+}
\ No newline at end of file