mirror of
				https://gitee.com/ThingsGateway/ThingsGateway.git
				synced 2025-11-04 17:43:58 +08:00 
			
		
		
		
	Compare commits
	
		
			20 Commits
		
	
	
		
			10.11.81.0
			...
			14f3c31265
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					14f3c31265 | ||
| 
						 | 
					1bad65378f | ||
| 
						 | 
					db3affc67e | ||
| 
						 | 
					5ee8b50a92 | ||
| 
						 | 
					301beda2a2 | ||
| 
						 | 
					628b51a353 | ||
| 
						 | 
					f03445bc83 | ||
| 
						 | 
					55a2ff5487 | ||
| 
						 | 
					0fef7dcf3b | ||
| 
						 | 
					19d9702606 | ||
| 
						 | 
					a8a9774932 | ||
| 
						 | 
					aad0f0e8c3 | ||
| 
						 | 
					e74eae50a7 | ||
| 
						 | 
					3b16d7019f | ||
| 
						 | 
					3e038028c2 | ||
| 
						 | 
					b1d8041f7e | ||
| 
						 | 
					53a98b26cd | ||
| 
						 | 
					42c740fa1b | ||
| 
						 | 
					556819c90c | ||
| 
						 | 
					2522333a9c | 
@@ -45,6 +45,7 @@ public class VerificatInfo : PrimaryIdEntity
 | 
			
		||||
    /// 登录IP
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [AutoGenerateColumn(Filterable = true, Sortable = true, Width = 200)]
 | 
			
		||||
    [SugarColumn(IsNullable = true)]
 | 
			
		||||
    public string LoginIp { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -78,5 +79,6 @@ public class VerificatInfo : PrimaryIdEntity
 | 
			
		||||
    /// 登录设备
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [AutoGenerateColumn(Filterable = true, Sortable = true, Width = 100)]
 | 
			
		||||
    [SugarColumn(IsNullable = true)]
 | 
			
		||||
    public string Device { get; set; }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -145,7 +145,7 @@ public class AdminOAuthHandler<TOptions>(
 | 
			
		||||
        var loginEvent = new LoginEvent
 | 
			
		||||
        {
 | 
			
		||||
            Ip = appService.RemoteIpAddress,
 | 
			
		||||
            Device = appService.UserAgent?.Platform,
 | 
			
		||||
            Device = appService.UserAgent?.Platform ?? "Unknown",
 | 
			
		||||
            Expire = expire,
 | 
			
		||||
            SysUser = sysUser,
 | 
			
		||||
            VerificatId = CommonUtils.GetSingleId()
 | 
			
		||||
@@ -156,7 +156,7 @@ public class AdminOAuthHandler<TOptions>(
 | 
			
		||||
        //生成verificat信息
 | 
			
		||||
        var verificatInfo = new VerificatInfo
 | 
			
		||||
        {
 | 
			
		||||
            Device = loginEvent.Device,
 | 
			
		||||
            Device = loginEvent.Device ?? "Unknown",
 | 
			
		||||
            Expire = loginEvent.Expire,
 | 
			
		||||
            VerificatTimeout = tokenTimeout,
 | 
			
		||||
            Id = loginEvent.VerificatId,
 | 
			
		||||
 
 | 
			
		||||
@@ -235,7 +235,7 @@ public class AuthService : IAuthService
 | 
			
		||||
        var logingEvent = new LoginEvent
 | 
			
		||||
        {
 | 
			
		||||
            Ip = _appService.RemoteIpAddress,
 | 
			
		||||
            Device = _appService.UserAgent?.Platform,
 | 
			
		||||
            Device = _appService.UserAgent?.Platform ?? "Unknown",
 | 
			
		||||
            Expire = expire,
 | 
			
		||||
            SysUser = sysUser,
 | 
			
		||||
            VerificatId = verificatId
 | 
			
		||||
@@ -344,7 +344,7 @@ public class AuthService : IAuthService
 | 
			
		||||
        //生成verificat信息
 | 
			
		||||
        var verificatInfo = new VerificatInfo
 | 
			
		||||
        {
 | 
			
		||||
            Device = loginEvent.Device,
 | 
			
		||||
            Device = loginEvent.Device ?? "Unknown",
 | 
			
		||||
            Expire = loginEvent.Expire,
 | 
			
		||||
            VerificatTimeout = tokenTimeout,
 | 
			
		||||
            Id = loginEvent.VerificatId,
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
	
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<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 Condition=" '$(TargetFramework)' == 'net8.0' ">
 | 
			
		||||
		<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
<div class="tg-table h-100">
 | 
			
		||||
 | 
			
		||||
    <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!"
 | 
			
		||||
           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
 | 
			
		||||
@@ -41,6 +41,7 @@
 | 
			
		||||
           DoubleClickToEdit="DoubleClickToEdit"
 | 
			
		||||
           OnDoubleClickCellCallback="OnDoubleClickCellCallback"
 | 
			
		||||
           OnDoubleClickRowCallback="OnDoubleClickRowCallback"
 | 
			
		||||
           RowContentTemplate="RowContentTemplate"
 | 
			
		||||
           OnClickRowCallback="OnClickRowCallback">
 | 
			
		||||
    </Table>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,14 @@ namespace ThingsGateway.Admin.Razor;
 | 
			
		||||
[CascadingTypeParameter(nameof(TItem))]
 | 
			
		||||
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; }
 | 
			
		||||
@@ -40,6 +48,10 @@ public partial class AdminTable<TItem> where TItem : class, new()
 | 
			
		||||
    /// <inheritdoc cref="Table{TItem}.OnDoubleClickRowCallback"/>
 | 
			
		||||
    [Parameter]
 | 
			
		||||
    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"/>
 | 
			
		||||
    [Parameter]
 | 
			
		||||
    public Func<TItem, Task>? OnClickRowCallback { get; set; }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<ProjectReference Include="..\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor.Chart" Version="9.0.1" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor.Chart" Version="9.0.3" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor.UniverSheet" Version="9.0.5" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor.WinBox" Version="9.0.7" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor.CodeEditor" Version="9.0.3" />
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@ public static class AdminResourceUtil
 | 
			
		||||
                Target = item.Target.ToString(),
 | 
			
		||||
                Items = BuildMenuTrees(items, item.Id).ToList()
 | 
			
		||||
            };
 | 
			
		||||
            if(menu.Url.IsNullOrEmpty())
 | 
			
		||||
            if (menu.Url.IsNullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                menu.Match = Microsoft.AspNetCore.Components.Routing.NavLinkMatch.Prefix;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,8 @@ using System.Runtime.CompilerServices;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Common.Extension;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 对象拓展类
 | 
			
		||||
@@ -48,113 +50,7 @@ public static class ObjectExtensions
 | 
			
		||||
        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>
 | 
			
		||||
    /// 合并两个字典
 | 
			
		||||
 
 | 
			
		||||
@@ -12,9 +12,9 @@
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
	
 | 
			
		||||
	<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="BootstrapBlazor" Version="9.11.0" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor" Version="9.11.2" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway;
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Reflection;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.Extensions.Hosting;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.NewLife;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 对象拓展类
 | 
			
		||||
@@ -28,70 +28,10 @@ namespace ThingsGateway.Extensions;
 | 
			
		||||
[SuppressSniffer]
 | 
			
		||||
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>
 | 
			
		||||
    /// 将 IFormFile 转换成 byte[]
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.AspNetCore;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.AspNetCore;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.AspNetCore;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway;
 | 
			
		||||
using ThingsGateway.ConfigurableOptions;
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ using System.ComponentModel.DataAnnotations;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Templates.Extensions;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.DataValidation;
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ using System.Collections.Concurrent;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.UnifyResult;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.DynamicApiController;
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ using System.ComponentModel.DataAnnotations;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Templates.Extensions;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.FriendlyException;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ using Microsoft.AspNetCore.SignalR;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway;
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.InstantMessaging;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.AspNetCore.Builder;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
			
		||||
// ------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Logging;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ using System.Text.Json;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway;
 | 
			
		||||
using ThingsGateway.DataValidation;
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
using ThingsGateway.JsonSerialization;
 | 
			
		||||
using ThingsGateway.Logging;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
 | 
			
		||||
using System.Linq.Expressions;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Options;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.Extensions.Options;
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ using System.Xml.Linq;
 | 
			
		||||
using System.Xml.XPath;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.DynamicApiController;
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Reflection;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.SpecificationDocument;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.SpecificationDocument;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Templates.Extensions;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@
 | 
			
		||||
	</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="$(NET10Version)" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ using Microsoft.AspNetCore.Http;
 | 
			
		||||
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.UnifyResult;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.AspNetCore.Mvc;
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ using Microsoft.Extensions.Options;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.FriendlyException;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.UnifyResult;
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
using System.Text.Json.Serialization;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Converters.Json;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="Assembly" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="ConcurrentDictionary{TKey, TValue}" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ using Microsoft.Extensions.Hosting;
 | 
			
		||||
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     核心模块 <see cref="IServiceCollection" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Data;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="DataTable" /> 和 <see cref="DataSet" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
			
		||||
// ------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     委托拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     枚举拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
			
		||||
// ------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="EventHandler{TEventArgs}" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="ICollection{T}" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="IDictionary{TKey, TValue}" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
			
		||||
// ------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="IEnumerable" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ using System.Text.RegularExpressions;
 | 
			
		||||
using System.Xml;
 | 
			
		||||
using System.Xml.Linq;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     System.Text.Json 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using System.Linq.Expressions;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="Expression" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="MethodInfo" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
			
		||||
// ------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     数值类型拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="string" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ using System.Reflection;
 | 
			
		||||
using System.Reflection.Emit;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="Type" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ using System.Buffers;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="Utf8JsonReader" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ using System.Text.Json;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
namespace ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
///     <see cref="object" /> 拓展类
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ using System.Collections.Concurrent;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Reflection;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ using System.Collections.Concurrent;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Reflection;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ using Microsoft.Net.Http.Headers;
 | 
			
		||||
using System.Net.Mime;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.AspNetCore.Extensions;
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using System.Net.Http.Headers;
 | 
			
		||||
using System.Threading.Channels;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ using System.Text;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
using System.Threading.Channels;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ using Microsoft.Extensions.Logging;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ using System.Net.Mime;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ using System.Globalization;
 | 
			
		||||
using System.Net.Http.Headers;
 | 
			
		||||
using System.Net.Mime;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
using CacheControlHeaderValue = System.Net.Http.Headers.CacheControlHeaderValue;
 | 
			
		||||
using StringWithQualityHeaderValue = System.Net.Http.Headers.StringWithQualityHeaderValue;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using System.Net.Mime;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ using System.Net.Mime;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
			
		||||
// ------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using System.Net.Http.Headers;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote.Extensions;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ using System.Net.Http.Headers;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
using StringWithQualityHeaderValue = System.Net.Http.Headers.StringWithQualityHeaderValue;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.Controllers;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.Filters;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.HttpRemote.Extensions;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ using Microsoft.Extensions.Options;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Threading.Channels;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ using Microsoft.Extensions.Options;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Threading.Channels;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ using Microsoft.Extensions.Options;
 | 
			
		||||
 | 
			
		||||
using System.Threading.Channels;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Channels;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
			
		||||
// ------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Utilities;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ using System.Net.Http.Headers;
 | 
			
		||||
using System.Net.Mime;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ using System.Net.Http.Headers;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using System.Net.Mime;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ using System.Globalization;
 | 
			
		||||
using System.Net.Http.Headers;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ using System.Text;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
using System.Text.Json.Nodes;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ using System.Net;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
			
		||||
// ------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
using System.Net.WebSockets;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.HttpRemote;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ using System.Net.Mime;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Web;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Shapeless;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ using System.Text.Json.Nodes;
 | 
			
		||||
using System.Xml;
 | 
			
		||||
using System.Xml.Linq;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Shapeless;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ using System.Dynamic;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
using ThingsGateway.Shapeless.Extensions;
 | 
			
		||||
 | 
			
		||||
using Binder = Microsoft.CSharp.RuntimeBinder.Binder;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ using System.Dynamic;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
using System.Text.Json.Nodes;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Shapeless;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,34 +1,108 @@
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.NewLife.Threading;
 | 
			
		||||
namespace ThingsGateway.NewLife;
 | 
			
		||||
 | 
			
		||||
public class ExpiringDictionary<TKey, TValue> : IDisposable
 | 
			
		||||
{
 | 
			
		||||
    private ConcurrentDictionary<TKey, TValue> _dict = new();
 | 
			
		||||
    private readonly TimerX _cleanupTimer;
 | 
			
		||||
 | 
			
		||||
    public ExpiringDictionary(int cleanupInterval = 60000)
 | 
			
		||||
    /// <summary>缓存项</summary>
 | 
			
		||||
    public class CacheItem
 | 
			
		||||
    {
 | 
			
		||||
        _cleanupTimer = new TimerX(Clear, null, cleanupInterval, cleanupInterval) { Async = true };
 | 
			
		||||
        private TValue? _value;
 | 
			
		||||
        /// <summary>数值</summary>
 | 
			
		||||
        public TValue? Value { get => _value; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>过期时间。系统启动以来的毫秒数</summary>
 | 
			
		||||
        public Int64 ExpiredTime { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>是否过期</summary>
 | 
			
		||||
        public Boolean Expired => ExpiredTime <= Runtime.TickCount64;
 | 
			
		||||
 | 
			
		||||
        /// <summary>访问时间</summary>
 | 
			
		||||
        public Int64 VisitTime { get; private set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>构造缓存项</summary>
 | 
			
		||||
        /// <param name="value"></param>
 | 
			
		||||
        /// <param name="expire"></param>
 | 
			
		||||
        public CacheItem(TValue? value, Int32 expire) => Set(value, expire);
 | 
			
		||||
 | 
			
		||||
        /// <summary>设置数值和过期时间</summary>
 | 
			
		||||
        /// <param name="value"></param>
 | 
			
		||||
        /// <param name="expire">过期时间,秒</param>
 | 
			
		||||
        public void Set(TValue value, Int32 expire)
 | 
			
		||||
        {
 | 
			
		||||
            _value = value;
 | 
			
		||||
 | 
			
		||||
            var now = VisitTime = Runtime.TickCount64;
 | 
			
		||||
            if (expire <= 0)
 | 
			
		||||
                ExpiredTime = Int64.MaxValue;
 | 
			
		||||
            else
 | 
			
		||||
                ExpiredTime = now + expire * 1000L;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>更新访问时间并返回数值</summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public TValue? Visit()
 | 
			
		||||
        {
 | 
			
		||||
            VisitTime = Runtime.TickCount64;
 | 
			
		||||
            var rs = _value;
 | 
			
		||||
            if (rs == null) return default;
 | 
			
		||||
 | 
			
		||||
            return rs;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private ConcurrentDictionary<TKey, CacheItem> _dict;
 | 
			
		||||
 | 
			
		||||
    private readonly TimerX _cleanupTimer;
 | 
			
		||||
    private int defaultExpire = 60;
 | 
			
		||||
    IEqualityComparer<TKey>? comparer;
 | 
			
		||||
    public ExpiringDictionary(int expire = 60, IEqualityComparer<TKey>? comparer = null)
 | 
			
		||||
    {
 | 
			
		||||
        defaultExpire = expire;
 | 
			
		||||
        this.comparer = comparer;
 | 
			
		||||
        _dict = new ConcurrentDictionary<TKey, CacheItem>(comparer);
 | 
			
		||||
 | 
			
		||||
        _cleanupTimer = new TimerX(TimerClear, null, 10000, 10000) { Async = true };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void TryAdd(TKey key, TValue value)
 | 
			
		||||
    public bool TryAdd(TKey key, TValue value)
 | 
			
		||||
    {
 | 
			
		||||
        _dict.TryAdd(key, value);
 | 
			
		||||
        if (_dict.TryGetValue(key, out var item))
 | 
			
		||||
        {
 | 
			
		||||
            if (!item.Expired) return false;
 | 
			
		||||
            item.Set(value, defaultExpire);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return _dict.TryAdd(key, new CacheItem(value, defaultExpire));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public bool TryGetValue(TKey key, out TValue value)
 | 
			
		||||
    {
 | 
			
		||||
        return _dict.TryGetValue(key, out value);
 | 
			
		||||
        value = default;
 | 
			
		||||
 | 
			
		||||
        // 没有值,直接结束
 | 
			
		||||
        if (!_dict.TryGetValue(key, out var item) || item == null) return false;
 | 
			
		||||
 | 
			
		||||
        // 得到已有值
 | 
			
		||||
        value = item.Visit();
 | 
			
		||||
 | 
			
		||||
        // 是否未过期的有效值
 | 
			
		||||
        return !item.Expired;
 | 
			
		||||
    }
 | 
			
		||||
    public TValue GetOrAdd(TKey key, Func<TKey, TValue> func)
 | 
			
		||||
    {
 | 
			
		||||
        return _dict.GetOrAdd(key, func);
 | 
			
		||||
    }
 | 
			
		||||
    public TValue GetOrAdd(TKey key, TValue value)
 | 
			
		||||
    {
 | 
			
		||||
        return _dict.GetOrAdd(key, value);
 | 
			
		||||
        CacheItem? item = null;
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            if (_dict.TryGetValue(key, out item) && item != null) return item.Visit();
 | 
			
		||||
 | 
			
		||||
            item ??= new CacheItem(func(key), defaultExpire);
 | 
			
		||||
        }
 | 
			
		||||
        while (!_dict.TryAdd(key, item));
 | 
			
		||||
 | 
			
		||||
        return item.Visit();
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public bool TryRemove(TKey key) => _dict.TryRemove(key, out _);
 | 
			
		||||
@@ -38,13 +112,38 @@ public class ExpiringDictionary<TKey, TValue> : IDisposable
 | 
			
		||||
    private void Clear(object? state)
 | 
			
		||||
    {
 | 
			
		||||
        var data = _dict;
 | 
			
		||||
        _dict = new();
 | 
			
		||||
        _dict = new(comparer);
 | 
			
		||||
        data.Clear();
 | 
			
		||||
    }
 | 
			
		||||
    private void TimerClear(object? state)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        var dic = _dict;
 | 
			
		||||
        if (dic.IsEmpty) return;
 | 
			
		||||
 | 
			
		||||
        // 60分钟之内过期的数据,进入LRU淘汰
 | 
			
		||||
        var now = Runtime.TickCount64;
 | 
			
		||||
 | 
			
		||||
        // 这里先计算,性能很重要
 | 
			
		||||
        var toDels = new List<TKey>();
 | 
			
		||||
        foreach (var item in dic)
 | 
			
		||||
        {
 | 
			
		||||
            // 已过期,准备删除
 | 
			
		||||
            var ci = item.Value;
 | 
			
		||||
            if (ci.ExpiredTime <= now)
 | 
			
		||||
                toDels.Add(item.Key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 确认删除
 | 
			
		||||
        foreach (var item in toDels)
 | 
			
		||||
        {
 | 
			
		||||
            _dict.Remove(item);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public void Dispose()
 | 
			
		||||
    {
 | 
			
		||||
        _dict.Clear();
 | 
			
		||||
        _cleanupTimer.Dispose();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,6 @@
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.NewLife.Log;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.NewLife;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -66,7 +64,7 @@ public sealed class WaitLock : IDisposable
 | 
			
		||||
            }
 | 
			
		||||
            catch (SemaphoreFullException)
 | 
			
		||||
            {
 | 
			
		||||
                XTrace.WriteException(new Exception($"WaitLock {_name} 释放失败,当前信号量无需释放"));
 | 
			
		||||
                //XTrace.WriteException(new Exception($"WaitLock {_name} 释放失败,当前信号量无需释放"));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -155,7 +155,7 @@ public static class DateExtensions
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="timestamp"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    internal static DateTime ConvertToDateTime(this long timestamp)
 | 
			
		||||
    public 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);
 | 
			
		||||
@@ -169,4 +169,5 @@ public static class DateExtensions
 | 
			
		||||
            ? timeStampDateTime.AddMilliseconds(timestamp)  // 13 位时间戳
 | 
			
		||||
            : timeStampDateTime.AddSeconds(timestamp)).ToLocalTime();   // 10 位时间戳
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,13 +8,14 @@
 | 
			
		||||
// 项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。
 | 
			
		||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
			
		||||
// ------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Newtonsoft.Json.Linq;
 | 
			
		||||
 | 
			
		||||
#if NET6_0_OR_GREATER
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Extensions;
 | 
			
		||||
using ThingsGateway.Extension;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.JsonSerialization;
 | 
			
		||||
 | 
			
		||||
@@ -23,6 +24,7 @@ namespace ThingsGateway.JsonSerialization;
 | 
			
		||||
/// </summary>
 | 
			
		||||
internal static class Penetrates
 | 
			
		||||
{
 | 
			
		||||
#if NET6_0_OR_GREATER
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 转换
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -35,7 +37,6 @@ internal static class Penetrates
 | 
			
		||||
        {
 | 
			
		||||
            return longValue.ConvertToDateTime();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var stringValue = reader.GetString();
 | 
			
		||||
 | 
			
		||||
        // 处理时间戳自动转换
 | 
			
		||||
@@ -46,6 +47,9 @@ internal static class Penetrates
 | 
			
		||||
 | 
			
		||||
        return Convert.ToDateTime(stringValue);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 转换
 | 
			
		||||
@@ -69,4 +73,6 @@ internal static class Penetrates
 | 
			
		||||
 | 
			
		||||
        return Convert.ToDateTime(stringValue);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -53,12 +53,16 @@ public static class LinqExtensions
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public static void RemoveWhere<T>(this ICollection<T> @this, Func<T, bool> @where)
 | 
			
		||||
    {
 | 
			
		||||
        foreach (var obj in @this.Where(where).ToList())
 | 
			
		||||
        var del = new List<T>();
 | 
			
		||||
        foreach (var obj in @this.Where(where))
 | 
			
		||||
        {
 | 
			
		||||
            del.Add(obj);
 | 
			
		||||
        }
 | 
			
		||||
        foreach (var obj in del)
 | 
			
		||||
        {
 | 
			
		||||
            @this.Remove(obj);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> thisValue, bool isOk, Func<T, bool> predicate)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
 | 
			
		||||
//  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
 | 
			
		||||
//  使用文档:https://thingsgateway.cn/
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
public class NewtonsoftEncodingConverter : Newtonsoft.Json.JsonConverter<Encoding>
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override Encoding? ReadJson(JsonReader reader, Type objectType, Encoding? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
 | 
			
		||||
    {
 | 
			
		||||
        // 从 JSON 字符串中读取编码名称,并创建相应的 Encoding 对象
 | 
			
		||||
        string? encodingName = reader.Value as string;
 | 
			
		||||
        return Encoding.GetEncoding(encodingName ?? Encoding.UTF8.WebName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override void WriteJson(JsonWriter writer, Encoding? value, Newtonsoft.Json.JsonSerializer serializer)
 | 
			
		||||
    {
 | 
			
		||||
        writer.WriteValue(value.WebName);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
// 项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。
 | 
			
		||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
			
		||||
// ------------------------------------------------------------------------
 | 
			
		||||
#if NET6_0_OR_GREATER
 | 
			
		||||
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Newtonsoft.Json.Linq;
 | 
			
		||||
@@ -17,7 +18,6 @@ namespace ThingsGateway.JsonSerialization;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// DateOnly 类型序列化
 | 
			
		||||
/// </summary>
 | 
			
		||||
[SuppressSniffer]
 | 
			
		||||
public class NewtonsoftJsonDateOnlyJsonConverter : JsonConverter<DateOnly>
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -72,7 +72,6 @@ public class NewtonsoftJsonDateOnlyJsonConverter : JsonConverter<DateOnly>
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// DateOnly? 类型序列化
 | 
			
		||||
/// </summary>
 | 
			
		||||
[SuppressSniffer]
 | 
			
		||||
public class NewtonsoftJsonNullableDateOnlyJsonConverter : JsonConverter<DateOnly?>
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -123,4 +122,6 @@ public class NewtonsoftJsonNullableDateOnlyJsonConverter : JsonConverter<DateOnl
 | 
			
		||||
        if (value == null) writer.WriteNull();
 | 
			
		||||
        else writer.WriteValue(value.Value.ToString(Format));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -16,7 +16,7 @@ namespace ThingsGateway.JsonSerialization;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// DateTime 类型序列化
 | 
			
		||||
/// </summary>
 | 
			
		||||
[SuppressSniffer]
 | 
			
		||||
 | 
			
		||||
public class NewtonsoftJsonDateTimeJsonConverter : JsonConverter<DateTime>
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -90,7 +90,7 @@ public class NewtonsoftJsonDateTimeJsonConverter : JsonConverter<DateTime>
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// DateTime 类型序列化
 | 
			
		||||
/// </summary>
 | 
			
		||||
[SuppressSniffer]
 | 
			
		||||
 | 
			
		||||
public class NewtonsoftNullableJsonDateTimeJsonConverter : JsonConverter<DateTime?>
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -16,7 +16,6 @@ namespace ThingsGateway.JsonSerialization;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// DateTimeOffset 类型序列化
 | 
			
		||||
/// </summary>
 | 
			
		||||
[SuppressSniffer]
 | 
			
		||||
public class NewtonsoftJsonDateTimeOffsetJsonConverter : JsonConverter<DateTimeOffset>
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -90,7 +89,6 @@ public class NewtonsoftJsonDateTimeOffsetJsonConverter : JsonConverter<DateTimeO
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// DateTimeOffset 类型序列化
 | 
			
		||||
/// </summary>
 | 
			
		||||
[SuppressSniffer]
 | 
			
		||||
public class NewtonsoftJsonNullableDateTimeOffsetJsonConverter : JsonConverter<DateTimeOffset?>
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user