mirror of
				https://gitee.com/ThingsGateway/ThingsGateway.git
				synced 2025-10-31 15:43:59 +08:00 
			
		
		
		
	Compare commits
	
		
			48 Commits
		
	
	
		
			10.11.40.0
			...
			10.11.101.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 1bad65378f | ||
|   | db3affc67e | ||
|   | 5ee8b50a92 | ||
|   | 301beda2a2 | ||
|   | 628b51a353 | ||
|   | f03445bc83 | ||
|   | 55a2ff5487 | ||
|   | 0fef7dcf3b | ||
|   | 19d9702606 | ||
|   | a8a9774932 | ||
|   | aad0f0e8c3 | ||
|   | e74eae50a7 | ||
|   | 3b16d7019f | ||
|   | 3e038028c2 | ||
|   | b1d8041f7e | ||
|   | 53a98b26cd | ||
|   | 42c740fa1b | ||
|   | 556819c90c | ||
|   | 2522333a9c | ||
|   | bd4ce7c09b | ||
|   | 156ed88bd6 | ||
|   | 2416226eb0 | ||
|   | 976323a716 | ||
|   | 3c9e397403 | ||
|   | 79406ad4a0 | ||
|   | 20c44f10ca | ||
|   | 31d6b2a9e6 | ||
|   | 68e5a9c546 | ||
|   | b2ea9f99b9 | ||
|   | 6d7d0e468a | ||
|   | ff1f632de2 | ||
|   | fc3d7015ee | ||
|   | 40c5acb522 | ||
|   | f9cc1cbb05 | ||
|   | cf6e8b58f0 | ||
|   | 615e3bb24c | ||
|   | 4a7534b210 | ||
|   | 58e099cb93 | ||
|   | a94a9c953c | ||
|   | 35e1ffa3e9 | ||
|   | 4921642151 | ||
|   | d71ee29da8 | ||
|   | 901aa2d59f | ||
|   | 764957c014 | ||
|   | 0e3898218b | ||
|   | 61f13cef3c | ||
|   | 0b663d9e01 | ||
|   | 6c95c6209f | 
| @@ -45,6 +45,7 @@ public class VerificatInfo : PrimaryIdEntity | |||||||
|     /// 登录IP |     /// 登录IP | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     [AutoGenerateColumn(Filterable = true, Sortable = true, Width = 200)] |     [AutoGenerateColumn(Filterable = true, Sortable = true, Width = 200)] | ||||||
|  |     [SugarColumn(IsNullable = true)] | ||||||
|     public string LoginIp { get; set; } |     public string LoginIp { get; set; } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
| @@ -78,5 +79,6 @@ public class VerificatInfo : PrimaryIdEntity | |||||||
|     /// 登录设备 |     /// 登录设备 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     [AutoGenerateColumn(Filterable = true, Sortable = true, Width = 100)] |     [AutoGenerateColumn(Filterable = true, Sortable = true, Width = 100)] | ||||||
|  |     [SugarColumn(IsNullable = true)] | ||||||
|     public string Device { get; set; } |     public string Device { get; set; } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
| using Riok.Mapperly.Abstractions; | using Riok.Mapperly.Abstractions; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Admin.Application; | namespace ThingsGateway.Admin.Application; | ||||||
|  |  | ||||||
| [Mapper(UseDeepCloning = true, EnumMappingStrategy = EnumMappingStrategy.ByName, RequiredMappingStrategy = RequiredMappingStrategy.None)] | [Mapper(UseDeepCloning = true, EnumMappingStrategy = EnumMappingStrategy.ByName, RequiredMappingStrategy = RequiredMappingStrategy.None)] | ||||||
| public static partial class AdminMapper | public static partial class AdminMapper | ||||||
| { | { | ||||||
|   | |||||||
| @@ -145,7 +145,7 @@ public class AdminOAuthHandler<TOptions>( | |||||||
|         var loginEvent = new LoginEvent |         var loginEvent = new LoginEvent | ||||||
|         { |         { | ||||||
|             Ip = appService.RemoteIpAddress, |             Ip = appService.RemoteIpAddress, | ||||||
|             Device = appService.UserAgent?.Platform, |             Device = appService.UserAgent?.Platform ?? "Unknown", | ||||||
|             Expire = expire, |             Expire = expire, | ||||||
|             SysUser = sysUser, |             SysUser = sysUser, | ||||||
|             VerificatId = CommonUtils.GetSingleId() |             VerificatId = CommonUtils.GetSingleId() | ||||||
| @@ -156,7 +156,7 @@ public class AdminOAuthHandler<TOptions>( | |||||||
|         //生成verificat信息 |         //生成verificat信息 | ||||||
|         var verificatInfo = new VerificatInfo |         var verificatInfo = new VerificatInfo | ||||||
|         { |         { | ||||||
|             Device = loginEvent.Device, |             Device = loginEvent.Device ?? "Unknown", | ||||||
|             Expire = loginEvent.Expire, |             Expire = loginEvent.Expire, | ||||||
|             VerificatTimeout = tokenTimeout, |             VerificatTimeout = tokenTimeout, | ||||||
|             Id = loginEvent.VerificatId, |             Id = loginEvent.VerificatId, | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ | |||||||
|       "Module": 2, |       "Module": 2, | ||||||
|       "Title": "权限管理", |       "Title": "权限管理", | ||||||
|       "Code": "System", |       "Code": "System", | ||||||
|       "NavLinkMatch": "All", |       "NavLinkMatch": "Prefix", | ||||||
|       "Category": "MENU", |       "Category": "MENU", | ||||||
|       "Target": "_self", |       "Target": "_self", | ||||||
|       "Href": null, |       "Href": null, | ||||||
| @@ -47,7 +47,7 @@ | |||||||
|       "ParentId": 0, |       "ParentId": 0, | ||||||
|       "Module": 2, |       "Module": 2, | ||||||
|       "Title": "系统运维", |       "Title": "系统运维", | ||||||
|       "NavLinkMatch": "All", |       "NavLinkMatch": "Prefix", | ||||||
|       "Code": "System", |       "Code": "System", | ||||||
|       "Category": "MENU", |       "Category": "MENU", | ||||||
|       "Target": "_self", |       "Target": "_self", | ||||||
|   | |||||||
| @@ -235,7 +235,7 @@ public class AuthService : IAuthService | |||||||
|         var logingEvent = new LoginEvent |         var logingEvent = new LoginEvent | ||||||
|         { |         { | ||||||
|             Ip = _appService.RemoteIpAddress, |             Ip = _appService.RemoteIpAddress, | ||||||
|             Device = _appService.UserAgent?.Platform, |             Device = _appService.UserAgent?.Platform ?? "Unknown", | ||||||
|             Expire = expire, |             Expire = expire, | ||||||
|             SysUser = sysUser, |             SysUser = sysUser, | ||||||
|             VerificatId = verificatId |             VerificatId = verificatId | ||||||
| @@ -344,7 +344,7 @@ public class AuthService : IAuthService | |||||||
|         //生成verificat信息 |         //生成verificat信息 | ||||||
|         var verificatInfo = new VerificatInfo |         var verificatInfo = new VerificatInfo | ||||||
|         { |         { | ||||||
|             Device = loginEvent.Device, |             Device = loginEvent.Device ?? "Unknown", | ||||||
|             Expire = loginEvent.Expire, |             Expire = loginEvent.Expire, | ||||||
|             VerificatTimeout = tokenTimeout, |             VerificatTimeout = tokenTimeout, | ||||||
|             Id = loginEvent.VerificatId, |             Id = loginEvent.VerificatId, | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| namespace ThingsGateway.Admin.Application; | namespace ThingsGateway.Admin.Application; | ||||||
|  |  | ||||||
| internal sealed class NoticeService : INoticeService | internal sealed class NoticeService : INoticeService | ||||||
| { | { | ||||||
|     private IEventService<AppMessage>? MessageDispatchService { get; set; } |     private IEventService<AppMessage>? MessageDispatchService { get; set; } | ||||||
|   | |||||||
| @@ -282,7 +282,7 @@ internal sealed class SysRoleService : BaseService<SysRole>, ISysRoleService | |||||||
|         if (sysRole != null) |         if (sysRole != null) | ||||||
|         { |         { | ||||||
|             var resources = await _sysResourceService.GetAllAsync().ConfigureAwait(false); |             var resources = await _sysResourceService.GetAllAsync().ConfigureAwait(false); | ||||||
|             var menusList = resources.Where(a => a.Category == ResourceCategoryEnum.Menu).Where(a => menuIds.Contains(a.Id)); |             var menusList = resources.Where(a => a.Category == ResourceCategoryEnum.Menu && menuIds.Contains(a.Id)); | ||||||
|  |  | ||||||
|             #region 角色模块处理 |             #region 角色模块处理 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -550,7 +550,7 @@ internal sealed class SysUserService : BaseService<SysUser>, ISysUserService | |||||||
|         if (sysUser != null) |         if (sysUser != null) | ||||||
|         { |         { | ||||||
|             var resources = await _sysResourceService.GetAllAsync().ConfigureAwait(false); |             var resources = await _sysResourceService.GetAllAsync().ConfigureAwait(false); | ||||||
|             var menusList = resources.Where(a => a.Category == ResourceCategoryEnum.Menu).Where(a => menuIds.Contains(a.Id)); |             var menusList = resources.Where(a => a.Category == ResourceCategoryEnum.Menu && menuIds.Contains(a.Id)); | ||||||
|  |  | ||||||
|             #region 用户模块处理 |             #region 用户模块处理 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -119,7 +119,7 @@ internal sealed class VerificatInfoService : BaseService<VerificatInfo>, IVerifi | |||||||
|     public void Add(VerificatInfo verificatInfo) |     public void Add(VerificatInfo verificatInfo) | ||||||
|     { |     { | ||||||
|         using var db = GetDB(); |         using var db = GetDB(); | ||||||
|         db.Insertable<VerificatInfo>(verificatInfo).ExecuteCommand(); |         db.InsertableT<VerificatInfo>(verificatInfo).ExecuteCommand(); | ||||||
|         VerificatInfoService.RemoveCache(verificatInfo.Id); |         VerificatInfoService.RemoveCache(verificatInfo.Id); | ||||||
|         if (verificatInfo != null) |         if (verificatInfo != null) | ||||||
|             VerificatInfoService.SetCahce(verificatInfo); |             VerificatInfoService.SetCahce(verificatInfo); | ||||||
| @@ -132,7 +132,7 @@ internal sealed class VerificatInfoService : BaseService<VerificatInfo>, IVerifi | |||||||
|     public void Update(VerificatInfo verificatInfo) |     public void Update(VerificatInfo verificatInfo) | ||||||
|     { |     { | ||||||
|         using var db = GetDB(); |         using var db = GetDB(); | ||||||
|         db.Updateable<VerificatInfo>(verificatInfo).ExecuteCommand(); |         db.UpdateableT<VerificatInfo>(verificatInfo).ExecuteCommand(); | ||||||
|         VerificatInfoService.RemoveCache(verificatInfo.Id); |         VerificatInfoService.RemoveCache(verificatInfo.Id); | ||||||
|         if (verificatInfo != null) |         if (verificatInfo != null) | ||||||
|             VerificatInfoService.SetCahce(verificatInfo); |             VerificatInfoService.SetCahce(verificatInfo); | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
| 		 | 		 | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
| 		<TargetFrameworks>net8.0;net9.0;</TargetFrameworks> | 		<TargetFrameworks>net8.0;$(OtherTargetFrameworks);</TargetFrameworks> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
|  |  | ||||||
| 	<ItemGroup> | 	<ItemGroup> | ||||||
| @@ -20,7 +20,7 @@ | |||||||
| 	 | 	 | ||||||
| 	<ItemGroup> | 	<ItemGroup> | ||||||
| 		<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" /> | 		<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" /> | ||||||
| 		<PackageReference Include="Rougamo.Fody" Version="5.0.1" /> | 		<PackageReference Include="Rougamo.Fody" Version="5.0.2" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
| 	<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' "> | 	<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' "> | ||||||
| 		<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" /> | 		<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" /> | ||||||
| @@ -28,10 +28,10 @@ | |||||||
| 		<PackageReference Include="System.Threading.RateLimiting" Version="8.0.0" /> | 		<PackageReference Include="System.Threading.RateLimiting" Version="8.0.0" /> | ||||||
|  |  | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
| 	<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' "> | 	<ItemGroup Condition=" '$(TargetFramework)' == 'net10.0' "> | ||||||
| 		<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(NET9Version)" /> | 		<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(NET10Version)" /> | ||||||
| 		<PackageReference Include="System.Formats.Asn1" Version="$(NET9Version)" /> | 		<PackageReference Include="System.Formats.Asn1" Version="$(NET10Version)" /> | ||||||
| 		<PackageReference Include="System.Threading.RateLimiting" Version="$(NET9Version)" /> | 		<PackageReference Include="System.Threading.RateLimiting" Version="$(NET10Version)" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
| 	<ItemGroup> | 	<ItemGroup> | ||||||
| 		<Content Remove="SeedData\Admin\*.json" /> | 		<Content Remove="SeedData\Admin\*.json" /> | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ | |||||||
|  |  | ||||||
| <div class="tg-table h-100"> | <div class="tg-table h-100"> | ||||||
|  |  | ||||||
|     <Table TItem="TItem" IsBordered="true" IsStriped="true" TableSize="TableSize.Compact" IsMultipleSelect="IsMultipleSelect" @ref="Instance" SearchTemplate="SearchTemplate" |     <Table TItem="TItem" IsBordered="true" IsStriped="true" TableSize="TableSize.Compact" SelectedRows=SelectedRows SelectedRowsChanged=privateSelectedRowsChanged IsMultipleSelect="IsMultipleSelect" @ref="Instance" SearchTemplate="SearchTemplate" | ||||||
|            DataService="DataService" CreateItemCallback="CreateItemCallback!" |            DataService="DataService" CreateItemCallback="CreateItemCallback!" RenderMode=RenderMode | ||||||
|            IsPagination="IsPagination" PageItemsSource="PageItemsSource" IsFixedHeader="IsFixedHeader" IndentSize=24 RowHeight=RowHeight ShowSearchText="ShowSearchText" ShowSearchButton="ShowSearchButton" DisableEditButtonCallback="DisableEditButtonCallback" DisableDeleteButtonCallback="DisableDeleteButtonCallback" BeforeShowEditDialogCallback=" BeforeShowEditDialogCallback!" |            IsPagination="IsPagination" PageItemsSource="PageItemsSource" IsFixedHeader="IsFixedHeader" IndentSize=24 RowHeight=RowHeight ShowSearchText="ShowSearchText" ShowSearchButton="ShowSearchButton" DisableEditButtonCallback="DisableEditButtonCallback" DisableDeleteButtonCallback="DisableDeleteButtonCallback" BeforeShowEditDialogCallback=" BeforeShowEditDialogCallback!" | ||||||
|            IsTree="IsTree" OnTreeExpand="OnTreeExpand!" TreeNodeConverter="TreeNodeConverter!" TreeIcon="fa-solid fa-circle-chevron-right" TreeExpandIcon="fa-solid fa-circle-chevron-right fa-rotate-90" IsAutoQueryFirstRender=IsAutoQueryFirstRender |            IsTree="IsTree" OnTreeExpand="OnTreeExpand!" TreeNodeConverter="TreeNodeConverter!" TreeIcon="fa-solid fa-circle-chevron-right" TreeExpandIcon="fa-solid fa-circle-chevron-right fa-rotate-90" IsAutoQueryFirstRender=IsAutoQueryFirstRender | ||||||
|            ShowDefaultButtons="ShowDefaultButtons" ShowAdvancedSearch="ShowAdvancedSearch" ShowResetButton=ShowResetButton |            ShowDefaultButtons="ShowDefaultButtons" ShowAdvancedSearch="ShowAdvancedSearch" ShowResetButton=ShowResetButton | ||||||
| @@ -41,6 +41,7 @@ | |||||||
|            DoubleClickToEdit="DoubleClickToEdit" |            DoubleClickToEdit="DoubleClickToEdit" | ||||||
|            OnDoubleClickCellCallback="OnDoubleClickCellCallback" |            OnDoubleClickCellCallback="OnDoubleClickCellCallback" | ||||||
|            OnDoubleClickRowCallback="OnDoubleClickRowCallback" |            OnDoubleClickRowCallback="OnDoubleClickRowCallback" | ||||||
|  |            RowContentTemplate="RowContentTemplate" | ||||||
|            OnClickRowCallback="OnClickRowCallback"> |            OnClickRowCallback="OnClickRowCallback"> | ||||||
|     </Table> |     </Table> | ||||||
| </div> | </div> | ||||||
|   | |||||||
| @@ -13,6 +13,32 @@ namespace ThingsGateway.Admin.Razor; | |||||||
| [CascadingTypeParameter(nameof(TItem))] | [CascadingTypeParameter(nameof(TItem))] | ||||||
| public partial class AdminTable<TItem> where TItem : class, new() | public partial class AdminTable<TItem> where TItem : class, new() | ||||||
| { | { | ||||||
|  |  | ||||||
|  |     /// <inheritdoc cref="Table{TItem}.RenderMode"/> | ||||||
|  |     [Parameter] | ||||||
|  |     public TableRenderMode RenderMode { get; set; } | ||||||
|  |  | ||||||
|  |     public List<ITableColumn> Columns => Instance?.Columns; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /// <inheritdoc cref="Table{TItem}.SelectedRowsChanged"/> | ||||||
|  |     [Parameter] | ||||||
|  |     public EventCallback<List<TItem>> SelectedRowsChanged { get; set; } | ||||||
|  |  | ||||||
|  |     /// <inheritdoc cref="Table{TItem}.SelectedRows"/> | ||||||
|  |     [Parameter] | ||||||
|  |     public List<TItem> SelectedRows { get; set; } = new(); | ||||||
|  |  | ||||||
|  |     private async Task privateSelectedRowsChanged(List<TItem> items) | ||||||
|  |     { | ||||||
|  |         SelectedRows = items; | ||||||
|  |         if (SelectedRowsChanged.HasDelegate) | ||||||
|  |             await SelectedRowsChanged.InvokeAsync(items); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     /// <inheritdoc cref="Table{TItem}.DoubleClickToEdit"/> |     /// <inheritdoc cref="Table{TItem}.DoubleClickToEdit"/> | ||||||
|     [Parameter] |     [Parameter] | ||||||
|     public bool DoubleClickToEdit { get; set; } = false; |     public bool DoubleClickToEdit { get; set; } = false; | ||||||
| @@ -22,6 +48,10 @@ public partial class AdminTable<TItem> where TItem : class, new() | |||||||
|     /// <inheritdoc cref="Table{TItem}.OnDoubleClickRowCallback"/> |     /// <inheritdoc cref="Table{TItem}.OnDoubleClickRowCallback"/> | ||||||
|     [Parameter] |     [Parameter] | ||||||
|     public Func<TItem, Task>? OnDoubleClickRowCallback { get; set; } |     public Func<TItem, Task>? OnDoubleClickRowCallback { get; set; } | ||||||
|  |     /// <inheritdoc cref="Table{TItem}.RowContentTemplate"/> | ||||||
|  |     [Parameter] | ||||||
|  |     public RenderFragment<TableRowContext<TItem>>? RowContentTemplate { get; set; } | ||||||
|  |  | ||||||
|     /// <inheritdoc cref="Table{TItem}.OnClickRowCallback"/> |     /// <inheritdoc cref="Table{TItem}.OnClickRowCallback"/> | ||||||
|     [Parameter] |     [Parameter] | ||||||
|     public Func<TItem, Task>? OnClickRowCallback { get; set; } |     public Func<TItem, Task>? OnClickRowCallback { get; set; } | ||||||
|   | |||||||
| @@ -125,13 +125,22 @@ public class BlazorAppContext | |||||||
|             var ownMenus = OwnMenus.Where(a => a.Module == CurrentModuleId); |             var ownMenus = OwnMenus.Where(a => a.Module == CurrentModuleId); | ||||||
|             OwnMenuItems = AdminResourceUtil.BuildMenuTrees(ownMenus).ToList(); |             OwnMenuItems = AdminResourceUtil.BuildMenuTrees(ownMenus).ToList(); | ||||||
|             AllOwnMenuItems = AdminResourceUtil.BuildMenuTrees(OwnMenus).ToList(); |             AllOwnMenuItems = AdminResourceUtil.BuildMenuTrees(OwnMenus).ToList(); | ||||||
|             OwnSameLevelMenuItems = ownMenus.Where(a => !a.Href.IsNullOrWhiteSpace()).Select(item => new MenuItem() |             OwnSameLevelMenuItems = ownMenus.Where(a => !a.Href.IsNullOrWhiteSpace()).Select(item => | ||||||
|             { |             { | ||||||
|                 Match = item.NavLinkMatch ?? Microsoft.AspNetCore.Components.Routing.NavLinkMatch.All, |                 var menu = new MenuItem() | ||||||
|  |                 { | ||||||
|  |                     Match = item.NavLinkMatch ?? Microsoft.AspNetCore.Components.Routing.NavLinkMatch.Prefix, | ||||||
|                     Text = item.Title, |                     Text = item.Title, | ||||||
|                     Icon = item.Icon, |                     Icon = item.Icon, | ||||||
|                     Url = item.Href, |                     Url = item.Href, | ||||||
|                     Target = item.Target.ToString(), |                     Target = item.Target.ToString(), | ||||||
|  |                 }; | ||||||
|  |                 if (menu.Url.IsNullOrEmpty()) | ||||||
|  |                 { | ||||||
|  |                     menu.Match = Microsoft.AspNetCore.Components.Routing.NavLinkMatch.Prefix; | ||||||
|  |                 } | ||||||
|  |                 return menu; | ||||||
|  |  | ||||||
|             }).ToList(); |             }).ToList(); | ||||||
|             UserWorkbenchOutputs = AllMenus.Where(it => UserWorkBench.Shortcuts.Contains(it.Id)).ToList(); |             UserWorkbenchOutputs = AllMenus.Where(it => UserWorkBench.Shortcuts.Contains(it.Id)).ToList(); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ | |||||||
|         </Card> |         </Card> | ||||||
|  |  | ||||||
|     </div> |     </div> | ||||||
|     <div class="col-12 col-sm-10 h-100"> |     <div class="col-12 col-sm-10 h-100 ps-2"> | ||||||
|     <AdminTable @ref=table TItem="SysUser" |     <AdminTable @ref=table TItem="SysUser" | ||||||
|         AutoGenerateColumns="true" |         AutoGenerateColumns="true" | ||||||
|         ShowAdvancedSearch=false |         ShowAdvancedSearch=false | ||||||
|   | |||||||
| @@ -20,5 +20,6 @@ public class Startup : AppStartup | |||||||
|         services.AddScoped<IMenuService, MenuService>(); |         services.AddScoped<IMenuService, MenuService>(); | ||||||
|         services.AddScoped<IAuthRazorService, AuthRazorService>(); |         services.AddScoped<IAuthRazorService, AuthRazorService>(); | ||||||
|         services.AddBootstrapBlazorTableExportService(); |         services.AddBootstrapBlazorTableExportService(); | ||||||
|  |         services.AddBootstrapBlazorWinBoxService(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,19 +5,21 @@ | |||||||
|  |  | ||||||
| 	<ItemGroup> | 	<ItemGroup> | ||||||
| 		<ProjectReference Include="..\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj" /> | 		<ProjectReference Include="..\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj" /> | ||||||
| 		<PackageReference Include="BootstrapBlazor.Chart" Version="9.0.0" /> | 		<PackageReference Include="BootstrapBlazor.Chart" Version="9.0.3" /> | ||||||
| 		<PackageReference Include="BootstrapBlazor.UniverSheet" Version="9.0.5" /> | 		<PackageReference Include="BootstrapBlazor.UniverSheet" Version="9.0.5" /> | ||||||
|  | 		<PackageReference Include="BootstrapBlazor.WinBox" Version="9.0.7" /> | ||||||
|  | 		<PackageReference Include="BootstrapBlazor.CodeEditor" Version="9.0.3" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
|  |  | ||||||
| 	<ItemGroup Condition="'$(TargetFramework)'=='net8.0'"> | 	<ItemGroup Condition="'$(TargetFramework)'=='net8.0'"> | ||||||
| 		<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="$(NET8Version)" /> | 		<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="$(NET8Version)" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
| 	<ItemGroup Condition="'$(TargetFramework)'=='net9.0'"> | 	<ItemGroup Condition="'$(TargetFramework)'=='net10.0'"> | ||||||
| 		<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="$(NET9Version)" /> | 		<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="$(NET10Version)" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
|  |  | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
| 		<TargetFrameworks>net8.0;net9.0</TargetFrameworks> | 		<TargetFrameworks>net8.0;$(OtherTargetFrameworks);</TargetFrameworks> | ||||||
| 		 | 		 | ||||||
| 		<!--<UseRazorSourceGenerator>false</UseRazorSourceGenerator>--> | 		<!--<UseRazorSourceGenerator>false</UseRazorSourceGenerator>--> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
|   | |||||||
| @@ -41,14 +41,21 @@ public static class AdminResourceUtil | |||||||
|         return items |         return items | ||||||
|         .Where(it => it.ParentId == parentId) |         .Where(it => it.ParentId == parentId) | ||||||
|         .Select((item, index) => |         .Select((item, index) => | ||||||
|             new MenuItem() |  | ||||||
|         { |         { | ||||||
|                 Match = item.NavLinkMatch ?? Microsoft.AspNetCore.Components.Routing.NavLinkMatch.All, |             var menu = new MenuItem() | ||||||
|  |             { | ||||||
|  |                 Match = item.NavLinkMatch ?? Microsoft.AspNetCore.Components.Routing.NavLinkMatch.Prefix, | ||||||
|                 Text = item.Title, |                 Text = item.Title, | ||||||
|                 Icon = item.Icon, |                 Icon = item.Icon, | ||||||
|                 Url = item.Href, |                 Url = item.Href, | ||||||
|                 Target = item.Target.ToString(), |                 Target = item.Target.ToString(), | ||||||
|                 Items = BuildMenuTrees(items, item.Id).ToList() |                 Items = BuildMenuTrees(items, item.Id).ToList() | ||||||
|  |             }; | ||||||
|  |             if (menu.Url.IsNullOrEmpty()) | ||||||
|  |             { | ||||||
|  |                 menu.Match = Microsoft.AspNetCore.Components.Routing.NavLinkMatch.Prefix; | ||||||
|  |             } | ||||||
|  |             return menu; | ||||||
|         } |         } | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -21,11 +21,13 @@ | |||||||
|     <link rel="apple-touch-icon" href="favicon.png"> |     <link rel="apple-touch-icon" href="favicon.png"> | ||||||
|     <base href="/" /> |     <base href="/" /> | ||||||
|     <title>ThingsGateway</title> |     <title>ThingsGateway</title> | ||||||
|     <link rel="stylesheet" href=@($"_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css?v={this.GetType().Assembly.GetName().Version}") /> |     <link rel="stylesheet" href=@($"_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css") /> | ||||||
|     <link rel="stylesheet" href=@($"_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css?v={this.GetType().Assembly.GetName().Version}") /> |     <link rel="stylesheet" href=@($"_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css") /> | ||||||
|     <link rel="stylesheet" href=@($"_content/BootstrapBlazor/css/motronic.min.css?v={this.GetType().Assembly.GetName().Version}") /> |     <link rel="stylesheet" href=@($"_content/BootstrapBlazor/css/motronic.min.css") /> | ||||||
|     <link rel="stylesheet" href=@($"ThingsGateway.AdminServer.styles.css?v={this.GetType().Assembly.GetName().Version}") /> |     <link rel="stylesheet" href=@($"ThingsGateway.AdminServer.styles.css") /> | ||||||
|     <link rel="stylesheet" href=@($"{WebsiteConst.DefaultResourceUrl}css/site.css?v={this.GetType().Assembly.GetName().Version}") /> |     <link rel="stylesheet" href=@($"{WebsiteConst.DefaultResourceUrl}css/site.css") /> | ||||||
|  |     <link rel="stylesheet" href=@($"{WebsiteConst.DefaultResourceUrl}css/devui.css") /> | ||||||
|  |  | ||||||
|     @* <script src=@($"{WebsiteConst.DefaultResourceUrl}js/theme.js") type="module"></script><!-- 初始主题 --> *@ |     @* <script src=@($"{WebsiteConst.DefaultResourceUrl}js/theme.js") type="module"></script><!-- 初始主题 --> *@ | ||||||
|     <!-- PWA Manifest --> |     <!-- PWA Manifest --> | ||||||
|     <link rel="manifest" href="./manifest.json" /> |     <link rel="manifest" href="./manifest.json" /> | ||||||
| @@ -38,12 +40,13 @@ | |||||||
|  |  | ||||||
|     <BlazorReconnector @rendermode="new InteractiveServerRenderMode(false)" /> |     <BlazorReconnector @rendermode="new InteractiveServerRenderMode(false)" /> | ||||||
|  |  | ||||||
|     <script src=@($"_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js?v={this.GetType().Assembly.GetName().Version}")></script> |     <script src=@($"_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js")></script> | ||||||
|     <script src=@($"{WebsiteConst.DefaultResourceUrl}js/localStorageUtil.js?v={this.GetType().Assembly.GetName().Version}")></script> |     <script src=@($"{WebsiteConst.DefaultResourceUrl}js/localStorageUtil.js")></script> | ||||||
|     <script src="_framework/blazor.web.js"></script> |     <script src="_framework/blazor.web.js"></script> | ||||||
|     <!-- PWA Service Worker --> |     <!-- PWA Service Worker --> | ||||||
|     <script type="text/javascript">'serviceWorker' in navigator && navigator.serviceWorker.register('./service-worker.js')</script> |     <script type="text/javascript">'serviceWorker' in navigator && navigator.serviceWorker.register('./service-worker.js')</script> | ||||||
|  |  | ||||||
|  |     <script src="pwa-install.js"></script> | ||||||
| </body> | </body> | ||||||
|  |  | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -70,7 +70,7 @@ | |||||||
|                         <Button @onclick="ShowAbout" class="layout-header-bar d-none d-lg-flex px-2" Icon="fa fa-info" Color="Color.None" TooltipText="@Localizer[nameof(About)]" /> |                         <Button @onclick="ShowAbout" class="layout-header-bar d-none d-lg-flex px-2" Icon="fa fa-info" Color="Color.None" TooltipText="@Localizer[nameof(About)]" /> | ||||||
|                     } |                     } | ||||||
|                     @* 版本号 *@ |                     @* 版本号 *@ | ||||||
|                     <div class="px-1 navbar-header-text d-none d-lg-block">@_versionString</div> |                     <div class="px-1 navbar-header-text text-nowrap d-none d-lg-block">@_versionString</div> | ||||||
|  |  | ||||||
|                     @* 主题切换 *@ |                     @* 主题切换 *@ | ||||||
|                     @* <ThemeToggle /> *@ |                     @* <ThemeToggle /> *@ | ||||||
| @@ -94,7 +94,14 @@ | |||||||
|                          DefaultUrl=@("/") Body=@(Body!) OnCloseTabItemAsync=@((a)=> |                          DefaultUrl=@("/") Body=@(Body!) OnCloseTabItemAsync=@((a)=> | ||||||
|                                                                                   { |                                                                                   { | ||||||
|                                                                                       return Task.FromResult(!(a.Url == "/" || a.Url.IsNullOrEmpty())); |                                                                                       return Task.FromResult(!(a.Url == "/" || a.Url.IsNullOrEmpty())); | ||||||
|                              })> |                                                                                   }) | ||||||
|  |                                                                                   > | ||||||
|  |                         <BeforeContextMenuTemplate> | ||||||
|  |  | ||||||
|  |                                                      <ContextMenuItem Icon="fa fa-window-restore" Text="@Localizer["WindowRestore"]" OnClick="WinboxRender"></ContextMenuItem> | ||||||
|  |                                                      <ContextMenuDivider></ContextMenuDivider> | ||||||
|  |  | ||||||
|  |                                                  </BeforeContextMenuTemplate> | ||||||
|                         </Tab> |                         </Tab> | ||||||
|                 </Main> |                 </Main> | ||||||
|                 <NotAuthorized> |                 <NotAuthorized> | ||||||
|   | |||||||
| @@ -120,6 +120,38 @@ public partial class MainLayout : IDisposable | |||||||
|  |  | ||||||
|     #endregion 注销 |     #endregion 注销 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     private async Task WinboxRender(ContextMenuItem item, object? context) | ||||||
|  |     { | ||||||
|  |         if (context is TabItem tabItem) | ||||||
|  |         { | ||||||
|  |             await WinboxRender(tabItem.ChildContent, tabItem.Text); | ||||||
|  |             //await _tab.RemoveTab(tabItem); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     [Inject] | ||||||
|  |     [NotNull] | ||||||
|  |     private WinBoxService? WinBoxService { get; set; } | ||||||
|  |  | ||||||
|  |     private async Task WinboxRender(RenderFragment item, string title) | ||||||
|  |     { | ||||||
|  |         if (item != null) | ||||||
|  |         { | ||||||
|  |             var option = new WinBoxOption() | ||||||
|  |             { | ||||||
|  |                 Title = title, | ||||||
|  |                 ContentTemplate = item, | ||||||
|  |                 Max = false, | ||||||
|  |                 Width = "80%", | ||||||
|  |                 Height = "80%", | ||||||
|  |                 Top = "0%", | ||||||
|  |                 Left = "10%", | ||||||
|  |                 Background = "var(--bb-primary-color)", | ||||||
|  |                 Overflow = true | ||||||
|  |             }; | ||||||
|  |             await WinBoxService.Show(option); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     private string _versionString = string.Empty; |     private string _versionString = string.Empty; | ||||||
|     [Inject] |     [Inject] | ||||||
|     [NotNull] |     [NotNull] | ||||||
|   | |||||||
| @@ -132,7 +132,11 @@ public class Startup : AppStartup | |||||||
|         services.Configure<ForwardedHeadersOptions>(options => |         services.Configure<ForwardedHeadersOptions>(options => | ||||||
|         { |         { | ||||||
|             options.ForwardedHeaders = ForwardedHeaders.All; |             options.ForwardedHeaders = ForwardedHeaders.All; | ||||||
|  | #if NET10_0_OR_GREATER | ||||||
|  |             options.KnownIPNetworks.Clear(); | ||||||
|  | #else | ||||||
|             options.KnownNetworks.Clear(); |             options.KnownNetworks.Clear(); | ||||||
|  | #endif | ||||||
|             options.KnownProxies.Clear(); |             options.KnownProxies.Clear(); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
| @@ -204,7 +208,16 @@ public class Startup : AppStartup | |||||||
|     public void Use(IApplicationBuilder applicationBuilder, IWebHostEnvironment env) |     public void Use(IApplicationBuilder applicationBuilder, IWebHostEnvironment env) | ||||||
|     { |     { | ||||||
|         var app = (WebApplication)applicationBuilder; |         var app = (WebApplication)applicationBuilder; | ||||||
|         app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.All, KnownNetworks = { }, KnownProxies = { } }); |         app.UseForwardedHeaders(new ForwardedHeadersOptions | ||||||
|  |         { | ||||||
|  |             ForwardedHeaders = ForwardedHeaders.All, | ||||||
|  | #if NET10_0_OR_GREATER | ||||||
|  |             KnownIPNetworks = { }, | ||||||
|  | #else | ||||||
|  |             KnownNetworks = { }, | ||||||
|  | #endif | ||||||
|  |             KnownProxies = { } | ||||||
|  |         }); | ||||||
|         app.UseBootstrapBlazor(); |         app.UseBootstrapBlazor(); | ||||||
|  |  | ||||||
|         // 启用本地化 |         // 启用本地化 | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
| 		<TargetFrameworks>net8.0;net9.0;</TargetFrameworks> | 		<TargetFrameworks>net8.0;$(OtherTargetFrameworks);</TargetFrameworks> | ||||||
| 		 | 		 | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
|  |  | ||||||
| @@ -53,9 +53,9 @@ | |||||||
| 		<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.1" /> | 		<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.1" /> | ||||||
| 		<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" /> | 		<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
| 	<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' "> | 	<ItemGroup Condition=" '$(TargetFramework)' == 'net10.0' "> | ||||||
| 		<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="$(NET9Version)" /> | 		<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="$(NET10Version)" /> | ||||||
| 		<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="$(NET9Version)" /> | 		<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="$(NET10Version)" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
| 	 | 	 | ||||||
| 	<ItemGroup> | 	<ItemGroup> | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								src/Admin/ThingsGateway.AdminServer/wwwroot/pwa-install.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/Admin/ThingsGateway.AdminServer/wwwroot/pwa-install.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | let installPromptTriggered = false; | ||||||
|  |  | ||||||
|  | function getCookie(name) { | ||||||
|  |     const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); | ||||||
|  |     return match ? match[2] : null; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function hasShownInstallPrompt() { | ||||||
|  |     return getCookie("tgPWAInstallPromptShown") === "true"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function markInstallPromptShown() { | ||||||
|  |     document.cookie = "tgPWAInstallPromptShown=true; max-age=31536000; path=/"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | window.addEventListener('beforeinstallprompt', (e) => { | ||||||
|  |     e.preventDefault(); | ||||||
|  |  | ||||||
|  |     if (!hasShownInstallPrompt() && !installPromptTriggered) { | ||||||
|  |         installPromptTriggered = true; | ||||||
|  |         setTimeout(() => { | ||||||
|  |             e.prompt() | ||||||
|  |                 .then(() => e.userChoice) | ||||||
|  |                 .then(choiceResult => { | ||||||
|  |                     markInstallPromptShown(); | ||||||
|  |                 }) | ||||||
|  |                 .catch(err => { | ||||||
|  |                     // 可选错误处理 | ||||||
|  |                 }); | ||||||
|  |         }, 2000); // 延迟 2 秒提示 | ||||||
|  |     } else { | ||||||
|  |         // console.log("已提示过安装,不再弹出"); | ||||||
|  |     } | ||||||
|  | }); | ||||||
| @@ -31,8 +31,8 @@ public static class GenericExtensions | |||||||
|  |  | ||||||
|         // 比较oldModel和model的属性,找出差异 |         // 比较oldModel和model的属性,找出差异 | ||||||
|         var differences = properties |         var differences = properties | ||||||
|             .Where(prop => prop.CanRead && prop.CanWrite) // 确保属性可读可写 |             .Where(prop => prop.CanRead && prop.CanWrite && !Equals(prop.GetValue(oldModel), prop.GetValue(model))) // 确保属性可读可写 | ||||||
|             .Where(prop => !Equals(prop.GetValue(oldModel), prop.GetValue(model))) // 找出值不同的属性 |                                                                                                                     // 找出值不同的属性 | ||||||
|             .ToDictionary(prop => prop.Name, prop => prop.GetValue(model)); // 将属性名和新值存储到字典中 |             .ToDictionary(prop => prop.Name, prop => prop.GetValue(model)); // 将属性名和新值存储到字典中 | ||||||
|  |  | ||||||
|         // 应用差异到channels列表中的每个Channel对象 |         // 应用差异到channels列表中的每个Channel对象 | ||||||
|   | |||||||
| @@ -16,6 +16,8 @@ using System.Runtime.CompilerServices; | |||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
|  | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Common.Extension; | namespace ThingsGateway.Common.Extension; | ||||||
| /// <summary> | /// <summary> | ||||||
| /// 对象拓展类 | /// 对象拓展类 | ||||||
| @@ -48,113 +50,7 @@ public static class ObjectExtensions | |||||||
|         bool IsTheRawGenericType(Type type) => generic == (type.IsGenericType ? type.GetGenericTypeDefinition() : type); |         bool IsTheRawGenericType(Type type) => generic == (type.IsGenericType ? type.GetGenericTypeDefinition() : type); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将 DateTimeOffset 转换成本地 DateTime |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="dateTime"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static DateTime ConvertToDateTime(this DateTimeOffset dateTime) |  | ||||||
|     { |  | ||||||
|         if (dateTime.Offset.Equals(TimeSpan.Zero)) |  | ||||||
|             return dateTime.UtcDateTime; |  | ||||||
|         if (dateTime.Offset.Equals(TimeZoneInfo.Local.GetUtcOffset(dateTime.DateTime))) |  | ||||||
|             return dateTime.ToLocalTime().DateTime; |  | ||||||
|         else |  | ||||||
|             return dateTime.DateTime; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将 DateTimeOffset? 转换成本地 DateTime? |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="dateTime"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static DateTime? ConvertToDateTime(this DateTimeOffset? dateTime) |  | ||||||
|     { |  | ||||||
|         return dateTime.HasValue ? dateTime.Value.ConvertToDateTime() : null; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将 DateTime 转换成 DateTimeOffset |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="dateTime"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static DateTimeOffset ConvertToDateTimeOffset(this DateTime dateTime) |  | ||||||
|     { |  | ||||||
|         return DateTime.SpecifyKind(dateTime, DateTimeKind.Local); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将 DateTime? 转换成 DateTimeOffset? |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="dateTime"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static DateTimeOffset? ConvertToDateTimeOffset(this DateTime? dateTime) |  | ||||||
|     { |  | ||||||
|         return dateTime.HasValue ? dateTime.Value.ConvertToDateTimeOffset() : null; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将流保存到本地磁盘 |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="stream"></param> |  | ||||||
|     /// <param name="path"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static void CopyToSave(this Stream stream, string path) |  | ||||||
|     { |  | ||||||
|         // 空检查 |  | ||||||
|         if (string.IsNullOrWhiteSpace(path)) throw new ArgumentNullException(nameof(path)); |  | ||||||
|  |  | ||||||
|         using var fileStream = File.Create(path); |  | ||||||
|         stream.CopyTo(fileStream); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将字节数组保存到本地磁盘 |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="bytes"></param> |  | ||||||
|     /// <param name="path"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static void CopyToSave(this byte[] bytes, string path) |  | ||||||
|     { |  | ||||||
|         using var stream = new MemoryStream(bytes); |  | ||||||
|         stream.CopyToSave(path); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将流保存到本地磁盘 |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="stream"></param> |  | ||||||
|     /// <param name="path">需包含文件名完整路径</param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static async Task CopyToSaveAsync(this Stream stream, string path) |  | ||||||
|     { |  | ||||||
|         // 空检查 |  | ||||||
|         if (string.IsNullOrWhiteSpace(path)) |  | ||||||
|         { |  | ||||||
|             throw new ArgumentNullException(nameof(path)); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // 文件名判断 |  | ||||||
|         if (string.IsNullOrWhiteSpace(Path.GetFileName(path))) |  | ||||||
|         { |  | ||||||
|             throw new ArgumentException("The parameter of <path> parameter must include the complete file name."); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         using var fileStream = File.Create(path); |  | ||||||
|         await stream.CopyToAsync(fileStream).ConfigureAwait(false); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将字节数组保存到本地磁盘 |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="bytes"></param> |  | ||||||
|     /// <param name="path"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static async Task CopyToSaveAsync(this byte[] bytes, string path) |  | ||||||
|     { |  | ||||||
|         using var stream = new MemoryStream(bytes); |  | ||||||
|         await stream.CopyToSaveAsync(path).ConfigureAwait(false); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 合并两个字典 |     /// 合并两个字典 | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ public static class ParallelExtensions | |||||||
|     /// <typeparam name="T">集合元素类型</typeparam> |     /// <typeparam name="T">集合元素类型</typeparam> | ||||||
|     /// <param name="source">要操作的集合</param> |     /// <param name="source">要操作的集合</param> | ||||||
|     /// <param name="body">要执行的操作</param> |     /// <param name="body">要执行的操作</param> | ||||||
|     public static void ParallelForEach<T>(this IList<T> source, Action<T> body) |     public static void ParallelForEach<T>(this IEnumerable<T> source, Action<T> body) | ||||||
|     { |     { | ||||||
|         ParallelOptions options = new(); |         ParallelOptions options = new(); | ||||||
|         options.MaxDegreeOfParallelism = Environment.ProcessorCount; |         options.MaxDegreeOfParallelism = Environment.ProcessorCount; | ||||||
| @@ -38,7 +38,7 @@ public static class ParallelExtensions | |||||||
|     /// <typeparam name="T">集合元素类型</typeparam> |     /// <typeparam name="T">集合元素类型</typeparam> | ||||||
|     /// <param name="source">要操作的集合</param> |     /// <param name="source">要操作的集合</param> | ||||||
|     /// <param name="body">要执行的操作</param> |     /// <param name="body">要执行的操作</param> | ||||||
|     public static void ParallelForEach<T>(this IList<T> source, Action<T, ParallelLoopState, long> body) |     public static void ParallelForEach<T>(this IEnumerable<T> source, Action<T, ParallelLoopState, long> body) | ||||||
|     { |     { | ||||||
|         ParallelOptions options = new(); |         ParallelOptions options = new(); | ||||||
|         options.MaxDegreeOfParallelism = Environment.ProcessorCount; |         options.MaxDegreeOfParallelism = Environment.ProcessorCount; | ||||||
| @@ -53,7 +53,7 @@ public static class ParallelExtensions | |||||||
|     /// <param name="source">要操作的集合</param> |     /// <param name="source">要操作的集合</param> | ||||||
|     /// <param name="body">要执行的操作</param> |     /// <param name="body">要执行的操作</param> | ||||||
|     /// <param name="parallelCount">最大并行度</param> |     /// <param name="parallelCount">最大并行度</param> | ||||||
|     public static void ParallelForEach<T>(this IList<T> source, Action<T> body, int parallelCount) |     public static void ParallelForEach<T>(this IEnumerable<T> source, Action<T> body, int parallelCount) | ||||||
|     { |     { | ||||||
|         // 创建并行操作的选项对象,设置最大并行度为指定的值 |         // 创建并行操作的选项对象,设置最大并行度为指定的值 | ||||||
|         var options = new ParallelOptions(); |         var options = new ParallelOptions(); | ||||||
| @@ -109,7 +109,7 @@ public static class ParallelExtensions | |||||||
|     /// <param name="parallelCount">最大并行度</param> |     /// <param name="parallelCount">最大并行度</param> | ||||||
|     /// <param name="cancellationToken">取消操作的标志</param> |     /// <param name="cancellationToken">取消操作的标志</param> | ||||||
|     /// <returns>表示异步操作的任务</returns> |     /// <returns>表示异步操作的任务</returns> | ||||||
|     public static Task ParallelForEachAsync<T>(this IList<T> source, Func<T, CancellationToken, ValueTask> body, int parallelCount, CancellationToken cancellationToken = default) |     public static Task ParallelForEachAsync<T>(this IEnumerable<T> source, Func<T, CancellationToken, ValueTask> body, int parallelCount, CancellationToken cancellationToken = default) | ||||||
|     { |     { | ||||||
|         // 创建并行操作的选项对象,设置最大并行度和取消标志 |         // 创建并行操作的选项对象,设置最大并行度和取消标志 | ||||||
|         var options = new ParallelOptions(); |         var options = new ParallelOptions(); | ||||||
| @@ -126,7 +126,7 @@ public static class ParallelExtensions | |||||||
|     /// <param name="body">异步执行的操作</param> |     /// <param name="body">异步执行的操作</param> | ||||||
|     /// <param name="cancellationToken">取消操作的标志</param> |     /// <param name="cancellationToken">取消操作的标志</param> | ||||||
|     /// <returns>表示异步操作的任务</returns> |     /// <returns>表示异步操作的任务</returns> | ||||||
|     public static Task ParallelForEachAsync<T>(this IList<T> source, Func<T, CancellationToken, ValueTask> body, CancellationToken cancellationToken = default) |     public static Task ParallelForEachAsync<T>(this IEnumerable<T> source, Func<T, CancellationToken, ValueTask> body, CancellationToken cancellationToken = default) | ||||||
|     { |     { | ||||||
|         return ParallelForEachAsync(source, body, Environment.ProcessorCount, cancellationToken); |         return ParallelForEachAsync(source, body, Environment.ProcessorCount, cancellationToken); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -8,13 +8,13 @@ | |||||||
| 		 | 		 | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
| 		<TargetFrameworks>net8.0;net9.0;</TargetFrameworks> | 		<TargetFrameworks>net8.0;$(OtherTargetFrameworks);</TargetFrameworks> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
| 	 | 	 | ||||||
| 	<ItemGroup> | 	<ItemGroup> | ||||||
| 		<PackageReference Include="BootstrapBlazor.TableExport" Version="9.2.6" /> | 		<PackageReference Include="BootstrapBlazor.TableExport" Version="9.2.7" /> | ||||||
| 		<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" /> | 		<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" /> | ||||||
| 		<PackageReference Include="BootstrapBlazor" Version="9.10.1" /> | 		<PackageReference Include="BootstrapBlazor" Version="9.11.1" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
|  |  | ||||||
| 	<ItemGroup> | 	<ItemGroup> | ||||||
|   | |||||||
| @@ -27,10 +27,15 @@ public abstract class PrimaryIdEntity : IPrimaryIdEntity | |||||||
|     public virtual long Id { get; set; } |     public virtual long Id { get; set; } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | public interface IPrimaryKeyEntity | ||||||
|  | { | ||||||
|  |     string ExtJson { get; set; } | ||||||
|  | } | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| /// 主键实体基类 | /// 主键实体基类 | ||||||
| /// </summary> | /// </summary> | ||||||
| public abstract class PrimaryKeyEntity : PrimaryIdEntity | public abstract class PrimaryKeyEntity : PrimaryIdEntity, IPrimaryKeyEntity | ||||||
| { | { | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 拓展信息 |     /// 拓展信息 | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
| 		 | 		 | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
| 		<TargetFrameworks>net8.0;net9.0;</TargetFrameworks> | 		<TargetFrameworks>net8.0;$(OtherTargetFrameworks);</TargetFrameworks> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using Microsoft.AspNetCore.Hosting; | using Microsoft.AspNetCore.Hosting; | ||||||
|  |  | ||||||
| using ThingsGateway; | using ThingsGateway; | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Reflection; | using ThingsGateway.Reflection; | ||||||
|  |  | ||||||
| namespace Microsoft.Extensions.Hosting; | namespace Microsoft.Extensions.Hosting; | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ using System.Text.RegularExpressions; | |||||||
|  |  | ||||||
| using ThingsGateway.NewLife; | using ThingsGateway.NewLife; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| /// 对象拓展类 | /// 对象拓展类 | ||||||
| @@ -28,70 +28,10 @@ namespace ThingsGateway.Extensions; | |||||||
| [SuppressSniffer] | [SuppressSniffer] | ||||||
| public static class ObjectExtensions | public static class ObjectExtensions | ||||||
| { | { | ||||||
|     /// <summary> |  | ||||||
|     /// 将 DateTimeOffset 转换成本地 DateTime |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="dateTime"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static DateTime ConvertToDateTime(this DateTimeOffset dateTime) |  | ||||||
|     { |  | ||||||
|         if (dateTime.Offset.Equals(TimeSpan.Zero)) |  | ||||||
|             return dateTime.UtcDateTime; |  | ||||||
|         if (dateTime.Offset.Equals(TimeZoneInfo.Local.GetUtcOffset(dateTime.DateTime))) |  | ||||||
|             return dateTime.ToLocalTime().DateTime; |  | ||||||
|         else |  | ||||||
|             return dateTime.DateTime; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将 DateTimeOffset? 转换成本地 DateTime? |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="dateTime"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static DateTime? ConvertToDateTime(this DateTimeOffset? dateTime) |  | ||||||
|     { |  | ||||||
|         return dateTime.HasValue ? dateTime.Value.ConvertToDateTime() : null; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将 DateTime 转换成 DateTimeOffset |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="dateTime"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static DateTimeOffset ConvertToDateTimeOffset(this DateTime dateTime) |  | ||||||
|     { |  | ||||||
|         return DateTime.SpecifyKind(dateTime, DateTimeKind.Local); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将 DateTime? 转换成 DateTimeOffset? |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="dateTime"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     public static DateTimeOffset? ConvertToDateTimeOffset(this DateTime? dateTime) |  | ||||||
|     { |  | ||||||
|         return dateTime.HasValue ? dateTime.Value.ConvertToDateTimeOffset() : null; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |  | ||||||
|     /// 将时间戳转换为 DateTime |  | ||||||
|     /// </summary> |  | ||||||
|     /// <param name="timestamp"></param> |  | ||||||
|     /// <returns></returns> |  | ||||||
|     internal static DateTime ConvertToDateTime(this long timestamp) |  | ||||||
|     { |  | ||||||
|         var timeStampDateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); |  | ||||||
|         var digitCount = (int)Math.Floor(Math.Log10(timestamp) + 1); |  | ||||||
|  |  | ||||||
|         if (digitCount != 13 && digitCount != 10) |  | ||||||
|         { |  | ||||||
|             throw new ArgumentException("Data is not a valid timestamp format."); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return (digitCount == 13 |  | ||||||
|             ? timeStampDateTime.AddMilliseconds(timestamp)  // 13 位时间戳 |  | ||||||
|             : timeStampDateTime.AddSeconds(timestamp)).ToLocalTime();   // 10 位时间戳 |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 将 IFormFile 转换成 byte[] |     /// 将 IFormFile 转换成 byte[] | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using Microsoft.AspNetCore.Mvc.ModelBinding; | using Microsoft.AspNetCore.Mvc.ModelBinding; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.AspNetCore; | namespace ThingsGateway.AspNetCore; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using Microsoft.AspNetCore.Mvc.ModelBinding; | using Microsoft.AspNetCore.Mvc.ModelBinding; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.AspNetCore; | namespace ThingsGateway.AspNetCore; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using Microsoft.AspNetCore.Mvc.ModelBinding; | using Microsoft.AspNetCore.Mvc.ModelBinding; | ||||||
| using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; | using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.AspNetCore; | namespace ThingsGateway.AspNetCore; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ using System.Reflection; | |||||||
|  |  | ||||||
| using ThingsGateway; | using ThingsGateway; | ||||||
| using ThingsGateway.ConfigurableOptions; | using ThingsGateway.ConfigurableOptions; | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace Microsoft.Extensions.DependencyInjection; | namespace Microsoft.Extensions.DependencyInjection; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -34,9 +34,12 @@ public static class PBKDF2Encryption | |||||||
|         using var rng = RandomNumberGenerator.Create(); |         using var rng = RandomNumberGenerator.Create(); | ||||||
|         var salt = new byte[saltSize]; |         var salt = new byte[saltSize]; | ||||||
|         rng.GetBytes(salt); |         rng.GetBytes(salt); | ||||||
|  | #if NET10_0_OR_GREATER | ||||||
|  |         var hash = Rfc2898DeriveBytes.Pbkdf2(System.Text.Encoding.UTF8.GetBytes(text), salt, iterationCount, HashAlgorithmName.SHA256, derivedKeyLength); | ||||||
|  | #else | ||||||
|         using var pbkdf2 = new Rfc2898DeriveBytes(text, salt, iterationCount, HashAlgorithmName.SHA256); |         using var pbkdf2 = new Rfc2898DeriveBytes(text, salt, iterationCount, HashAlgorithmName.SHA256); | ||||||
|         var hash = pbkdf2.GetBytes(derivedKeyLength); |         var hash = pbkdf2.GetBytes(derivedKeyLength); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|         // 分别编码盐和哈希,并用分隔符拼接 |         // 分别编码盐和哈希,并用分隔符拼接 | ||||||
|         return Convert.ToBase64String(salt) + SaltHashSeparator + Convert.ToBase64String(hash); |         return Convert.ToBase64String(salt) + SaltHashSeparator + Convert.ToBase64String(hash); | ||||||
| @@ -65,8 +68,12 @@ public static class PBKDF2Encryption | |||||||
|             if (saltBytes.Length != saltSize || storedHashBytes.Length != derivedKeyLength) |             if (saltBytes.Length != saltSize || storedHashBytes.Length != derivedKeyLength) | ||||||
|                 return false; |                 return false; | ||||||
|  |  | ||||||
|  | #if NET10_0_OR_GREATER | ||||||
|  |             var computedHash = Rfc2898DeriveBytes.Pbkdf2(System.Text.Encoding.UTF8.GetBytes(text), saltBytes, iterationCount, HashAlgorithmName.SHA256, derivedKeyLength); | ||||||
|  | #else | ||||||
|             using var pbkdf2 = new Rfc2898DeriveBytes(text, saltBytes, iterationCount, HashAlgorithmName.SHA256); |             using var pbkdf2 = new Rfc2898DeriveBytes(text, saltBytes, iterationCount, HashAlgorithmName.SHA256); | ||||||
|             var computedHash = pbkdf2.GetBytes(derivedKeyLength); |             var computedHash = pbkdf2.GetBytes(derivedKeyLength); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|             return computedHash.SequenceEqual(storedHashBytes); |             return computedHash.SequenceEqual(storedHashBytes); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ using System.ComponentModel.DataAnnotations; | |||||||
| using System.Reflection; | using System.Reflection; | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Templates.Extensions; | using ThingsGateway.Templates.Extensions; | ||||||
|  |  | ||||||
| namespace ThingsGateway.DataValidation; | namespace ThingsGateway.DataValidation; | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ using System.Collections.Concurrent; | |||||||
| using System.Reflection; | using System.Reflection; | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.UnifyResult; | using ThingsGateway.UnifyResult; | ||||||
|  |  | ||||||
| namespace ThingsGateway.DynamicApiController; | namespace ThingsGateway.DynamicApiController; | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ using System.ComponentModel.DataAnnotations; | |||||||
| using System.Diagnostics; | using System.Diagnostics; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Templates.Extensions; | using ThingsGateway.Templates.Extensions; | ||||||
|  |  | ||||||
| namespace ThingsGateway.FriendlyException; | namespace ThingsGateway.FriendlyException; | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ using Microsoft.AspNetCore.SignalR; | |||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway; | using ThingsGateway; | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.InstantMessaging; | using ThingsGateway.InstantMessaging; | ||||||
|  |  | ||||||
| namespace Microsoft.AspNetCore.Builder; | namespace Microsoft.AspNetCore.Builder; | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | ||||||
| // ------------------------------------------------------------------------ | // ------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Logging; | namespace ThingsGateway.Logging; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ using System.Text.Json; | |||||||
|  |  | ||||||
| using ThingsGateway; | using ThingsGateway; | ||||||
| using ThingsGateway.DataValidation; | using ThingsGateway.DataValidation; | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.FriendlyException; | using ThingsGateway.FriendlyException; | ||||||
| using ThingsGateway.JsonSerialization; | using ThingsGateway.JsonSerialization; | ||||||
| using ThingsGateway.Logging; | using ThingsGateway.Logging; | ||||||
| @@ -151,7 +151,7 @@ public sealed class LoggingMonitorAttribute : Attribute, IAsyncActionFilter, IAs | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         await MonitorAsync(actionMethod, context.ActionArguments, context, next).ConfigureAwait(false); |         await MonitorAsync(actionMethod, context.ActionArguments, context, () => next()).ConfigureAwait(false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
| @@ -183,7 +183,7 @@ public sealed class LoggingMonitorAttribute : Attribute, IAsyncActionFilter, IAs | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         await MonitorAsync(actionMethod, context.HandlerArguments, context, next).ConfigureAwait(false); |         await MonitorAsync(actionMethod, context.HandlerArguments, context, () => next()).ConfigureAwait(false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
| @@ -789,12 +789,12 @@ public sealed class LoggingMonitorAttribute : Attribute, IAsyncActionFilter, IAs | |||||||
|         return typeName; |         return typeName; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private async Task MonitorAsync(MethodInfo actionMethod, IDictionary<string, object> parameterValues, FilterContext context, dynamic next) |     private async Task MonitorAsync<T>(MethodInfo actionMethod, IDictionary<string, object> parameterValues, FilterContext context, Func<Task<T>> next) | ||||||
|     { |     { | ||||||
|         // 排除 WebSocket 请求处理 |         // 排除 WebSocket 请求处理 | ||||||
|         if (context.HttpContext.IsWebSocketRequest()) |         if (context.HttpContext.IsWebSocketRequest()) | ||||||
|         { |         { | ||||||
|             _ = await next(); |             _ = await next().ConfigureAwait(false); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -805,14 +805,14 @@ public sealed class LoggingMonitorAttribute : Attribute, IAsyncActionFilter, IAs | |||||||
|         if (actionMethod.IsDefined(typeof(SuppressMonitorAttribute), true) |         if (actionMethod.IsDefined(typeof(SuppressMonitorAttribute), true) | ||||||
|             || actionMethod.DeclaringType.IsDefined(typeof(SuppressMonitorAttribute), true)) |             || actionMethod.DeclaringType.IsDefined(typeof(SuppressMonitorAttribute), true)) | ||||||
|         { |         { | ||||||
|             _ = await next(); |             _ = await next().ConfigureAwait(false); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 判断是否自定义了日志筛选器,如果是则检查是否符合条件 |         // 判断是否自定义了日志筛选器,如果是则检查是否符合条件 | ||||||
|         if (LoggingMonitorSettings.InternalWriteFilter?.Invoke(context) == false) |         if (LoggingMonitorSettings.InternalWriteFilter?.Invoke(context) == false) | ||||||
|         { |         { | ||||||
|             _ = await next(); |             _ = await next().ConfigureAwait(false); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -825,7 +825,7 @@ public sealed class LoggingMonitorAttribute : Attribute, IAsyncActionFilter, IAs | |||||||
|         // 解决局部和全局触发器同时配置触发两次问题 |         // 解决局部和全局触发器同时配置触发两次问题 | ||||||
|         if (isDefinedScopedAttribute && Settings.FromGlobalFilter == true) |         if (isDefinedScopedAttribute && Settings.FromGlobalFilter == true) | ||||||
|         { |         { | ||||||
|             _ = await next(); |             _ = await next().ConfigureAwait(false); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -839,7 +839,7 @@ public sealed class LoggingMonitorAttribute : Attribute, IAsyncActionFilter, IAs | |||||||
|                     && !Settings.IncludeOfMethods.Contains(methodFullName, StringComparer.OrdinalIgnoreCase)) |                     && !Settings.IncludeOfMethods.Contains(methodFullName, StringComparer.OrdinalIgnoreCase)) | ||||||
|                 { |                 { | ||||||
|                     // 查找是否包含匹配,忽略大小写 |                     // 查找是否包含匹配,忽略大小写 | ||||||
|                     _ = await next(); |                     _ = await next().ConfigureAwait(false); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
| @@ -847,7 +847,7 @@ public sealed class LoggingMonitorAttribute : Attribute, IAsyncActionFilter, IAs | |||||||
|                 if (Settings.GlobalEnabled |                 if (Settings.GlobalEnabled | ||||||
|                     && Settings.ExcludeOfMethods.Contains(methodFullName, StringComparer.OrdinalIgnoreCase)) |                     && Settings.ExcludeOfMethods.Contains(methodFullName, StringComparer.OrdinalIgnoreCase)) | ||||||
|                 { |                 { | ||||||
|                     _ = await next(); |                     _ = await next().ConfigureAwait(false); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -958,7 +958,8 @@ public sealed class LoggingMonitorAttribute : Attribute, IAsyncActionFilter, IAs | |||||||
|  |  | ||||||
|         // 计算接口执行时间 |         // 计算接口执行时间 | ||||||
|         var timeOperation = Stopwatch.StartNew(); |         var timeOperation = Stopwatch.StartNew(); | ||||||
|         var resultContext = await next(); |  | ||||||
|  |         var resultContext = await next().ConfigureAwait(false); | ||||||
|         timeOperation.Stop(); |         timeOperation.Stop(); | ||||||
|         writer.WriteNumber("timeOperationElapsedMilliseconds", timeOperation.ElapsedMilliseconds); |         writer.WriteNumber("timeOperationElapsedMilliseconds", timeOperation.ElapsedMilliseconds); | ||||||
|  |  | ||||||
| @@ -1014,8 +1015,13 @@ public sealed class LoggingMonitorAttribute : Attribute, IAsyncActionFilter, IAs | |||||||
|         var environment = httpContext.RequestServices.GetRequiredService<IWebHostEnvironment>().EnvironmentName; |         var environment = httpContext.RequestServices.GetRequiredService<IWebHostEnvironment>().EnvironmentName; | ||||||
|         writer.WriteString(nameof(environment), environment); |         writer.WriteString(nameof(environment), environment); | ||||||
|  |  | ||||||
|  |         Exception exception = null; | ||||||
|         // 获取异常对象情况 |         // 获取异常对象情况 | ||||||
|         Exception exception = resultContext.Exception; |         if (resultContext is PageHandlerExecutedContext pageHandlerExecutedContext) | ||||||
|  |             exception = pageHandlerExecutedContext.Exception; | ||||||
|  |         else if (resultContext is ActionExecutedContext actionExecutedContext) | ||||||
|  |             exception = actionExecutedContext.Exception; | ||||||
|  |  | ||||||
|         if (exception == null) |         if (exception == null) | ||||||
|         { |         { | ||||||
|             // 解析存储的验证信息 |             // 解析存储的验证信息 | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; | |||||||
| using System.Linq.Expressions; | using System.Linq.Expressions; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Options; | using ThingsGateway.Options; | ||||||
|  |  | ||||||
| namespace Microsoft.Extensions.Options; | namespace Microsoft.Extensions.Options; | ||||||
|   | |||||||
| @@ -204,7 +204,7 @@ internal sealed partial class SchedulerFactory : ISchedulerFactory | |||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 _logger.LogWarning("Schedule hosted service preload completed, and a total of <{Count}> schedulers are appended.", _schedulers.Count); |                 _logger.LogInformation("Schedule hosted service preload completed, and a total of <{Count}> schedulers are appended.", _schedulers.Count); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ using System.Xml.Linq; | |||||||
| using System.Xml.XPath; | using System.Xml.XPath; | ||||||
|  |  | ||||||
| using ThingsGateway.DynamicApiController; | using ThingsGateway.DynamicApiController; | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Reflection; | using ThingsGateway.Reflection; | ||||||
|  |  | ||||||
| namespace ThingsGateway.SpecificationDocument; | namespace ThingsGateway.SpecificationDocument; | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ using System.Reflection; | |||||||
| using System.Text; | using System.Text; | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.SpecificationDocument; | namespace ThingsGateway.SpecificationDocument; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Templates.Extensions; | namespace ThingsGateway.Templates.Extensions; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| 	<Import Project="..\..\PackNuget.props" /> | 	<Import Project="..\..\PackNuget.props" /> | ||||||
|  |  | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
| 		<TargetFrameworks>net8.0;net9.0;</TargetFrameworks> | 		<TargetFrameworks>net8.0;$(OtherTargetFrameworks);</TargetFrameworks> | ||||||
| 		 | 		 | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
| 	 | 	 | ||||||
| @@ -29,8 +29,8 @@ | |||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
|  |  | ||||||
| 	<ItemGroup> | 	<ItemGroup> | ||||||
| 		<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.4" /> | 		<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.6" /> | ||||||
| 		<PackageReference Include="System.Text.Encoding.CodePages" Version="$(NET9Version)" /> | 		<PackageReference Include="System.Text.Encoding.CodePages" Version="$(NET10Version)" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
|  |  | ||||||
| 	<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' "> | 	<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' "> | ||||||
| @@ -39,10 +39,10 @@ | |||||||
| 		<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="8.0.2" /> | 		<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="8.0.2" /> | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
| 	 | 	 | ||||||
| 	<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' "> | 	<ItemGroup Condition=" '$(TargetFramework)' == 'net10.0' "> | ||||||
| 		<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(NET9Version)" /> | 		<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(NET10Version)" /> | ||||||
| 		<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(NET9Version)" /> | 		<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(NET10Version)" /> | ||||||
| 		<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(NET9Version)" /> | 		<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(NET10Version)" /> | ||||||
| 		 | 		 | ||||||
|  |  | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ using Microsoft.AspNetCore.Http; | |||||||
|  |  | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.UnifyResult; | using ThingsGateway.UnifyResult; | ||||||
|  |  | ||||||
| namespace Microsoft.AspNetCore.Mvc; | namespace Microsoft.AspNetCore.Mvc; | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ using Microsoft.Extensions.Options; | |||||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.FriendlyException; | using ThingsGateway.FriendlyException; | ||||||
|  |  | ||||||
| namespace ThingsGateway.UnifyResult; | namespace ThingsGateway.UnifyResult; | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
| using System.Text.Json.Serialization; | using System.Text.Json.Serialization; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Converters.Json; | namespace ThingsGateway.Converters.Json; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="Assembly" /> 拓展类 | ///     <see cref="Assembly" /> 拓展类 | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="ConcurrentDictionary{TKey, TValue}" /> 拓展类 | ///     <see cref="ConcurrentDictionary{TKey, TValue}" /> 拓展类 | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ using Microsoft.Extensions.Hosting; | |||||||
|  |  | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     核心模块 <see cref="IServiceCollection" /> 拓展类 | ///     核心模块 <see cref="IServiceCollection" /> 拓展类 | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Data; | using System.Data; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="DataTable" /> 和 <see cref="DataSet" /> 拓展类 | ///     <see cref="DataTable" /> 和 <see cref="DataSet" /> 拓展类 | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | ||||||
| // ------------------------------------------------------------------------ | // ------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     委托拓展类 | ///     委托拓展类 | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using System.ComponentModel; | using System.ComponentModel; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     枚举拓展类 | ///     枚举拓展类 | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | ||||||
| // ------------------------------------------------------------------------ | // ------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="EventHandler{TEventArgs}" /> 拓展类 | ///     <see cref="EventHandler{TEventArgs}" /> 拓展类 | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="ICollection{T}" /> 拓展类 | ///     <see cref="ICollection{T}" /> 拓展类 | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="IDictionary{TKey, TValue}" /> 拓展类 | ///     <see cref="IDictionary{TKey, TValue}" /> 拓展类 | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | ||||||
| // ------------------------------------------------------------------------ | // ------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="IEnumerable" /> 拓展类 | ///     <see cref="IEnumerable" /> 拓展类 | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ using System.Text.RegularExpressions; | |||||||
| using System.Xml; | using System.Xml; | ||||||
| using System.Xml.Linq; | using System.Xml.Linq; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     System.Text.Json 拓展类 | ///     System.Text.Json 拓展类 | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using System.Linq.Expressions; | using System.Linq.Expressions; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="Expression" /> 拓展类 | ///     <see cref="Expression" /> 拓展类 | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="MethodInfo" /> 拓展类 | ///     <see cref="MethodInfo" /> 拓展类 | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | ||||||
| // ------------------------------------------------------------------------ | // ------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     数值类型拓展类 | ///     数值类型拓展类 | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ using System.Reflection; | |||||||
| using System.Text; | using System.Text; | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="string" /> 拓展类 | ///     <see cref="string" /> 拓展类 | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ using System.Reflection; | |||||||
| using System.Reflection.Emit; | using System.Reflection.Emit; | ||||||
| using System.Runtime.CompilerServices; | using System.Runtime.CompilerServices; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="Type" /> 拓展类 | ///     <see cref="Type" /> 拓展类 | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ using System.Buffers; | |||||||
| using System.Text; | using System.Text; | ||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="Utf8JsonReader" /> 拓展类 | ///     <see cref="Utf8JsonReader" /> 拓展类 | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ using System.Text.Json; | |||||||
|  |  | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Extensions; | namespace ThingsGateway.Extension; | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| ///     <see cref="object" /> 拓展类 | ///     <see cref="object" /> 拓展类 | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ using System.Collections.Concurrent; | |||||||
| using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Reflection; | namespace ThingsGateway.Reflection; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ using System.Collections.Concurrent; | |||||||
| using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Reflection; | namespace ThingsGateway.Reflection; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Utilities; | namespace ThingsGateway.Utilities; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Text; | using System.Text; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Utilities; | namespace ThingsGateway.Utilities; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ using Microsoft.Net.Http.Headers; | |||||||
| using System.Net.Mime; | using System.Net.Mime; | ||||||
|  |  | ||||||
| using ThingsGateway.AspNetCore.Extensions; | using ThingsGateway.AspNetCore.Extensions; | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue; | using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using System.Net.Http.Headers; | using System.Net.Http.Headers; | ||||||
| using System.Threading.Channels; | using System.Threading.Channels; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ using System.Text; | |||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
| using System.Threading.Channels; | using System.Threading.Channels; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ using Microsoft.Extensions.Logging; | |||||||
| using System.Reflection; | using System.Reflection; | ||||||
| using System.Text; | using System.Text; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ using System.Net.Mime; | |||||||
| using System.Text; | using System.Text; | ||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue; | using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue; | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ using System.Globalization; | |||||||
| using System.Net.Http.Headers; | using System.Net.Http.Headers; | ||||||
| using System.Net.Mime; | using System.Net.Mime; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| using CacheControlHeaderValue = System.Net.Http.Headers.CacheControlHeaderValue; | using CacheControlHeaderValue = System.Net.Http.Headers.CacheControlHeaderValue; | ||||||
| using StringWithQualityHeaderValue = System.Net.Http.Headers.StringWithQualityHeaderValue; | using StringWithQualityHeaderValue = System.Net.Http.Headers.StringWithQualityHeaderValue; | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ | |||||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using System.Net.Mime; | using System.Net.Mime; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ using System.Net.Mime; | |||||||
| using System.Reflection; | using System.Reflection; | ||||||
| using System.Text; | using System.Text; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | ||||||
| // ------------------------------------------------------------------------ | // ------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using System.ComponentModel.DataAnnotations; | using System.ComponentModel.DataAnnotations; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ using Microsoft.Extensions.DependencyInjection; | |||||||
|  |  | ||||||
| using System.Net.Http.Headers; | using System.Net.Http.Headers; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote.Extensions; | namespace ThingsGateway.HttpRemote.Extensions; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ using System.Net.Http.Headers; | |||||||
| using System.Text; | using System.Text; | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| using StringWithQualityHeaderValue = System.Net.Http.Headers.StringWithQualityHeaderValue; | using StringWithQualityHeaderValue = System.Net.Http.Headers.StringWithQualityHeaderValue; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Text; | using System.Text; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Mvc; | |||||||
| using Microsoft.AspNetCore.Mvc.Controllers; | using Microsoft.AspNetCore.Mvc.Controllers; | ||||||
| using Microsoft.AspNetCore.Mvc.Filters; | using Microsoft.AspNetCore.Mvc.Filters; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.HttpRemote.Extensions; | using ThingsGateway.HttpRemote.Extensions; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| using System.Globalization; | using System.Globalization; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ using Microsoft.Extensions.Options; | |||||||
| using System.Diagnostics; | using System.Diagnostics; | ||||||
| using System.Threading.Channels; | using System.Threading.Channels; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ using Microsoft.Extensions.Options; | |||||||
| using System.Diagnostics; | using System.Diagnostics; | ||||||
| using System.Threading.Channels; | using System.Threading.Channels; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ using Microsoft.Extensions.Options; | |||||||
|  |  | ||||||
| using System.Threading.Channels; | using System.Threading.Channels; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ using System.Diagnostics.CodeAnalysis; | |||||||
| using System.Text; | using System.Text; | ||||||
| using System.Threading.Channels; | using System.Threading.Channels; | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | // 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。 | ||||||
| // ------------------------------------------------------------------------ | // ------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| using ThingsGateway.Extensions; | using ThingsGateway.Extension; | ||||||
| using ThingsGateway.Utilities; | using ThingsGateway.Utilities; | ||||||
|  |  | ||||||
| namespace ThingsGateway.HttpRemote; | namespace ThingsGateway.HttpRemote; | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user