diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 22894202e..81c7fe39f 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 7.2.0.11 - 9.0.2.11 + 7.2.0.17 + 9.0.2.12 9.0.2.18 diff --git a/src/Foundation/ThingsGateway.CSScript/ThingsGateway.CSScript.csproj b/src/Foundation/ThingsGateway.CSScript/ThingsGateway.CSScript.csproj index f69ff22e2..9f2eb807d 100644 --- a/src/Foundation/ThingsGateway.CSScript/ThingsGateway.CSScript.csproj +++ b/src/Foundation/ThingsGateway.CSScript/ThingsGateway.CSScript.csproj @@ -1,17 +1,25 @@ - - + + - - netstandard2.0;net9.0;net8.0;net6.0; - + + netstandard2.0;net9.0;net8.0;net6.0; + - - - - + + - - - + + + + + + + + + + + + + diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Controler/GatewayExportController.cs b/src/Gateway/ThingsGateway.Gateway.Application/Controler/GatewayExportController.cs index 03907b2bb..a76783ccb 100644 --- a/src/Gateway/ThingsGateway.Gateway.Application/Controler/GatewayExportController.cs +++ b/src/Gateway/ThingsGateway.Gateway.Application/Controler/GatewayExportController.cs @@ -10,15 +10,88 @@ using BootstrapBlazor.Components; +using Mapster; + +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace ThingsGateway.Gateway.Application; +/// +/// 查询条件实体类 +/// +public class QueryPageOptionsDto +{ + /// + /// 获得/设置 模糊查询关键字 + /// + public string? SearchText { get; set; } + /// + /// 获得 排序字段名称 由 设置 + /// + public string? SortName { get; set; } + + /// + /// 获得 排序方式 由 设置 + /// + public SortOrder SortOrder { get; set; } + + /// + /// 获得/设置 多列排序集合 默认为 Empty 内部为 "Name" "Age desc" 由 设置 + /// + public List SortList { get; } = new(10); + + /// + /// 获得/设置 自定义多列排序集合 默认为 Empty 内部为 "Name" "Age desc" 由 设置 + /// + public List AdvancedSortList { get; } = new(10); + + /// + /// 获得 搜索条件绑定模型 未设置 时为 泛型模型 + /// + public object? SearchModel { get; set; } + + /// + /// 获得 当前页码 首页为 第一页 + /// + public int PageIndex { get; set; } = 1; + + /// + /// 获得 请求读取数据开始行 默认 0 + /// + /// 开启虚拟滚动 时使用 + public int StartIndex { get; set; } + + public int PageItems { get; set; } = 20; + + /// + /// 获得 是否分页查询模式 默认为 false 由 设置 + /// + public bool IsPage { get; set; } + + /// + /// 获得 是否为虚拟滚动查询模式 默认为 false 由 设置 + /// + public bool IsVirtualScroll { get; set; } + + /// + /// 获得 是否为首次查询 默认 false + /// + /// 组件首次查询数据时为 true + public bool IsFirstQuery { get; set; } +} +public class ExportDto +{ + public QueryPageOptionsDto QueryPageOptions { get; set; } = new(); + public FilterKeyValueAction FilterKeyValueAction { get; set; } = new(); +} /// /// 导出文件 /// [ApiDescriptionSettings(false)] [Route("api/gatewayExport")] +[IgnoreRolePermission] +[Authorize] [LoggingMonitor] public class GatewayExportController : ControllerBase { @@ -27,7 +100,6 @@ public class GatewayExportController : ControllerBase private readonly IVariableService _variableService; private readonly IImportExportService _importExportService; - public GatewayExportController( IChannelService channelService, IDeviceService deviceService, @@ -46,12 +118,12 @@ public class GatewayExportController : ControllerBase /// 下载设备 /// /// - [HttpGet("businessdevice")] - public async Task DownloadBusinessDeviceAsync([FromQuery] QueryPageOptions input) + [HttpPost("businessdevice")] + public async Task DownloadBusinessDeviceAsync([FromBody] ExportDto input) { - input.IsPage = false; - input.IsVirtualScroll = false; - var sheets = await _deviceService.ExportDeviceAsync(input, PluginTypeEnum.Business).ConfigureAwait(false); + input.QueryPageOptions.IsPage = false; + input.QueryPageOptions.IsVirtualScroll = false; + var sheets = await _deviceService.ExportDeviceAsync(input.QueryPageOptions.Adapt(), PluginTypeEnum.Business, input.FilterKeyValueAction).ConfigureAwait(false); return await _importExportService.ExportAsync(sheets, "BusinessDevice", false).ConfigureAwait(false); } @@ -60,13 +132,13 @@ public class GatewayExportController : ControllerBase /// 下载通道 /// /// - [HttpGet("channel")] - public async Task DownloadChannelAsync([FromQuery] QueryPageOptions input) + [HttpPost("channel")] + public async Task DownloadChannelAsync([FromBody] ExportDto input) { - input.IsPage = false; - input.IsVirtualScroll = false; + input.QueryPageOptions.IsPage = false; + input.QueryPageOptions.IsVirtualScroll = false; - var sheets = await _channelService.ExportChannelAsync(input).ConfigureAwait(false); + var sheets = await _channelService.ExportChannelAsync(input.QueryPageOptions.Adapt(), input.FilterKeyValueAction).ConfigureAwait(false); return await _importExportService.ExportAsync(sheets, "Channel", false).ConfigureAwait(false); } @@ -74,13 +146,13 @@ public class GatewayExportController : ControllerBase /// 下载设备 /// /// - [HttpGet("collectdevice")] - public async Task DownloadCollectDeviceAsync([FromQuery] QueryPageOptions input) + [HttpPost("collectdevice")] + public async Task DownloadCollectDeviceAsync([FromBody] ExportDto input) { - input.IsPage = false; - input.IsVirtualScroll = false; + input.QueryPageOptions.IsPage = false; + input.QueryPageOptions.IsVirtualScroll = false; - var sheets = await _deviceService.ExportDeviceAsync(input, PluginTypeEnum.Collect).ConfigureAwait(false); + var sheets = await _deviceService.ExportDeviceAsync(input.QueryPageOptions.Adapt(), PluginTypeEnum.Collect, input.FilterKeyValueAction).ConfigureAwait(false); return await _importExportService.ExportAsync(sheets, "CollectDevice", false).ConfigureAwait(false); } @@ -88,13 +160,13 @@ public class GatewayExportController : ControllerBase /// 下载变量 /// /// - [HttpGet("variable")] - public async Task DownloadVariableAsync([FromQuery] QueryPageOptions input) + [HttpPost("variable")] + public async Task DownloadVariableAsync([FromBody] ExportDto input) { - input.IsPage = false; - input.IsVirtualScroll = false; + input.QueryPageOptions.IsPage = false; + input.QueryPageOptions.IsVirtualScroll = false; - var sheets = await _variableService.ExportVariableAsync(input).ConfigureAwait(false); + var sheets = await _variableService.ExportVariableAsync(input.QueryPageOptions.Adapt(), input.FilterKeyValueAction).ConfigureAwait(false); return await _importExportService.ExportAsync(sheets, "Variable", false).ConfigureAwait(false); } } diff --git a/src/Gateway/ThingsGateway.Gateway.Application/SeedData/Gateway/seed_gateway_resource.json b/src/Gateway/ThingsGateway.Gateway.Application/SeedData/Gateway/seed_gateway_resource.json index ad2a1196b..fe500c2b9 100644 --- a/src/Gateway/ThingsGateway.Gateway.Application/SeedData/Gateway/seed_gateway_resource.json +++ b/src/Gateway/ThingsGateway.Gateway.Application/SeedData/Gateway/seed_gateway_resource.json @@ -20,6 +20,7 @@ "SortCode": 0, "ExtJson": null }, + { "Id": 61100022003, "ParentId": 6100001, @@ -1007,6 +1008,27 @@ "SortCode": 102, "ExtJson": null }, + { + "Id": 11000022001002, + "ParentId": 0, + "Module": 6, + "Title": "重启", + "Icon": null, + "Code": "System", + "Category": 2, + "Target": null, + "NavLinkMatch": null, + "Href": null, + "CreateTime": "5/11/2024 04:08:09.92", + "CreateUser": "SuperAdmin", + "CreateUserId": 212725263002001, + "IsDelete": "0", + "UpdateTime": "5/11/2024 04:28:42.83", + "UpdateUser": null, + "UpdateUserId": null, + "SortCode": null, + "ExtJson": null + }, { "Id": 6100002, "ParentId": 0, diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/ChannelService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/ChannelService.cs index bce4d62f7..c4e6265e0 100644 --- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/ChannelService.cs +++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/ChannelService.cs @@ -174,14 +174,15 @@ internal class ChannelService : BaseService, IChannelService /// 报表查询 /// /// 查询条件 - public async Task> PageAsync(QueryPageOptions option) + /// 查询条件 + public async Task> PageAsync(QueryPageOptions option, FilterKeyValueAction filterKeyValueAction = null) { var dataScope = await SysUserService.GetCurrentUserDataScopeAsync(); return await QueryAsync(option, a => a .WhereIF(!option.SearchText.IsNullOrWhiteSpace(), a => a.Name.Contains(option.SearchText!)) .WhereIF(dataScope != null && dataScope?.Count > 0, u => dataScope.Contains(u.CreateOrgId))//在指定机构列表查询 .WhereIF(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId) - ); + , filterKeyValueAction); } /// @@ -273,9 +274,9 @@ internal class ChannelService : BaseService, IChannelService /// [OperDesc("ExportChannel", isRecordPar: false, localizerType: typeof(Channel))] - public async Task> ExportChannelAsync(QueryPageOptions options) + public async Task> ExportChannelAsync(QueryPageOptions options, FilterKeyValueAction filterKeyValueAction = null) { - var data = await PageAsync(options).ConfigureAwait(false); + var data = await PageAsync(options, filterKeyValueAction).ConfigureAwait(false); return ExportChannelCore(data.Items); } diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/IChannelService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/IChannelService.cs index 7e959b4e8..7ba2670e7 100644 --- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/IChannelService.cs +++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Channel/IChannelService.cs @@ -48,7 +48,7 @@ public interface IChannelService /// 导出通道为文件流结果 /// /// 文件流结果 - Task> ExportChannelAsync(QueryPageOptions options); + Task> ExportChannelAsync(QueryPageOptions options, FilterKeyValueAction filterKeyValueAction = null); /// /// 导出通道为内存流 @@ -84,7 +84,8 @@ public interface IChannelService /// 报表查询 /// /// 查询条件 - Task> PageAsync(QueryPageOptions option); + /// 查询条件 + Task> PageAsync(QueryPageOptions option, FilterKeyValueAction filterKeyValueAction = null); /// /// API查询 diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/DeviceService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/DeviceService.cs index d98d56dc1..3798ff7b0 100644 --- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/DeviceService.cs +++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/DeviceService.cs @@ -293,14 +293,15 @@ internal class DeviceService : BaseService, IDeviceService /// /// 查询条件 /// 查询条件 - public async Task> PageAsync(QueryPageOptions option, PluginTypeEnum pluginType) + /// 查询条件 + public async Task> PageAsync(QueryPageOptions option, PluginTypeEnum pluginType, FilterKeyValueAction filterKeyValueAction = null) { var dataScope = await SysUserService.GetCurrentUserDataScopeAsync(); return await QueryAsync(option, a => a .WhereIF(!option.SearchText.IsNullOrWhiteSpace(), a => a.Name.Contains(option.SearchText!)).Where(a => a.PluginType == pluginType) .WhereIF(dataScope != null && dataScope?.Count > 0, u => dataScope.Contains(u.CreateOrgId))//在指定机构列表查询 .WhereIF(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId) - ); + , filterKeyValueAction); } @@ -372,10 +373,10 @@ internal class DeviceService : BaseService, IDeviceService /// /// [OperDesc("ExportDevice", isRecordPar: false, localizerType: typeof(Device))] - public async Task> ExportDeviceAsync(QueryPageOptions options, PluginTypeEnum pluginType) + public async Task> ExportDeviceAsync(QueryPageOptions options, PluginTypeEnum pluginType, FilterKeyValueAction filterKeyValueAction = null) { //导出 - var data = await PageAsync(options, pluginType).ConfigureAwait(false); + var data = await PageAsync(options, pluginType, filterKeyValueAction).ConfigureAwait(false); string fileName; Dictionary sheets; ExportCore(data.Items, pluginType, out fileName, out sheets); diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/IDeviceService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/IDeviceService.cs index 283123e0a..b124286b2 100644 --- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/IDeviceService.cs +++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Device/IDeviceService.cs @@ -64,7 +64,7 @@ public interface IDeviceService /// 导出设备信息到文件流。 /// /// 导出的文件流 - Task> ExportDeviceAsync(QueryPageOptions options, PluginTypeEnum pluginType); + Task> ExportDeviceAsync(QueryPageOptions options, PluginTypeEnum pluginType, FilterKeyValueAction filterKeyValueAction = null); /// /// 导出设备信息到内存流。 @@ -115,8 +115,9 @@ public interface IDeviceService /// /// 查询条件 /// 查询条件 + /// 查询条件 /// 查询结果 - Task> PageAsync(QueryPageOptions option, PluginTypeEnum pluginType); + Task> PageAsync(QueryPageOptions option, PluginTypeEnum pluginType, FilterKeyValueAction filterKeyValueAction = null); /// /// API查询 diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayExport/GatewayExportService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayExport/GatewayExportService.cs index ce7edf99d..a4d747a12 100644 --- a/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayExport/GatewayExportService.cs +++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/GatewayExport/GatewayExportService.cs @@ -10,10 +10,14 @@ using BootstrapBlazor.Components; +using Mapster; + using Microsoft.JSInterop; using ThingsGateway.Extension; +using TouchSocket.Core; + namespace ThingsGateway.Gateway.Application; internal class GatewayExportService : IGatewayExportService @@ -30,7 +34,7 @@ internal class GatewayExportService : IGatewayExportService await using var ajaxJS = await JSRuntime.InvokeAsync("import", $"/_content/ThingsGateway.Razor/js/downloadFile.js"); string url = "api/gatewayExport/channel"; string fileName = DateTime.Now.ToFileDateTimeFormat(); - await ajaxJS.InvokeVoidAsync("blazor_downloadFile", url, fileName, dtoObject); + await ajaxJS.InvokeVoidAsync("postJson_downloadFile", url, fileName, new ExportDto() { FilterKeyValueAction = dtoObject.ToFilter(), QueryPageOptions = dtoObject.Adapt() }.ToJsonString()); } public async Task OnDeviceExport(QueryPageOptions dtoObject, bool collect) @@ -38,7 +42,7 @@ internal class GatewayExportService : IGatewayExportService await using var ajaxJS = await JSRuntime.InvokeAsync("import", $"/_content/ThingsGateway.Razor/js/downloadFile.js"); string url = collect ? "api/gatewayExport/collectdevice" : "api/gatewayExport/businessdevice"; string fileName = DateTime.Now.ToFileDateTimeFormat(); - await ajaxJS.InvokeVoidAsync("blazor_downloadFile", url, fileName, dtoObject); + await ajaxJS.InvokeVoidAsync("postJson_downloadFile", url, fileName, new ExportDto() { FilterKeyValueAction = dtoObject.ToFilter(), QueryPageOptions = dtoObject.Adapt() }.ToJsonString()); } public async Task OnVariableExport(QueryPageOptions dtoObject) @@ -46,6 +50,7 @@ internal class GatewayExportService : IGatewayExportService await using var ajaxJS = await JSRuntime.InvokeAsync("import", $"/_content/ThingsGateway.Razor/js/downloadFile.js"); string url = "api/gatewayExport/variable"; string fileName = DateTime.Now.ToFileDateTimeFormat(); - await ajaxJS.InvokeVoidAsync("blazor_downloadFile", url, fileName, dtoObject); + await ajaxJS.InvokeVoidAsync("postJson_downloadFile", url, fileName, new ExportDto() { FilterKeyValueAction = dtoObject.ToFilter(), QueryPageOptions = dtoObject.Adapt() }.ToJsonString()); + } } diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/IVariableService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/IVariableService.cs index 1149f9881..eb3fd8b2b 100644 --- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/IVariableService.cs +++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/IVariableService.cs @@ -64,8 +64,7 @@ public interface IVariableService /// /// 异步导出变量数据到文件流中。 /// - /// 查询分页选项。 - Task> ExportVariableAsync(QueryPageOptions options); + Task> ExportVariableAsync(QueryPageOptions options, FilterKeyValueAction filterKeyValueAction = null); /// /// 异步获取变量的运行时信息。 diff --git a/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableService.cs b/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableService.cs index c334cf075..4471011a1 100644 --- a/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableService.cs +++ b/src/Gateway/ThingsGateway.Gateway.Application/Services/Variable/VariableService.cs @@ -358,9 +358,9 @@ internal class VariableService : BaseService, IVariableService /// 导出文件 /// [OperDesc("ExportVariable", isRecordPar: false, localizerType: typeof(Variable))] - public async Task> ExportVariableAsync(QueryPageOptions options) + public async Task> ExportVariableAsync(QueryPageOptions options, FilterKeyValueAction filterKeyValueAction = null) { - var data = (await QueryAsync(options).ConfigureAwait(false)); + var data = (await QueryAsync(options, null, filterKeyValueAction).ConfigureAwait(false)); Dictionary sheets = ExportCore(data.Items); return sheets; } diff --git a/src/ThingsGateway.Server/Layout/MainLayout.razor b/src/ThingsGateway.Server/Layout/MainLayout.razor index feba77d7d..702cd4a8f 100644 --- a/src/ThingsGateway.Server/Layout/MainLayout.razor +++ b/src/ThingsGateway.Server/Layout/MainLayout.razor @@ -98,8 +98,10 @@ - - + @if(AppContext.IsHasButtonWithRole("", "重启")) + { + + } diff --git a/src/Version.props b/src/Version.props index d061b5706..585531fb2 100644 --- a/src/Version.props +++ b/src/Version.props @@ -1,6 +1,6 @@ - 7.2.0.15 + 7.2.0.16