mirror of
https://gitee.com/ThingsGateway/ThingsGateway.git
synced 2025-10-20 10:50:48 +08:00
Compare commits
5 Commits
6f9ec2e24b
...
21215d0379
Author | SHA1 | Date | |
---|---|---|---|
![]() |
21215d0379 | ||
![]() |
7448183791 | ||
![]() |
35edd7dc43 | ||
![]() |
bd178831e3 | ||
![]() |
fe9ec6ad10 |
@@ -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" SelectedRows=SelectedRows SelectedRowsChanged=privateSelectedRowsChanged IsMultipleSelect="IsMultipleSelect" @ref="Instance" SearchTemplate="SearchTemplate"
|
<Table Id=@Id TItem="TItem" IsBordered="true" IsStriped="true" TableSize="TableSize.Compact" SelectedRows=SelectedRows SelectedRowsChanged=privateSelectedRowsChanged IsMultipleSelect="IsMultipleSelect" @ref="Instance" SearchTemplate="SearchTemplate"
|
||||||
DataService="DataService" CreateItemCallback="CreateItemCallback!" RenderMode=RenderMode
|
DataService="DataService" CreateItemCallback="CreateItemCallback!" RenderMode=RenderMode OnColumnCreating=OnColumnCreating
|
||||||
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
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
ShowSkeleton="true" ShowLoading="ShowLoading" ShowSearch="ShowSearch" SearchModel=@SearchModel ShowLineNo
|
ShowSkeleton="true" ShowLoading="ShowLoading" ShowSearch="ShowSearch" SearchModel=@SearchModel ShowLineNo
|
||||||
SearchMode=SearchMode ShowExportPdfButton=ShowExportPdfButton ExportButtonText=@ExportButtonText
|
SearchMode=SearchMode ShowExportPdfButton=ShowExportPdfButton ExportButtonText=@ExportButtonText
|
||||||
ShowExportButton=@ShowExportButton Items=Items ClickToSelect=ClickToSelect ScrollMode=ScrollMode
|
ShowExportButton=@ShowExportButton Items=Items ClickToSelect=ClickToSelect ScrollMode=ScrollMode
|
||||||
ShowExportCsvButton=@ShowExportCsvButton ShowCardView=ShowCardView
|
ShowExportCsvButton=@ShowExportCsvButton ShowCardView=ShowCardView OnColumnVisibleChanged=OnColumnVisibleChanged
|
||||||
FixedExtendButtonsColumn=FixedExtendButtonsColumn FixedMultipleColumn=FixedMultipleColumn FixedDetailRowHeaderColumn=FixedDetailRowHeaderColumn FixedLineNoColumn=FixedLineNoColumn
|
FixedExtendButtonsColumn=FixedExtendButtonsColumn FixedMultipleColumn=FixedMultipleColumn FixedDetailRowHeaderColumn=FixedDetailRowHeaderColumn FixedLineNoColumn=FixedLineNoColumn
|
||||||
IsAutoRefresh=IsAutoRefresh AutoRefreshInterval=AutoRefreshInterval
|
IsAutoRefresh=IsAutoRefresh AutoRefreshInterval=AutoRefreshInterval
|
||||||
AllowDragColumn=@AllowDragColumn Height=@Height ShowRefresh=ShowRefresh
|
AllowDragColumn=@AllowDragColumn Height=@Height ShowRefresh=ShowRefresh
|
||||||
|
@@ -13,13 +13,22 @@ 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}.OnColumnVisibleChanged"/>
|
||||||
|
[Parameter]
|
||||||
|
public Func<string,bool, Task> OnColumnVisibleChanged { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Table{TItem}.OnColumnCreating"/>
|
||||||
|
[Parameter]
|
||||||
|
public Func<List<ITableColumn>,Task> OnColumnCreating { get; set; }
|
||||||
/// <inheritdoc cref="Table{TItem}.RenderMode"/>
|
/// <inheritdoc cref="Table{TItem}.RenderMode"/>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public TableRenderMode RenderMode { get; set; }
|
public TableRenderMode RenderMode { get; set; }
|
||||||
|
|
||||||
public List<ITableColumn> Columns => Instance?.Columns;
|
public List<ITableColumn> Columns => Instance?.Columns;
|
||||||
|
|
||||||
|
public IEnumerable<ITableColumn> GetVisibleColumns => Instance?.GetVisibleColumns();
|
||||||
|
public List<TItem> Rows => Instance?.Rows;
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Table{TItem}.SelectedRowsChanged"/>
|
/// <inheritdoc cref="Table{TItem}.SelectedRowsChanged"/>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
@@ -158,6 +167,9 @@ public partial class AdminTable<TItem> where TItem : class, new()
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public IDataService<TItem> DataService { get; set; }
|
public IDataService<TItem> DataService { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="Table{TItem}.CreateItemCallback"/>
|
/// <inheritdoc cref="Table{TItem}.CreateItemCallback"/>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Func<TItem> CreateItemCallback { get; set; }
|
public Func<TItem> CreateItemCallback { get; set; }
|
||||||
|
@@ -72,7 +72,7 @@ public partial class HardwareInfoPage : IDisposable
|
|||||||
ChartDataSource.Options.Title = Localizer[nameof(HistoryHardwareInfo)];
|
ChartDataSource.Options.Title = Localizer[nameof(HistoryHardwareInfo)];
|
||||||
ChartDataSource.Options.X.Title = Localizer["DateTime"];
|
ChartDataSource.Options.X.Title = Localizer["DateTime"];
|
||||||
ChartDataSource.Options.Y.Title = Localizer["Data"];
|
ChartDataSource.Options.Y.Title = Localizer["Data"];
|
||||||
ChartDataSource.Labels = hisHardwareInfos.Select(a => a.Date.ToString("dd HH:mm zz"));
|
ChartDataSource.Labels = hisHardwareInfos.Select(a => a.Date.ToString("dd-HH:mm"));
|
||||||
ChartDataSource.Data.Add(new ChartDataset()
|
ChartDataSource.Data.Add(new ChartDataset()
|
||||||
{
|
{
|
||||||
Tension = 0.4f,
|
Tension = 0.4f,
|
||||||
@@ -116,7 +116,7 @@ public partial class HardwareInfoPage : IDisposable
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var hisHardwareInfos = await HardwareJob.GetHistoryHardwareInfos();
|
var hisHardwareInfos = await HardwareJob.GetHistoryHardwareInfos();
|
||||||
ChartDataSource.Labels = hisHardwareInfos.Select(a => a.Date.ToString("dd HH:mm zz"));
|
ChartDataSource.Labels = hisHardwareInfos.Select(a => a.Date.ToString("dd-HH:mm"));
|
||||||
ChartDataSource.Data[0].Data = hisHardwareInfos.Select(a => (object)a.CpuUsage);
|
ChartDataSource.Data[0].Data = hisHardwareInfos.Select(a => (object)a.CpuUsage);
|
||||||
ChartDataSource.Data[1].Data = hisHardwareInfos.Select(a => (object)a.MemoryUsage);
|
ChartDataSource.Data[1].Data = hisHardwareInfos.Select(a => (object)a.MemoryUsage);
|
||||||
ChartDataSource.Data[2].Data = hisHardwareInfos.Select(a => (object)a.DriveUsage);
|
ChartDataSource.Data[2].Data = hisHardwareInfos.Select(a => (object)a.DriveUsage);
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<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.3" />
|
<PackageReference Include="BootstrapBlazor.Chart" Version="9.0.4" />
|
||||||
<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.WinBox" Version="9.0.7" />
|
||||||
<PackageReference Include="BootstrapBlazor.CodeEditor" Version="9.0.3" />
|
<PackageReference Include="BootstrapBlazor.CodeEditor" Version="9.0.3" />
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||||
@@ -477,7 +477,7 @@ public class ConcurrentList<T> : IList<T>, IReadOnlyList<T>
|
|||||||
{
|
{
|
||||||
lock (((ICollection)m_list).SyncRoot)
|
lock (((ICollection)m_list).SyncRoot)
|
||||||
{
|
{
|
||||||
return m_list.IndexOf(item);
|
return m_list.LastIndexOf(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
<Project>
|
<Project>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PluginVersion>10.11.107</PluginVersion>
|
<PluginVersion>10.11.109</PluginVersion>
|
||||||
<ProPluginVersion>10.11.107</ProPluginVersion>
|
<ProPluginVersion>10.11.109</ProPluginVersion>
|
||||||
<DefaultVersion>10.11.107</DefaultVersion>
|
<DefaultVersion>10.11.109</DefaultVersion>
|
||||||
<AuthenticationVersion>10.11.6</AuthenticationVersion>
|
<AuthenticationVersion>10.11.6</AuthenticationVersion>
|
||||||
<SourceGeneratorVersion>10.11.6</SourceGeneratorVersion>
|
<SourceGeneratorVersion>10.11.6</SourceGeneratorVersion>
|
||||||
<NET8Version>8.0.21</NET8Version>
|
<NET8Version>8.0.21</NET8Version>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
@inherits ThingsGatewayModuleComponentBase
|
@inherits ThingsGatewayModuleComponentBase
|
||||||
@attribute [JSModuleAutoLoader("Components/QuickActions.razor.js", AutoInvokeDispose = false)]
|
@attribute [JSModuleAutoLoader("Components/QuickActions.razor.js", AutoInvokeDispose = false, AutoInvokeInit = true)]
|
||||||
@namespace ThingsGateway.Gateway.Razor
|
@namespace ThingsGateway.Gateway.Razor
|
||||||
|
|
||||||
<div id="@Id">
|
<div id="@Id">
|
||||||
@@ -8,12 +8,12 @@
|
|||||||
<div class="quickactions-list">
|
<div class="quickactions-list">
|
||||||
<div class="quickactions-header">
|
<div class="quickactions-header">
|
||||||
<div class="flex-fill">@HeaderText</div>
|
<div class="flex-fill">@HeaderText</div>
|
||||||
<button class="btn-close btn-close-white" type="button" aria-label="Close" onclick=@(async ()=>await ToggleOpen())></button>
|
<button class="btn-close btn-close-white" type="button" aria-label="Close" onclick=@(async () => await ToggleOpen())></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mx-2 row g-0">
|
<div class="mx-2 row g-0">
|
||||||
|
|
||||||
<div class="col-12 my-1">
|
<div class="col-12 my-1">
|
||||||
<RadioList ShowLabel="true" TValue="bool" IsButton ValueExpression=@(()=> AutoRestartThread ) Value="AutoRestartThread" ValueChanged="OnAutoRestartThreadChanged" Items="AutoRestartThreadBoolItems" />
|
<RadioList ShowLabel="true" TValue="bool" IsButton ValueExpression=@(() => AutoRestartThread) Value="AutoRestartThread" ValueChanged="OnAutoRestartThreadChanged" Items="AutoRestartThreadBoolItems" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -0,0 +1,18 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||||
|
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||||
|
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||||
|
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||||
|
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||||
|
// 使用文档:https://thingsgateway.cn/
|
||||||
|
// QQ群:605534569
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace ThingsGateway.Gateway.Razor;
|
||||||
|
|
||||||
|
public readonly struct CellValue
|
||||||
|
{
|
||||||
|
public readonly string Field { get; }
|
||||||
|
public readonly string Value { get; }
|
||||||
|
public CellValue(string f, string v) { Field = f; Value = v; }
|
||||||
|
}
|
@@ -0,0 +1,81 @@
|
|||||||
|
using ThingsGateway.NewLife.Caching;
|
||||||
|
using ThingsGateway.NewLife.Json.Extension;
|
||||||
|
|
||||||
|
namespace ThingsGateway.Gateway.Razor;
|
||||||
|
|
||||||
|
public static class VariableModelUtils
|
||||||
|
{
|
||||||
|
static MemoryCache MemoryCache = new();
|
||||||
|
public static object GetPropertyValue(VariableRuntime model, string fieldName)
|
||||||
|
{
|
||||||
|
if (model == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MemoryCache.TryGetValue(fieldName, out Func<VariableRuntime, object> data))
|
||||||
|
{
|
||||||
|
return data(model);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var ret = MemoryCache.GetOrAdd(fieldName, (fieldName) =>
|
||||||
|
{
|
||||||
|
return LambdaExtensions.GetPropertyValueLambda<VariableRuntime, object?>(model, fieldName).Compile();
|
||||||
|
})(model);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetValue(VariableRuntime row, string fieldName)
|
||||||
|
{
|
||||||
|
switch (fieldName)
|
||||||
|
{
|
||||||
|
case nameof(VariableRuntime.Value):
|
||||||
|
return row.Value?.ToSystemTextJsonString() ?? string.Empty;
|
||||||
|
case nameof(VariableRuntime.RawValue):
|
||||||
|
return row.RawValue?.ToSystemTextJsonString() ?? string.Empty;
|
||||||
|
case nameof(VariableRuntime.LastSetValue):
|
||||||
|
return row.LastSetValue?.ToSystemTextJsonString() ?? string.Empty;
|
||||||
|
case nameof(VariableRuntime.ChangeTime):
|
||||||
|
return row.ChangeTime.ToString("dd-HH:mm:ss.fff");
|
||||||
|
|
||||||
|
case nameof(VariableRuntime.CollectTime):
|
||||||
|
return row.CollectTime.ToString("dd-HH:mm:ss.fff");
|
||||||
|
|
||||||
|
case nameof(VariableRuntime.IsOnline):
|
||||||
|
return row.IsOnline.ToString();
|
||||||
|
|
||||||
|
case nameof(VariableRuntime.LastErrorMessage):
|
||||||
|
return row.LastErrorMessage;
|
||||||
|
|
||||||
|
|
||||||
|
case nameof(VariableRuntime.RuntimeType):
|
||||||
|
return row.RuntimeType;
|
||||||
|
default:
|
||||||
|
|
||||||
|
var ret = VariableModelUtils.GetPropertyValue(row, fieldName);
|
||||||
|
|
||||||
|
if (ret != null)
|
||||||
|
{
|
||||||
|
var t = ret.GetType();
|
||||||
|
if (t.IsEnum)
|
||||||
|
{
|
||||||
|
// 如果是枚举这里返回 枚举的描述信息
|
||||||
|
var itemName = ret.ToString();
|
||||||
|
if (!string.IsNullOrEmpty(itemName))
|
||||||
|
{
|
||||||
|
ret = Utility.GetDisplayName(t, itemName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret is string str ? str : ret?.ToString() ?? string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Alignment GetAlign(this ITableColumn col) => col.Align ?? Alignment.None;
|
||||||
|
internal static bool GetTextWrap(this ITableColumn col) => col.TextWrap ?? false;
|
||||||
|
internal static bool GetShowTips(this ITableColumn col) => col.ShowTips ?? false;
|
||||||
|
|
||||||
|
internal static bool GetTextEllipsis(this ITableColumn col) => col.TextEllipsis ?? false;
|
||||||
|
}
|
@@ -9,11 +9,18 @@
|
|||||||
|
|
||||||
@foreach (var col in RowContent.Columns)
|
@foreach (var col in RowContent.Columns)
|
||||||
{
|
{
|
||||||
<td class="@GetFixedCellClassString(col)" style="@GetFixedCellStyleString(col)">
|
<td class="@GetFixedCellClassString(col)" style="@GetFixedCellStyleString(col)" @key=col>
|
||||||
<DynamicElement TagName="div" TriggerClick="@false"
|
<div class="@GetCellClassString(col, false, false)" @key=col>
|
||||||
StopPropagation="false"
|
@if(col.GetShowTips())
|
||||||
class="@GetCellClassString(col, false, false)">
|
{
|
||||||
@GetValue(col, RowContent.Row)
|
<Tooltip @key=col Title="@VariableModelUtils.GetValue(RowContent.Row, col.GetFieldName())" class="text-truncate d-block">
|
||||||
</DynamicElement>
|
@VariableModelUtils.GetValue(RowContent.Row, col.GetFieldName())
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@VariableModelUtils.GetValue(RowContent.Row, col.GetFieldName())
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
}
|
}
|
||||||
|
@@ -10,40 +10,36 @@
|
|||||||
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
using ThingsGateway.NewLife.Threading;
|
|
||||||
|
|
||||||
using TouchSocket.Core;
|
|
||||||
|
|
||||||
namespace ThingsGateway.Gateway.Razor;
|
namespace ThingsGateway.Gateway.Razor;
|
||||||
|
|
||||||
public partial class VariableRow : IDisposable
|
public partial class VariableRow
|
||||||
{
|
{
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public TableRowContext<VariableRuntime>? RowContent { get; set; }
|
public TableRowContext<VariableRuntime>? RowContent { get; set; }
|
||||||
private bool Disposed;
|
//private bool Disposed;
|
||||||
public void Dispose()
|
//public void Dispose()
|
||||||
{
|
//{
|
||||||
Disposed = true;
|
// Disposed = true;
|
||||||
timer?.SafeDispose();
|
// timer?.SafeDispose();
|
||||||
GC.SuppressFinalize(this);
|
// GC.SuppressFinalize(this);
|
||||||
}
|
//}
|
||||||
TimerX? timer;
|
//TimerX? timer;
|
||||||
protected override void OnAfterRender(bool firstRender)
|
//protected override void OnAfterRender(bool firstRender)
|
||||||
{
|
//{
|
||||||
if (firstRender)
|
// if (firstRender)
|
||||||
{
|
// {
|
||||||
timer = new TimerX(Refresh, null, 1000, 1000, "VariableRow");
|
// timer = new TimerX(Refresh, null, 1000, 1000, "VariableRow");
|
||||||
}
|
// }
|
||||||
base.OnAfterRender(firstRender);
|
// base.OnAfterRender(firstRender);
|
||||||
}
|
//}
|
||||||
|
|
||||||
private Task Refresh(object? state)
|
//private Task Refresh(object? state)
|
||||||
{
|
//{
|
||||||
if (!Disposed)
|
// if (!Disposed)
|
||||||
return InvokeAsync(StateHasChanged);
|
// return InvokeAsync(StateHasChanged);
|
||||||
else
|
// else
|
||||||
return Task.CompletedTask;
|
// return Task.CompletedTask;
|
||||||
}
|
//}
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
@@ -51,32 +47,6 @@ public partial class VariableRow : IDisposable
|
|||||||
CellClassStringCache?.Clear();
|
CellClassStringCache?.Clear();
|
||||||
base.OnParametersSet();
|
base.OnParametersSet();
|
||||||
}
|
}
|
||||||
/// <summary>
|
|
||||||
/// 获得 指定单元格数据方法
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="col"></param>
|
|
||||||
/// <param name="item"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected static RenderFragment GetValue(ITableColumn col, VariableRuntime item) => builder =>
|
|
||||||
{
|
|
||||||
if (col.Template != null)
|
|
||||||
{
|
|
||||||
builder.AddContent(0, col.Template(item));
|
|
||||||
}
|
|
||||||
else if (col.ComponentType == typeof(ColorPicker))
|
|
||||||
{
|
|
||||||
// 自动化处理 ColorPicker 组件
|
|
||||||
builder.AddContent(10, col.RenderColor(item));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
builder.AddContent(20, col.RenderValue(item));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// internal static string? GetDoubleClickCellClassString(bool trigger) => CssBuilder.Default()
|
|
||||||
//.AddClass("is-dbcell", trigger)
|
|
||||||
//.Build();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获得指定列头固定列样式
|
/// 获得指定列头固定列样式
|
||||||
@@ -209,7 +179,7 @@ public partial class VariableRow : IDisposable
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return FixedCellClassStringCache.GetOrAdd(col, col => CssBuilder.Default()
|
return FixedCellClassStringCache.GetOrAdd(col, col => CssBuilder.Default(col.GetFieldName())
|
||||||
.AddClass("fixed", col.Fixed)
|
.AddClass("fixed", col.Fixed)
|
||||||
.AddClass("fixed-right", col.Fixed && IsTail(col))
|
.AddClass("fixed-right", col.Fixed && IsTail(col))
|
||||||
.AddClass("fr", IsLastColumn(col))
|
.AddClass("fr", IsLastColumn(col))
|
||||||
|
@@ -1,60 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
|
||||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
|
||||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
|
||||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
|
||||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
|
||||||
// 使用文档:https://thingsgateway.cn/
|
|
||||||
// QQ群:605534569
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace ThingsGateway.Gateway.Razor;
|
|
||||||
|
|
||||||
internal static class VariableRowHelpers
|
|
||||||
{
|
|
||||||
internal static Alignment GetAlign(this ITableColumn col) => col.Align ?? Alignment.None;
|
|
||||||
internal static bool GetTextWrap(this ITableColumn col) => col.TextWrap ?? false;
|
|
||||||
internal static bool GetShowTips(this ITableColumn col) => col.ShowTips ?? false;
|
|
||||||
|
|
||||||
|
|
||||||
internal static RenderFragment RenderColor<TItem>(this ITableColumn col, TItem item) => builder =>
|
|
||||||
{
|
|
||||||
var val = GetItemValue(col, item);
|
|
||||||
var v = val?.ToString() ?? "#000";
|
|
||||||
var style = $"background-color: {v};";
|
|
||||||
builder.OpenElement(0, "div");
|
|
||||||
builder.AddAttribute(1, "class", "is-color");
|
|
||||||
builder.AddAttribute(2, "style", style);
|
|
||||||
builder.CloseElement();
|
|
||||||
};
|
|
||||||
internal static object? GetItemValue<TItem>(this ITableColumn col, TItem item)
|
|
||||||
{
|
|
||||||
var fieldName = col.GetFieldName();
|
|
||||||
object? ret;
|
|
||||||
if (item is IDynamicObject dynamicObject)
|
|
||||||
{
|
|
||||||
ret = dynamicObject.GetValue(fieldName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = Utility.GetPropertyValue<TItem, object?>(item, fieldName);
|
|
||||||
|
|
||||||
if (ret != null)
|
|
||||||
{
|
|
||||||
var t = ret.GetType();
|
|
||||||
if (t.IsEnum)
|
|
||||||
{
|
|
||||||
// 如果是枚举这里返回 枚举的描述信息
|
|
||||||
var itemName = ret.ToString();
|
|
||||||
if (!string.IsNullOrEmpty(itemName))
|
|
||||||
{
|
|
||||||
ret = Utility.GetDisplayName(t, itemName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
internal static bool GetTextEllipsis(this ITableColumn col) => col.TextEllipsis ?? false;
|
|
||||||
|
|
||||||
}
|
|
@@ -4,10 +4,16 @@
|
|||||||
@using ThingsGateway.Admin.Application
|
@using ThingsGateway.Admin.Application
|
||||||
@using ThingsGateway.Admin.Razor
|
@using ThingsGateway.Admin.Razor
|
||||||
@using ThingsGateway.Gateway.Application
|
@using ThingsGateway.Gateway.Application
|
||||||
@inherits ComponentDefault
|
@attribute [JSModuleAutoLoader("Pages/GatewayMonitorPage/Variable/VariableRuntimeInfo.razor.js", AutoInvokeInit = true, AutoInvokeDispose = false, JSObjectReference = true)]
|
||||||
|
@inherits ThingsGatewayModuleComponentBase
|
||||||
|
|
||||||
<AdminTable @ref=table BeforeShowEditDialogCallback="BeforeShowEditDialogCallback"
|
@* RenderMode="TableRenderMode.Table"
|
||||||
|
ShowCardView=false *@
|
||||||
|
|
||||||
|
<AdminTable Id=@Id @ref=table BeforeShowEditDialogCallback="BeforeShowEditDialogCallback"
|
||||||
TItem="VariableRuntime"
|
TItem="VariableRuntime"
|
||||||
|
RenderMode="TableRenderMode.Table"
|
||||||
|
ShowCardView=false
|
||||||
EditDialogSize="Size.ExtraLarge"
|
EditDialogSize="Size.ExtraLarge"
|
||||||
AutoGenerateColumns="true"
|
AutoGenerateColumns="true"
|
||||||
ShowAdvancedSearch=false
|
ShowAdvancedSearch=false
|
||||||
@@ -15,13 +21,13 @@
|
|||||||
AllowResizing="true"
|
AllowResizing="true"
|
||||||
OnAdd="OnAdd"
|
OnAdd="OnAdd"
|
||||||
IsFixedHeader=true
|
IsFixedHeader=true
|
||||||
ShowCardView=false
|
|
||||||
IsMultipleSelect=true
|
IsMultipleSelect=true
|
||||||
SearchMode=SearchMode.Top
|
SearchMode=SearchMode.Top
|
||||||
ShowExtendButtons=true
|
ShowExtendButtons=true
|
||||||
ShowToolbar="true"
|
ShowToolbar="true"
|
||||||
ShowExportButton
|
ShowExportButton
|
||||||
RenderMode="TableRenderMode.Table"
|
OnColumnCreating="OnColumnCreating"
|
||||||
|
OnColumnVisibleChanged=OnColumnVisibleChanged
|
||||||
ShowDefaultButtons=true
|
ShowDefaultButtons=true
|
||||||
ShowSearch=false
|
ShowSearch=false
|
||||||
ExtendButtonColumnWidth=220
|
ExtendButtonColumnWidth=220
|
||||||
@@ -40,8 +46,8 @@
|
|||||||
<TableColumn @bind-Field="@context.RpcWriteCheck" ShowTips=true Filterable=true Sortable=true Visible=false />
|
<TableColumn @bind-Field="@context.RpcWriteCheck" ShowTips=true Filterable=true Sortable=true Visible=false />
|
||||||
|
|
||||||
<TableColumn @bind-Field="@context.Enable" Filterable=true Sortable=true Visible="false" />
|
<TableColumn @bind-Field="@context.Enable" Filterable=true Sortable=true Visible="false" />
|
||||||
<TableColumn Field="@context.ChangeTime" ShowTips=true FieldExpression=@(() => context.ChangeTime) Filterable=true Sortable=true Visible=false />
|
<TableColumn Field="@context.ChangeTime" Width=120 ShowTips=true FieldExpression=@(() => context.ChangeTime) Filterable=true Sortable=true Visible=false />
|
||||||
<TableColumn Field="@context.CollectTime" ShowTips=true FieldExpression=@(() => context.CollectTime) Filterable=true Sortable=true Visible=true />
|
<TableColumn Field="@context.CollectTime" Width=120 ShowTips =true FieldExpression=@(() => context.CollectTime) Filterable=true Sortable=true Visible=true />
|
||||||
<TableColumn Field="@context.IsOnline" FieldExpression=@(() => context.IsOnline) Filterable=true Sortable=true Visible=true />
|
<TableColumn Field="@context.IsOnline" FieldExpression=@(() => context.IsOnline) Filterable=true Sortable=true Visible=true />
|
||||||
<TableColumn Field="@context.LastErrorMessage" ShowTips=true FieldExpression=@(() => context.LastErrorMessage) Filterable=true Sortable=true Visible=false />
|
<TableColumn Field="@context.LastErrorMessage" ShowTips=true FieldExpression=@(() => context.LastErrorMessage) Filterable=true Sortable=true Visible=false />
|
||||||
|
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
using Microsoft.AspNetCore.Components.Forms;
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
using ThingsGateway.Admin.Application;
|
using ThingsGateway.Admin.Application;
|
||||||
using ThingsGateway.Admin.Razor;
|
using ThingsGateway.Admin.Razor;
|
||||||
@@ -19,11 +20,107 @@ using ThingsGateway.NewLife.Json.Extension;
|
|||||||
|
|
||||||
namespace ThingsGateway.Gateway.Razor;
|
namespace ThingsGateway.Gateway.Razor;
|
||||||
|
|
||||||
public partial class VariableRuntimeInfo : IDisposable
|
public partial class VariableRuntimeInfo
|
||||||
{
|
{
|
||||||
public List<ITableColumn> ColumnsFunc()
|
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
protected BlazorAppContext? AppContext { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
private NavigationManager? NavigationManager { get; set; }
|
||||||
|
|
||||||
|
public string RouteName => NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
|
||||||
|
|
||||||
|
protected bool AuthorizeButton(string operate)
|
||||||
{
|
{
|
||||||
return table?.Columns;
|
return AppContext.IsHasButtonWithRole(RouteName, operate);
|
||||||
|
}
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
public IStringLocalizer<ThingsGateway.Razor._Imports>? RazorLocalizer { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
public IStringLocalizer<ThingsGateway.Admin.Razor._Imports>? AdminLocalizer { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
public DialogService? DialogService { get; set; }
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public IStringLocalizer? Localizer { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
public IStringLocalizer<OperDescAttribute>? OperDescLocalizer { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
public ToastService? ToastService { get; set; }
|
||||||
|
|
||||||
|
#region js
|
||||||
|
private List<ITableColumn> ColumnsFunc()
|
||||||
|
{
|
||||||
|
return table.Columns;
|
||||||
|
}
|
||||||
|
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, new { Method = nameof(TriggerStateChanged) });
|
||||||
|
|
||||||
|
private Task OnColumnVisibleChanged(string name, bool visible)
|
||||||
|
{
|
||||||
|
_cachedFields = table.GetVisibleColumns.ToArray();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
private Task OnColumnCreating(List<ITableColumn> columns)
|
||||||
|
{
|
||||||
|
foreach (var column in columns)
|
||||||
|
{
|
||||||
|
column.OnCellRender = a =>
|
||||||
|
{
|
||||||
|
a.Class = $"{column.GetFieldName()}";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ITableColumn[] _cachedFields = Array.Empty<ITableColumn>();
|
||||||
|
|
||||||
|
[JSInvokable]
|
||||||
|
public List<CellValue> TriggerStateChanged(int rowIndex)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
if (table == null) return null;
|
||||||
|
var row = table.Rows[rowIndex];
|
||||||
|
if (_cachedFields.Length == 0) _cachedFields = table.GetVisibleColumns.ToArray();
|
||||||
|
var list = new List<CellValue>(_cachedFields.Length);
|
||||||
|
foreach (var col in _cachedFields)
|
||||||
|
{
|
||||||
|
var fieldName = col.GetFieldName();
|
||||||
|
list.Add(new(fieldName, VariableModelUtils.GetValue(row,fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
protected override void OnAfterRender(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender || _cachedFields.Length == 0)
|
||||||
|
{
|
||||||
|
_cachedFields = table.GetVisibleColumns.ToArray();
|
||||||
|
}
|
||||||
|
base.OnAfterRender(firstRender);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !Management
|
#if !Management
|
||||||
@@ -43,17 +140,16 @@ public partial class VariableRuntimeInfo : IDisposable
|
|||||||
[Inject]
|
[Inject]
|
||||||
private IOptions<WebsiteOptions>? WebsiteOption { get; set; }
|
private IOptions<WebsiteOptions>? WebsiteOption { get; set; }
|
||||||
public bool Disposed { get; set; }
|
public bool Disposed { get; set; }
|
||||||
|
protected override ValueTask DisposeAsync(bool disposing)
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
{
|
||||||
Disposed = true;
|
Disposed = true;
|
||||||
VariableRuntimeDispatchService.UnSubscribe(Refresh);
|
VariableRuntimeDispatchService.UnSubscribe(Refresh);
|
||||||
GC.SuppressFinalize(this);
|
return base.DisposeAsync(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
|
Localizer = App.CreateLocalizerByType(GetType());
|
||||||
VariableRuntimeDispatchService.Subscribe(Refresh);
|
VariableRuntimeDispatchService.Subscribe(Refresh);
|
||||||
|
|
||||||
scheduler = new SmartTriggerScheduler(Notify, TimeSpan.FromMilliseconds(1000));
|
scheduler = new SmartTriggerScheduler(Notify, TimeSpan.FromMilliseconds(1000));
|
||||||
|
@@ -0,0 +1,94 @@
|
|||||||
|
export function init(id, invoke, options) {
|
||||||
|
function getCellByClass(row, className) {
|
||||||
|
// 直接用 querySelector 精确查找
|
||||||
|
return row.querySelector(`td.${className}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
var variableHandler = setInterval(async () => {
|
||||||
|
var admintable = document.getElementById(id);
|
||||||
|
|
||||||
|
var tables = admintable.getElementsByTagName('table');
|
||||||
|
|
||||||
|
if (!tables || tables.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = tables[tables.length - 1];
|
||||||
|
|
||||||
|
if (!table) {
|
||||||
|
clearInterval(variableHandler)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var rowCount = table.rows.length;
|
||||||
|
var { method } = options;
|
||||||
|
|
||||||
|
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
||||||
|
|
||||||
|
|
||||||
|
var row = table.rows[rowIndex];
|
||||||
|
if (!row) continue;
|
||||||
|
|
||||||
|
var vals = await invoke.invokeMethodAsync(method, rowIndex);
|
||||||
|
if (vals == null) continue;
|
||||||
|
|
||||||
|
for (let i = 0; i < vals.length; i++) {
|
||||||
|
const cellName = vals[i].field;
|
||||||
|
const cellValue = vals[i].value;
|
||||||
|
if (cellValue == null) continue;
|
||||||
|
|
||||||
|
var cell = getCellByClass(row, cellName)
|
||||||
|
|
||||||
|
if (!cell) continue;
|
||||||
|
|
||||||
|
// 查找 tooltip span
|
||||||
|
var cellDiv = cell.querySelector('.table-cell');
|
||||||
|
if (cellDiv) {
|
||||||
|
var tooltipSpan = cell.querySelector('.bb-tooltip');
|
||||||
|
if (tooltipSpan) {
|
||||||
|
|
||||||
|
tooltipSpan.innerText = cellValue ?? ''; // 更新显示文字
|
||||||
|
tooltipSpan.setAttribute('data-bs-original-title', cellValue ?? ''); // 同步 tooltip 提示
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cellDiv.innerText = cellValue ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//// 查找 switch
|
||||||
|
//var switchDiv = cell.querySelector('.switch');
|
||||||
|
//if (switchDiv) {
|
||||||
|
// if (cellValue === true || cellValue === "on" || cellValue === "True" || cellValue === "true") {
|
||||||
|
// switchDiv.classList.add('is-checked');
|
||||||
|
// switchDiv.classList.add('enable');
|
||||||
|
// switchDiv.classList.remove('is-unchecked');
|
||||||
|
// switchDiv.classList.remove('disabled');
|
||||||
|
|
||||||
|
// switchDiv.querySelectorAll('span')[0].classList.add('border-success');
|
||||||
|
// switchDiv.querySelectorAll('span')[0].classList.add('bg-success');
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// switchDiv.classList.remove('is-checked');
|
||||||
|
// switchDiv.classList.remove('enable');
|
||||||
|
// switchDiv.classList.add('is-unchecked');
|
||||||
|
// switchDiv.classList.add('disabled');
|
||||||
|
|
||||||
|
// switchDiv.querySelectorAll('span')[0].classList.remove('border-success');
|
||||||
|
// switchDiv.querySelectorAll('span')[0].classList.remove('bg-success');
|
||||||
|
// }
|
||||||
|
// continue;
|
||||||
|
//}
|
||||||
|
//// 默认情况(普通单元格)
|
||||||
|
//getCellByClass(row, cellName).innerText = cellValue;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, 500) //1000ms刷新一次
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@@ -118,20 +118,20 @@ public partial class SiemensS7Master : DeviceBase
|
|||||||
return new DeviceSingleStreamDataHandleAdapter<S7Message>
|
return new DeviceSingleStreamDataHandleAdapter<S7Message>
|
||||||
{
|
{
|
||||||
CacheTimeout = TimeSpan.FromMilliseconds(Channel.ChannelOptions.CacheTimeout),
|
CacheTimeout = TimeSpan.FromMilliseconds(Channel.ChannelOptions.CacheTimeout),
|
||||||
IsSingleThread = false
|
//IsSingleThread = false
|
||||||
};
|
};
|
||||||
|
|
||||||
case ChannelTypeEnum.UdpSession:
|
case ChannelTypeEnum.UdpSession:
|
||||||
return new DeviceUdpDataHandleAdapter<S7Message>()
|
return new DeviceUdpDataHandleAdapter<S7Message>()
|
||||||
{
|
{
|
||||||
IsSingleThread = false
|
//IsSingleThread = false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DeviceSingleStreamDataHandleAdapter<S7Message>
|
return new DeviceSingleStreamDataHandleAdapter<S7Message>
|
||||||
{
|
{
|
||||||
CacheTimeout = TimeSpan.FromMilliseconds(Channel.ChannelOptions.CacheTimeout),
|
CacheTimeout = TimeSpan.FromMilliseconds(Channel.ChannelOptions.CacheTimeout),
|
||||||
IsSingleThread = false
|
//IsSingleThread = false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user