diff --git a/build/version.props b/build/version.props
index 88fe86b92..f1d53f884 100644
--- a/build/version.props
+++ b/build/version.props
@@ -2,7 +2,7 @@
8
0
- 9
+ 10
$(VersionMajor).$(VersionMinor).$(VersionPatch)
diff --git a/src/Util.Core/Helpers/FileWatcher.cs b/src/Util.Core/Helpers/FileWatcher.cs
index 05e341cd6..7db14331f 100644
--- a/src/Util.Core/Helpers/FileWatcher.cs
+++ b/src/Util.Core/Helpers/FileWatcher.cs
@@ -8,13 +8,34 @@ public class FileWatcher : IDisposable {
/// 文件系统监视器
///
private readonly FileSystemWatcher _watcher;
+ ///
+ /// 防抖间隔
+ ///
+ private int _debounceInterval;
+ ///
+ /// 文件监视事件过滤器
+ ///
+ private readonly FileWatcherEventFilter _fileWatcherEventFilter;
///
/// 初始化文件监视器
///
public FileWatcher() {
_watcher = new FileSystemWatcher();
- _watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
+ _watcher.NotifyFilter = NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastWrite
+ | NotifyFilters.CreationTime | NotifyFilters.LastAccess
+ | NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.Security;
+ _debounceInterval = 200;
+ _fileWatcherEventFilter = new FileWatcherEventFilter();
+ }
+
+ ///
+ /// 设置防抖间隔,默认值: 200 毫秒
+ ///
+ /// 防抖间隔, 单位: 毫秒
+ public FileWatcher Debounce( int interval ) {
+ _debounceInterval = interval;
+ return this;
}
///
@@ -52,7 +73,8 @@ public FileWatcher Filter( string filter ) {
/// 文件创建监听事件处理器
public FileWatcher OnCreated( Action
private static void ConfigRazorOptions( IServiceCollection services, NgZorroOptions options ) {
- void Action( RazorOptions t ) {
- t.IsGenerateHtml = options.IsGenerateHtml;
- t.GenerateHtmlBasePath = options.GenerateHtmlBasePath;
- t.GenerateHtmlFolder = options.GenerateHtmlFolder;
- t.GenerateHtmlSuffix = options.GenerateHtmlSuffix;
- t.EnableWatchRazor = options.EnableWatchRazor;
- t.StartInitDelay = options.StartInitDelay;
- t.HtmlRenderDelayOnRazorChange = options.HtmlRenderDelayOnRazorChange;
- t.EnablePreheat = options.EnablePreheat;
- t.EnableOverrideHtml = options.EnableOverrideHtml;
+ void Action( RazorOptions razorOptions ) {
+ options.MapTo( razorOptions );
}
services.Configure( (Action)Action );
}
diff --git a/src/Util.Ui.NgZorro/Components/Descriptions/DescriptionItemTagHelper.cs b/src/Util.Ui.NgZorro/Components/Descriptions/DescriptionItemTagHelper.cs
index 86ce56fe8..20ac889c2 100644
--- a/src/Util.Ui.NgZorro/Components/Descriptions/DescriptionItemTagHelper.cs
+++ b/src/Util.Ui.NgZorro/Components/Descriptions/DescriptionItemTagHelper.cs
@@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Util.Ui.Angular.TagHelpers;
-using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Descriptions.Renders;
using Util.Ui.NgZorro.Components.Display.Helpers;
using Util.Ui.Renders;
diff --git a/src/Util.Ui.NgZorro/Components/Links/Renders/ARender.cs b/src/Util.Ui.NgZorro/Components/Links/Renders/ARender.cs
index 5f5867775..f1c32121b 100644
--- a/src/Util.Ui.NgZorro/Components/Links/Renders/ARender.cs
+++ b/src/Util.Ui.NgZorro/Components/Links/Renders/ARender.cs
@@ -1,8 +1,9 @@
using Util.Ui.Builders;
+using Util.Ui.NgZorro.Components.Forms.Configs;
using Util.Ui.NgZorro.Components.Links.Builders;
using Util.Ui.Renders;
-namespace Util.Ui.NgZorro.Components.Links.Renders;
+namespace Util.Ui.NgZorro.Components.Links.Renders;
///
/// 链接渲染器
@@ -25,11 +26,31 @@ public ARender( Config config ) {
/// 获取标签生成器
///
protected override TagBuilder GetTagBuilder() {
+ if ( IsHide() )
+ return new EmptyTagBuilder();
var builder = new ABuilder( _config );
builder.Config();
return builder;
}
+ ///
+ /// 是否隐藏标签
+ ///
+ private bool IsHide() {
+ var isSearch = _config.GetValue( UiConst.IsSearch );
+ if ( isSearch != true )
+ return false;
+ var formShareConfig = GetFormShareConfig();
+ return formShareConfig.GetConditionCount() <= formShareConfig.SearchFormShowNumber;
+ }
+
+ ///
+ /// 获取表单共享配置
+ ///
+ public FormShareConfig GetFormShareConfig() {
+ return _config.GetValueFromItems() ?? new FormShareConfig();
+ }
+
///
public override IHtmlContent Clone() {
return new ARender( _config.Copy() );
diff --git a/src/Util.Ui.NgZorro/Components/Tables/Builders/TableBodyRowBuilder.cs b/src/Util.Ui.NgZorro/Components/Tables/Builders/TableBodyRowBuilder.cs
index b3d3c515c..73441ba5f 100644
--- a/src/Util.Ui.NgZorro/Components/Tables/Builders/TableBodyRowBuilder.cs
+++ b/src/Util.Ui.NgZorro/Components/Tables/Builders/TableBodyRowBuilder.cs
@@ -55,6 +55,7 @@ public override void Config() {
base.Config();
ConfigTableExtend();
ConfigEdit();
+ ConfigTableRowCheckedClass();
ConfigContent();
}
@@ -88,6 +89,16 @@ protected void ConfigEdit() {
Attribute( "(dblclick)", $"{EditId}.dblClickEdit(row.id)", append: true );
}
+ ///
+ /// 配置勾选样式
+ ///
+ protected void ConfigTableRowCheckedClass() {
+ var options = NgZorroOptionsService.GetOptions();
+ if ( options.EnableTableRowCheckedClass == false )
+ return;
+ Attribute( "[class.table-row-checked]", $"{TableShareConfig.TableExtendId}.isChecked(row)" );
+ }
+
///
/// 配置内容
///
diff --git a/src/Util.Ui.NgZorro/Components/Tables/Builders/TableHeadRowBuilder.cs b/src/Util.Ui.NgZorro/Components/Tables/Builders/TableHeadRowBuilder.cs
index bb5adc0cc..99d0edc96 100644
--- a/src/Util.Ui.NgZorro/Components/Tables/Builders/TableHeadRowBuilder.cs
+++ b/src/Util.Ui.NgZorro/Components/Tables/Builders/TableHeadRowBuilder.cs
@@ -1,5 +1,4 @@
using Util.Ui.Angular.Extensions;
-using Util.Ui.Configs;
using Util.Ui.Extensions;
using Util.Ui.NgZorro.Components.Tables.Configs;
using Util.Ui.NgZorro.Components.Tables.Helpers;
diff --git a/src/Util.Ui.NgZorro/Controllers/GenerateHtmlController.cs b/src/Util.Ui.NgZorro/Controllers/GenerateHtmlController.cs
new file mode 100644
index 000000000..906559337
--- /dev/null
+++ b/src/Util.Ui.NgZorro/Controllers/GenerateHtmlController.cs
@@ -0,0 +1,28 @@
+using Util.Ui.Razor;
+
+namespace Util.Ui.NgZorro.Controllers;
+
+///
+/// Razor生成Html控制器
+///
+[ApiController]
+[Route( "api/html" )]
+public class GenerateHtmlController : ControllerBase {
+ ///
+ /// 生成所有Razor页面的Html
+ ///
+ [HttpGet]
+ public async Task GenerateAsync() {
+ var message = new StringBuilder();
+ var result = await HtmlGenerator.GenerateAsync();
+ message.AppendLine( "======================= 欢迎使用 Util 应用框架 - 开始生成全部Razor页面html =======================" );
+ message.AppendLine();
+ message.AppendLine();
+ foreach ( var path in result )
+ message.AppendLine( path );
+ message.AppendLine();
+ message.AppendLine();
+ message.Append( "======================================== html文件生成完成 ========================================" );
+ return message.ToString();
+ }
+}
\ No newline at end of file
diff --git a/src/Util.Ui.NgZorro/NgZorroOptions.cs b/src/Util.Ui.NgZorro/NgZorroOptions.cs
index c5d8fdd20..e5931111b 100644
--- a/src/Util.Ui.NgZorro/NgZorroOptions.cs
+++ b/src/Util.Ui.NgZorro/NgZorroOptions.cs
@@ -1,11 +1,12 @@
using Util.Ui.NgZorro.Enums;
+using Util.Ui.Razor;
namespace Util.Ui.NgZorro;
///
/// NgZorro配置
///
-public class NgZorroOptions {
+public class NgZorroOptions : RazorOptions {
///
/// 初始化NgZorro配置
///
@@ -18,34 +19,6 @@ public NgZorroOptions() {
}
}
- ///
- /// Spa静态文件根路径,默认值: ClientApp
- ///
- public string RootPath { get; set; } = "ClientApp";
- ///
- /// 是否自动生成html,默认值: false
- ///
- internal bool IsGenerateHtml { get; set; }
- ///
- /// Razor生成Html页面的基路径,默认值: /ClientApp/src/app
- ///
- public string GenerateHtmlBasePath { get; set; } = "/ClientApp/src/app";
- ///
- /// Razor生成Html文件的目录名称,默认值:html
- ///
- public string GenerateHtmlFolder { get; set; } = "html";
- ///
- /// Razor生成Html页面的文件后缀,默认值:component.html
- ///
- public string GenerateHtmlSuffix { get; set; } = "component.html";
- ///
- /// Razor监听服务启动初始化的延迟时间,单位: 毫秒, 默认值:1000, 注意: 需要等待Web服务启动完成才能开始初始化
- ///
- public int StartInitDelay { get; set; } = 1000;
- ///
- /// 修改Razor页面生成Html文件的延迟时间,单位: 毫秒, 默认值:100 ,注意: 延迟太短可能导致生成异常
- ///
- public int HtmlRenderDelayOnRazorChange { get; set; } = 100;
///
/// 是否启用默认项文本,默认值: true
///
@@ -63,17 +36,9 @@ public NgZorroOptions() {
///
public bool EnableAllowClear { get; set; } = true;
///
- /// 是否启用Razor监视服务,默认值: true
- ///
- public bool EnableWatchRazor { get; set; } = true;
- ///
- /// 启动Razor监视服务时是否预热,默认值: true
- ///
- public bool EnablePreheat { get; set; } = true;
- ///
- /// Razor生成是否覆盖已存在的html文件,默认值: true
+ /// 是否启用勾选表格行复选框时添加样式类 table-row-checked ,默认值: false
///
- public bool EnableOverrideHtml { get; set; } = true;
+ public bool EnableTableRowCheckedClass { get; set; }
///
/// 获取表格布尔列内容操作
///
diff --git a/src/Util.Ui.NgZorro/WebApplicationExtensions.cs b/src/Util.Ui.NgZorro/WebApplicationExtensions.cs
index 00f19571d..ff6a14e06 100644
--- a/src/Util.Ui.NgZorro/WebApplicationExtensions.cs
+++ b/src/Util.Ui.NgZorro/WebApplicationExtensions.cs
@@ -20,11 +20,10 @@ public static class WebApplicationExtensions {
public static WebApplication UseNgZorro( this WebApplication app ) {
app.CheckNull( nameof( app ) );
AddEndpoints( app );
- if ( app.Environment.IsDevelopment() == false )
- return app;
app.UseAngular( spa => {
spa.Options.SourcePath = SourcePath;
- spa.UseAngularCliServer( "start" );
+ if ( app.Environment.IsDevelopment() )
+ spa.UseAngularCliServer( "start" );
} );
return app;
}
@@ -55,8 +54,12 @@ public static WebApplication UseNgZorro( this WebApplication app, Action {
+ if ( app.Environment.IsDevelopment() )
+ action( spa );
+ });
return app;
}
@@ -89,11 +92,10 @@ public static WebApplication UseNgZorro( this WebApplication app, int port, bool
private static WebApplication UseSpa( WebApplication app, string developmentServerBaseUri ) {
app.CheckNull( nameof( app ) );
AddEndpoints( app );
- if ( app.Environment.IsDevelopment() == false )
- return app;
app.UseSpa( spa => {
spa.Options.SourcePath = SourcePath;
- spa.UseProxyToSpaDevelopmentServer( developmentServerBaseUri );
+ if ( app.Environment.IsDevelopment() )
+ spa.UseProxyToSpaDevelopmentServer( developmentServerBaseUri );
} );
return app;
}
@@ -104,12 +106,11 @@ private static WebApplication UseSpa( WebApplication app, string developmentServ
private static WebApplication UseCustomSpa( WebApplication app, int port ) {
app.CheckNull( nameof( app ) );
AddEndpoints( app );
- if ( app.Environment.IsDevelopment() == false )
- return app;
app.UseAngular( spa => {
spa.Options.SourcePath = SourcePath;
spa.Options.DevServerPort = port;
- spa.UseAngularCliServer( "start" );
+ if ( app.Environment.IsDevelopment() )
+ spa.UseAngularCliServer( "start" );
} );
return app;
}
diff --git a/src/Util.Ui/Razor/GenerateHtmlFilter.cs b/src/Util.Ui/Razor/GenerateHtmlFilter.cs
index 8d9704078..72c0a1f4c 100644
--- a/src/Util.Ui/Razor/GenerateHtmlFilter.cs
+++ b/src/Util.Ui/Razor/GenerateHtmlFilter.cs
@@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
-using System.Globalization;
using Util.Helpers;
using File = System.IO.File;
@@ -60,12 +59,28 @@ protected virtual ILogger GetLogger( PageHandlerSelectedCont
private string CreatePath( PageHandlerSelectedContext context, RazorOptions options ) {
var attribute = context?.ActionDescriptor?.ModelTypeInfo?.GetCustomAttribute();
if ( attribute == null )
- return GetPath( context?.ActionDescriptor.ViewEnginePath, options.GenerateHtmlBasePath, options.GenerateHtmlFolder, options.GenerateHtmlSuffix );
+ return GetPath( context?.ActionDescriptor.ViewEnginePath, options );
if ( attribute.Ignore )
return string.Empty;
return string.IsNullOrWhiteSpace( attribute.Path ) ? string.Empty : attribute.Path;
}
+ ///
+ /// 获取Html文件路径
+ ///
+ /// 路径
+ /// 配置
+ public static string GetPath( string path, RazorOptions options ) {
+ if ( string.IsNullOrWhiteSpace( path ) )
+ return string.Empty;
+ if ( options.GenerateHtmlVersion == "v1" )
+ return GetPath( path, options.GenerateHtmlBasePath, options.GenerateHtmlFolder, options.GenerateHtmlSuffix );
+ if ( path.Contains( "/" ) == false )
+ return Util.Helpers.Url.JoinPath( options.RazorRootDirectory, options.GenerateHtmlFolder, $"{path}.html" );
+ var lastIndex = path.LastIndexOf( "/", StringComparison.Ordinal );
+ return Util.Helpers.Url.JoinPath( options.RazorRootDirectory, path.Substring( 0, lastIndex ), options.GenerateHtmlFolder, $"{path.Substring( lastIndex + 1 )}.html" );
+ }
+
///
/// 获取Html文件路径
///
diff --git a/src/Util.Ui/Razor/HtmlGenerator.cs b/src/Util.Ui/Razor/HtmlGenerator.cs
index e82e35cab..de0695da3 100644
--- a/src/Util.Ui/Razor/HtmlGenerator.cs
+++ b/src/Util.Ui/Razor/HtmlGenerator.cs
@@ -6,33 +6,6 @@ namespace Util.Ui.Razor;
/// Html生成器
///
public static class HtmlGenerator {
- ///
- /// 生成Html
- ///
- /// 视图路径
- /// 是否生成Html,默认值: true
- /// 取消令牌
- public static async Task GenerateAsync( string path, bool isGenerateHtml = true, CancellationToken cancellationToken = default ) {
- EnableGenerateHtml( isGenerateHtml );
- var requestPath = Url.JoinPath( GetHost(), "view", path.RemoveStart( "/Pages" ).RemoveEnd( ".cshtml" ) );
- return await Web.Client.Get( requestPath ).GetResultAsync( cancellationToken );
- }
-
- ///
- /// 启用Html自动生成
- ///
- private static void EnableGenerateHtml( bool isGenerateHtml = true ) {
- var options = Ioc.Create>();
- options.Value.IsGenerateHtml = isGenerateHtml;
- }
-
- ///
- /// 获取请求主机
- ///
- private static string GetHost() {
- return $"{Web.Request.Scheme}://{Web.Request.Host}";
- }
-
///
/// 生成Html
///
@@ -48,6 +21,14 @@ private static string GetHost() {
return result.Distinct().ToList();
}
+ ///
+ /// 启用Html自动生成
+ ///
+ private static void EnableGenerateHtml( bool isGenerateHtml = true ) {
+ var options = Ioc.Create>();
+ options.Value.IsGenerateHtml = isGenerateHtml;
+ }
+
///
/// 获取页面操作描述符列表
///
@@ -55,4 +36,11 @@ private static List GetPageActionDescriptors() {
var provider = Ioc.Create();
return provider.ActionDescriptors.Items.OfType().ToList();
}
+
+ ///
+ /// 获取请求主机
+ ///
+ private static string GetHost() {
+ return $"{Web.Request.Scheme}://{Web.Request.Host}";
+ }
}
\ No newline at end of file
diff --git a/src/Util.Ui/Razor/Internal/PartViewPathFinder.cs b/src/Util.Ui/Razor/Internal/PartViewPathFinder.cs
index ade465a8c..73ba55610 100644
--- a/src/Util.Ui/Razor/Internal/PartViewPathFinder.cs
+++ b/src/Util.Ui/Razor/Internal/PartViewPathFinder.cs
@@ -12,13 +12,19 @@ public class PartViewPathFinder : IPartViewPathFinder {
/// 视图引擎
///
private readonly ICompositeViewEngine _viewEngine;
+ ///
+ /// Razor配置
+ ///
+ private readonly RazorOptions _options;
///
/// 初始化分部视图路径查找器
///
/// 视图引擎
- public PartViewPathFinder( ICompositeViewEngine viewEngine ) {
+ /// Razor配置
+ public PartViewPathFinder( ICompositeViewEngine viewEngine, IOptions options ) {
_viewEngine = viewEngine ?? throw new ArgumentNullException( nameof( viewEngine ) );
+ _options = options.Value;
}
///
@@ -38,7 +44,7 @@ public string Find( string viewPath, string partViewName ) {
/// 获取路由值
///
private string GetRouteValue( string viewPath ) {
- return viewPath.RemoveStart( "/Pages" ).RemoveEnd( ".cshtml" );
+ return viewPath.RemoveStart( _options.RazorRootDirectory ).RemoveEnd( ".cshtml" );
}
///
diff --git a/src/Util.Ui/Razor/Internal/RazorViewContainer.cs b/src/Util.Ui/Razor/Internal/RazorViewContainer.cs
index 92d946129..032eaa1e1 100644
--- a/src/Util.Ui/Razor/Internal/RazorViewContainer.cs
+++ b/src/Util.Ui/Razor/Internal/RazorViewContainer.cs
@@ -63,7 +63,7 @@ public List GetRandomPaths() {
public RazorView FindView( string path ) {
if ( path.IsEmpty() )
return null;
- return _views.TryGetValue( path, out var view ) ? view : null;
+ return _views.TryGetValue( path.SafeString().ToLower(), out var view ) ? view : null;
}
///
@@ -73,7 +73,7 @@ public RazorView FindView( string path ) {
public void AddView( RazorView view ) {
if ( view == null )
return;
- _views.TryAdd( view.Path, view );
+ _views.TryAdd( view.Path.SafeString().ToLower(), view );
}
///
diff --git a/src/Util.Ui/Razor/RazorOptions.cs b/src/Util.Ui/Razor/RazorOptions.cs
index 2ca4395df..c8e86f41b 100644
--- a/src/Util.Ui/Razor/RazorOptions.cs
+++ b/src/Util.Ui/Razor/RazorOptions.cs
@@ -4,6 +4,18 @@
/// Razor配置
///
public class RazorOptions {
+ ///
+ /// Razor文件根路径,默认值: /ClientApp
+ ///
+ public string RazorRootDirectory { get; set; } = "/ClientApp";
+ ///
+ /// Spa静态文件根路径,默认值: ClientApp
+ ///
+ public string RootPath { get; set; } = "ClientApp";
+ ///
+ /// Razor页面生成html文件路径的版本,用于兼容传统使用方式,可选值: v1,v2, 如果需要退回到传统生成路径,传入 v1
+ ///
+ public string GenerateHtmlVersion { get; set; }
///
/// 是否在Razor页面运行时自动生成html文件
///
diff --git a/src/Util.Ui/Razor/RazorWatchService.cs b/src/Util.Ui/Razor/RazorWatchService.cs
index 719b7886d..d77a23b58 100644
--- a/src/Util.Ui/Razor/RazorWatchService.cs
+++ b/src/Util.Ui/Razor/RazorWatchService.cs
@@ -158,9 +158,9 @@ protected void EnableOverrideHtml( bool isOverrideHtml = true ) {
/// html是否存在
///
protected bool Exists( List htmlPaths, string razorPath ) {
- if ( string.Equals( razorPath, "/Pages/Error.cshtml", StringComparison.OrdinalIgnoreCase ) )
+ if ( string.Equals( razorPath, $"{_options.RazorRootDirectory}/Error.cshtml", StringComparison.OrdinalIgnoreCase ) )
return true;
- var path = GenerateHtmlFilter.GetPath( razorPath.RemoveStart( "/Pages" ).RemoveEnd( ".cshtml" ) );
+ var path = GenerateHtmlFilter.GetPath( razorPath.RemoveStart( _options.RazorRootDirectory ).RemoveEnd( ".cshtml" ), _options );
return htmlPaths.Any( t => t.Replace( "\\", "/" ).EndsWith( path, StringComparison.OrdinalIgnoreCase ) );
}
@@ -172,7 +172,7 @@ protected bool Exists( List htmlPaths, string razorPath ) {
/// 是否写入日志
public async Task Request( string path, CancellationToken cancellationToken = default, bool isWrite = true ) {
await Task.Delay( _options.HtmlRenderDelayOnRazorChange, cancellationToken );
- var requestPath = Url.JoinPath( GetApplicationUrl(), "view", path.RemoveStart( "/Pages" ).RemoveEnd( ".cshtml" ) );
+ var requestPath = Url.JoinPath( GetApplicationUrl(), "view", path.RemoveStart( _options.RazorRootDirectory ).RemoveEnd( ".cshtml" ) );
WriteLog( $"发送请求: {requestPath}", isWrite );
var response = await _client.GetAsync( requestPath, cancellationToken );
if ( response.IsSuccessStatusCode )
@@ -216,7 +216,7 @@ protected async Task Preheat( CancellationToken cancellationToken ) {
///
protected virtual Task StartWatch( CancellationToken cancellationToken ) {
WriteLog( "开始监听..." );
- var path = GetProjectPath( "Pages" );
+ var path = GetProjectPath( _options.RazorRootDirectory.RemoveStart( "/" ) );
_watcher.Path( path )
.Filter( "*.cshtml" )
.OnChangedAsync( async ( _, e ) => await GenerateAsync( e.FullPath, cancellationToken ) )
diff --git a/src/Util.Ui/Sources/Spa/Proxying/SpaProxyingExtensions.cs b/src/Util.Ui/Sources/Spa/Proxying/SpaProxyingExtensions.cs
index 281b2036d..9b29e846f 100644
--- a/src/Util.Ui/Sources/Spa/Proxying/SpaProxyingExtensions.cs
+++ b/src/Util.Ui/Sources/Spa/Proxying/SpaProxyingExtensions.cs
@@ -69,6 +69,10 @@ public static void UseProxyToSpaDevelopmentServer(
await next();
return;
}
+ if ( context.Request.Path.Value != null && context.Request.Path.Value.StartsWith( "/api/" ) ) {
+ await next();
+ return;
+ }
await SpaProxy.PerformProxyRequest(
context, neverTimeOutHttpClient, baseUriTaskFactory(), applicationStoppingToken,
proxy404s: true );
diff --git a/src/Util.Ui/Sources/Spa/SpaDefaultPageMiddleware.cs b/src/Util.Ui/Sources/Spa/SpaDefaultPageMiddleware.cs
index be3d1de23..32ba3f035 100644
--- a/src/Util.Ui/Sources/Spa/SpaDefaultPageMiddleware.cs
+++ b/src/Util.Ui/Sources/Spa/SpaDefaultPageMiddleware.cs
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Microsoft.Extensions.Hosting;
using Util.Ui.Sources.Spa.StaticFiles;
namespace Util.Ui.Sources.Spa;
@@ -34,18 +33,5 @@ public static void Attach(ISpaBuilder spaBuilder)
app.UseSpaStaticFilesInternal(
options.DefaultPageStaticFileOptions ?? new StaticFileOptions(),
allowFallbackOnServingWebRootFiles: true);
-
- // If the default file didn't get served as a static file (usually because it was not
- // present on disk), the SPA is definitely not going to work.
- //app.Use( async (context, next) =>
- //{
- // // If we have an Endpoint, then this is a deferred match - just noop.
- // if (context.GetEndpoint() != null)
- // {
- // await next(context);
- // }
- // await Task.Delay(100);
- // await next( context );
- //} );
}
}
diff --git a/test/Util.Ui.NgAlain.Tests/Startup.cs b/test/Util.Ui.NgAlain.Tests/Startup.cs
index e3502122e..f57e45a4d 100644
--- a/test/Util.Ui.NgAlain.Tests/Startup.cs
+++ b/test/Util.Ui.NgAlain.Tests/Startup.cs
@@ -12,13 +12,14 @@ public class Startup {
///
///
public void ConfigureHost( IHostBuilder hostBuilder ) {
- hostBuilder.ConfigureDefaults( null ).AddUtil();
- }
+ hostBuilder.ConfigureDefaults( null ).AddUtil();
+ Util.Helpers.Environment.IsTest = true;
+ }
///
/// ÷
///
public void ConfigureServices( IServiceCollection services ) {
- services.AddLogging( logBuilder => logBuilder.AddXunitOutput() );
- }
+ services.AddLogging( logBuilder => logBuilder.AddXunitOutput() );
+ }
}
\ No newline at end of file
diff --git a/test/Util.Ui.NgZorro.Tests/Links/ATagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/Links/ATagHelperTest.cs
index d061ca8c3..726d980d8 100644
--- a/test/Util.Ui.NgZorro.Tests/Links/ATagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/Links/ATagHelperTest.cs
@@ -2,6 +2,7 @@
using Util.Ui.Angular.Configs;
using Util.Ui.Configs;
using Util.Ui.Enums;
+using Util.Ui.NgZorro.Components.Forms.Configs;
using Util.Ui.NgZorro.Components.Links;
using Util.Ui.NgZorro.Configs;
using Util.Ui.NgZorro.Enums;
@@ -326,11 +327,17 @@ public void TestSpaceItem() {
}
///
- /// 测试查询表单链接
+ /// 测试查询表单链接 - 查询条件数量超过初始显示数量则显示
///
[Fact]
- public void TestIsSearch() {
+ public void TestIsSearch_1() {
_wrapper.SetContextAttribute( UiConst.IsSearch, true );
+ var formShareConfig = new FormShareConfig { SearchFormShowNumber = 1 };
+ formShareConfig.AddColumnId( "a" );
+ formShareConfig.AddColumnId( "b" );
+ formShareConfig.AddColumnId( "action" );
+ _wrapper.SetItem( formShareConfig );
+
var result = new StringBuilder();
result.Append( "" );
result.Append( "{{expand?'收起':'展开'}}" );
@@ -340,12 +347,18 @@ public void TestIsSearch() {
}
///
- /// 测试查询表单链接 - 多语言
+ /// 测试查询表单链接 - 查询条件数量超过初始显示数量则显示 - 多语言
///
[Fact]
- public void TestIsSearch_i18n() {
+ public void TestIsSearch_2() {
NgZorroOptionsService.SetOptions( new NgZorroOptions { EnableI18n = true } );
_wrapper.SetContextAttribute( UiConst.IsSearch, true );
+ var formShareConfig = new FormShareConfig { SearchFormShowNumber = 1 };
+ formShareConfig.AddColumnId( "a" );
+ formShareConfig.AddColumnId( "b" );
+ formShareConfig.AddColumnId( "action" );
+ _wrapper.SetItem( formShareConfig );
+
var result = new StringBuilder();
result.Append( "" );
result.Append( "{{expand?('util.collapse'|i18n):('util.expand'|i18n)}}" );
@@ -354,6 +367,20 @@ public void TestIsSearch_i18n() {
Assert.Equal( result.ToString(), GetResult() );
}
+ ///
+ /// 测试查询表单链接 - 查询条件数量少于等于初始显示数量则不显示
+ ///
+ [Fact]
+ public void TestIsSearch_3() {
+ _wrapper.SetContextAttribute( UiConst.IsSearch, true );
+ var formShareConfig = new FormShareConfig { SearchFormShowNumber = 2 };
+ formShareConfig.AddColumnId( "a" );
+ formShareConfig.AddColumnId( "b" );
+ formShareConfig.AddColumnId( "action" );
+ _wrapper.SetItem( formShareConfig );
+ Assert.Empty( GetResult() );
+ }
+
///
/// 测试显示表格设置
///
diff --git a/test/Util.Ui.NgZorro.Tests/Tables/TableRowTagHelperTest.cs b/test/Util.Ui.NgZorro.Tests/Tables/TableRowTagHelperTest.cs
index 540829a53..84358fb49 100644
--- a/test/Util.Ui.NgZorro.Tests/Tables/TableRowTagHelperTest.cs
+++ b/test/Util.Ui.NgZorro.Tests/Tables/TableRowTagHelperTest.cs
@@ -2,11 +2,12 @@
using Util.Helpers;
using Util.Ui.Configs;
using Util.Ui.NgZorro.Components.Tables;
+using Util.Ui.NgZorro.Configs;
using Util.Ui.TagHelpers;
using Xunit;
using Xunit.Abstractions;
-namespace Util.Ui.NgZorro.Tests.Tables;
+namespace Util.Ui.NgZorro.Tests.Tables;
///
/// 表格行测试
@@ -106,6 +107,17 @@ public void TestSelectOnlyOnClick_2() {
Assert.Equal( result.ToString(), GetResult() );
}
+ ///
+ /// 测试勾选样式
+ ///
+ [Fact]
+ public void TestEnableTableRowCheckedClass() {
+ NgZorroOptionsService.SetOptions( new NgZorroOptions { EnableTableRowCheckedClass = true } );
+ var result = new StringBuilder();
+ result.Append( "
" );
+ Assert.Equal( result.ToString(), GetResult() );
+ }
+
///
/// 测试行单击事件
///
diff --git a/test/Util.Ui.Tests/Razor/GenerateHtmlFilterTest.cs b/test/Util.Ui.Tests/Razor/GenerateHtmlFilterTest.cs
index 6d97e6e00..0c83964cd 100644
--- a/test/Util.Ui.Tests/Razor/GenerateHtmlFilterTest.cs
+++ b/test/Util.Ui.Tests/Razor/GenerateHtmlFilterTest.cs
@@ -104,5 +104,27 @@ public void TestGetPath_11() {
var result = GenerateHtmlFilter.GetPath( "FetchData/Test/NavMenu", "/a", htmlSuffix: "html" );
Assert.Equal( "/a/fetch-data/test/html/nav-menu.html", result );
}
+
+ ///
+ /// Razor生成版本为 v1 ,使用传统生成路径逻辑
+ ///
+ [Fact]
+ public void TestGetPath_12() {
+ var options = new RazorOptions {
+ GenerateHtmlVersion = "v1"
+ };
+ var result = GenerateHtmlFilter.GetPath( "FetchData/Test/NavMenu", options );
+ Assert.Equal( "/ClientApp/src/app/fetch-data/test/html/nav-menu.component.html", result );
+ }
+
+ ///
+ /// Razor生成版本不为 v1 ,使用新的生成路径逻辑
+ ///
+ [Fact]
+ public void TestGetPath_13() {
+ var options = new RazorOptions();
+ var result = GenerateHtmlFilter.GetPath( "src/app/fetch-data/test/nav-menu.component", options );
+ Assert.Equal( "/ClientApp/src/app/fetch-data/test/html/nav-menu.component.html", result );
+ }
}
}