mirror of
https://gitee.com/ThingsGateway/ThingsGateway.git
synced 2025-10-23 03:50:30 +08:00
release:6.0.5.9
refactor: 封装furion swagger文档 refactor:简化代码 refactor:更新依赖包
This commit is contained in:
@@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Http;
|
||||
|
||||
using System.Security.Claims;
|
||||
|
||||
using ThingsGateway.ASPNetCore;
|
||||
using ThingsGateway.NewLife.X;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
|
@@ -12,6 +12,8 @@ using SqlSugar;
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
using ThingsGateway.ASPNetCore;
|
||||
using ThingsGateway.Core;
|
||||
using ThingsGateway.Core.Extension;
|
||||
using ThingsGateway.Core.Json.Extension;
|
||||
using ThingsGateway.Logging;
|
||||
|
@@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
|
||||
[ApiDescriptionSettings(false)]
|
||||
[Route("api/auth")]
|
||||
[LoggingMonitor]
|
||||
public class AuthController : ControllerBase
|
||||
|
@@ -19,6 +19,7 @@ namespace ThingsGateway.Admin.Application;
|
||||
/// <summary>
|
||||
/// 文化 Controller
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(false)]
|
||||
[Route("[controller]/[action]")]
|
||||
public class CultureController : Controller
|
||||
{
|
||||
|
@@ -16,6 +16,7 @@ namespace ThingsGateway.Admin.Application;
|
||||
/// <summary>
|
||||
/// 文件下载
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(false)]
|
||||
[Route("api/file")]
|
||||
public class FileController : ControllerBase
|
||||
{
|
||||
|
@@ -1,82 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://kimdiego2098.github.io/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using ThingsGateway.Core;
|
||||
|
||||
using RouteAttribute = Microsoft.AspNetCore.Mvc.RouteAttribute;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
|
||||
/// <summary>
|
||||
/// Gitee WebHook
|
||||
/// </summary>
|
||||
[Route("api/[controller]/[action]")]
|
||||
[ApiController]
|
||||
public class GiteeController : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 跨域握手协议
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpOptions]
|
||||
public string Options() => string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gitee Webhook
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public IActionResult Webhook([FromQuery] string? id, [FromServices] IConfiguration config, [FromServices] IDispatchService<GiteePostBody> dispatch, [FromBody] GiteePostBody payload)
|
||||
{
|
||||
bool ret = false;
|
||||
if (Check())
|
||||
{
|
||||
// 全局推送
|
||||
if (payload.HeadCommit != null || payload.Commits?.Count > 0)
|
||||
{
|
||||
dispatch.Dispatch(new DispatchEntry<GiteePostBody>()
|
||||
{
|
||||
Name = "Gitee",
|
||||
Entry = payload
|
||||
});
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
return ret ? Ok() : Unauthorized();
|
||||
|
||||
bool Check()
|
||||
{
|
||||
var configId = config.GetValue<string>("WebHooks:Gitee:Id");
|
||||
var configToken = config.GetValue<string>("WebHooks:Gitee:Token");
|
||||
var token = "";
|
||||
if (Request.Headers.TryGetValue("X-Gitee-Token", out var val))
|
||||
{
|
||||
token = val.FirstOrDefault() ?? string.Empty;
|
||||
}
|
||||
return id == configId && token == configToken
|
||||
&& payload.Id == configId && payload.Password == configToken;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Webhook 测试接口
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public IActionResult Webhook()
|
||||
{
|
||||
return Ok(new { Message = "Ok" });
|
||||
}
|
||||
}
|
@@ -13,8 +13,16 @@ using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 登录
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings("ThingsGateway.OpenApi", Order = 200)]
|
||||
[Description("登录")]
|
||||
[Route("openapi/auth")]
|
||||
[LoggingMonitor]
|
||||
public class OpenApiController : ControllerBase
|
||||
@@ -27,6 +35,7 @@ public class OpenApiController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost("login")]
|
||||
[DisplayName("登录")]
|
||||
[AllowAnonymous]
|
||||
public async Task<OpenApiLoginOutput> LoginAsync([FromBody] OpenApiLoginInput input)
|
||||
{
|
||||
@@ -39,6 +48,7 @@ public class OpenApiController : ControllerBase
|
||||
|
||||
[HttpPost("logout")]
|
||||
[Authorize]
|
||||
[DisplayName("登出")]
|
||||
[IgnoreRolePermission]
|
||||
public async Task LogoutAsync()
|
||||
{
|
||||
|
@@ -1,28 +1,28 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://kimdiego2098.github.io/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://kimdiego2098.github.io/
|
||||
// QQ群:605534569
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
//using BootstrapBlazor.Components;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
//using Microsoft.AspNetCore.Authorization;
|
||||
//using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
//namespace ThingsGateway.Admin.Application;
|
||||
|
||||
[Route("api/[controller]/[action]")]
|
||||
[RolePermission]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
public class TestController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task Test(QueryPageOptions queryPageOptions)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
//[Route("api/[controller]/[action]")]
|
||||
//[RolePermission]
|
||||
//[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
//public class TestController : ControllerBase
|
||||
//{
|
||||
// [HttpGet]
|
||||
// public async Task Test(QueryPageOptions queryPageOptions)
|
||||
// {
|
||||
// await Task.CompletedTask;
|
||||
// }
|
||||
//}
|
||||
|
@@ -14,6 +14,8 @@ using Microsoft.AspNetCore.WebUtilities;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
|
||||
using ThingsGateway.ASPNetCore;
|
||||
|
||||
using UAParser;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
|
||||
using ThingsGateway.Core;
|
||||
using ThingsGateway.Core.Json.Extension;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
|
@@ -17,6 +17,7 @@ using SqlSugar;
|
||||
|
||||
using System.Security.Claims;
|
||||
|
||||
using ThingsGateway.ASPNetCore;
|
||||
using ThingsGateway.Core;
|
||||
|
||||
using Yitter.IdGenerator;
|
||||
|
@@ -1,6 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(SolutionDir)Version.props" />
|
||||
<Import Project="$(SolutionDir)PackNuget.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
<DocumentationFile>ThingsGateway.Admin.ASPNetCore.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
|
@@ -0,0 +1,324 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>ThingsGateway.Admin.ASPNetCore</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:ThingsGateway.Admin.Application.BlazorAuthenticationStateProvider">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.BlazorAuthenticationStateProvider.HandleAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.BlazorAuthenticationStateProvider.PipelineAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext,Microsoft.AspNetCore.Http.DefaultHttpContext)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.BlazorAuthenticationStateProvider.CheckVerificatFromCacheAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext)">
|
||||
<summary>
|
||||
检查 BearerToken/Cookie 有效性
|
||||
</summary>
|
||||
<param name="context">DefaultHttpContext</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Admin.Application.DatabaseLoggingWriter">
|
||||
<summary>
|
||||
数据库写入器
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Admin.Application.DatabaseLoggingWriter._operateLogMessageQueue">
|
||||
<summary>
|
||||
日志消息队列(线程安全)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.DatabaseLoggingWriter.WriteAsync(ThingsGateway.Logging.LogMessage,System.Boolean)">
|
||||
<summary>
|
||||
此方法只会写入经由MVCFilter捕捉的方法日志,对于BlazorServer的内部操作,由<see cref="T:ThingsGateway.Admin.Application.OperDescAttribute"/>执行
|
||||
</summary>
|
||||
<param name="logMsg"></param>
|
||||
<param name="flush"></param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.DatabaseLoggingWriter.CreateOperationLog(System.String,System.String,ThingsGateway.ASPNetCore.LoggingMonitorJson,UAParser.ClientInfo,System.Boolean)">
|
||||
<summary>
|
||||
创建操作日志
|
||||
</summary>
|
||||
<param name="operation">操作名称</param>
|
||||
<param name="path">请求地址</param>
|
||||
<param name="loggingMonitor">loggingMonitor</param>
|
||||
<param name="clientInfo">客户端信息</param>
|
||||
<param name="flush"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.DatabaseLoggingWriter.CreateVisitLog(System.String,System.String,ThingsGateway.ASPNetCore.LoggingMonitorJson,UAParser.ClientInfo,System.Boolean)">
|
||||
<summary>
|
||||
创建访问日志
|
||||
</summary>
|
||||
<param name="operation">访问类型</param>
|
||||
<param name="path"></param>
|
||||
<param name="loggingMonitor">loggingMonitor</param>
|
||||
<param name="clientInfo">客户端信息</param>
|
||||
<param name="flush"></param>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Admin.Application.CultureController">
|
||||
<summary>
|
||||
文化 Controller
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.CultureController.ResetCulture(System.String)">
|
||||
<summary>
|
||||
重置文化方法
|
||||
</summary>
|
||||
<param name="redirectUri"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.CultureController.SetCulture(System.String,System.String)">
|
||||
<summary>
|
||||
设置文化方法
|
||||
</summary>
|
||||
<param name="culture"></param>
|
||||
<param name="redirectUri"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Admin.Application.FileController">
|
||||
<summary>
|
||||
文件下载
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.FileController.Download(System.String)">
|
||||
<summary>
|
||||
下载wwwroot文件夹下的文件
|
||||
</summary>
|
||||
<param name="fileName">相对路径</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Admin.Application.OpenApiController">
|
||||
<summary>
|
||||
登录
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthRazorService.LoginAsync(ThingsGateway.Admin.Application.LoginInput)">
|
||||
<summary>
|
||||
用户登录
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthRazorService.LoginOutAsync">
|
||||
<summary>
|
||||
注销当前用户
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthService.LoginAsync(ThingsGateway.Admin.Application.LoginInput,System.Boolean)">
|
||||
<summary>
|
||||
登录
|
||||
</summary>
|
||||
<param name="input">登录参数</param>
|
||||
<param name="isCookie">cookie方式登录</param>
|
||||
<returns>登录输出</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthService.LoginOutAsync">
|
||||
<summary>
|
||||
注销当前用户
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthService.BeforeLogin(ThingsGateway.Admin.Application.AppConfig,System.String)">
|
||||
<summary>
|
||||
登录之前执行的方法
|
||||
</summary>
|
||||
<param name="appConfig">配置</param>
|
||||
<param name="userName">用户名称</param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthService.ExecLogin(ThingsGateway.Admin.Application.LoginPolicy,ThingsGateway.Admin.Application.LoginInput,ThingsGateway.Admin.Application.SysUser,System.Boolean)">
|
||||
<summary>
|
||||
执行登录
|
||||
</summary>
|
||||
<param name="loginPolicy">登录策略</param>
|
||||
<param name="input">用户登录参数</param>
|
||||
<param name="sysUser">用户信息</param>
|
||||
<param name="isCookie">cookie方式登录</param>
|
||||
<returns>登录输出结果</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthService.LoginError(ThingsGateway.Admin.Application.LoginPolicy,System.String)">
|
||||
<summary>
|
||||
登录错误反馈
|
||||
</summary>
|
||||
<param name="loginPolicy">登录策略</param>
|
||||
<param name="userName">用户名称</param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthService.RemoveTokenFromCache(ThingsGateway.Admin.Application.LoginEvent)">
|
||||
<summary>
|
||||
从cache删除用户verificat
|
||||
</summary>
|
||||
<param name="loginEvent">登录事件参数</param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthService.SingleLogin(System.Int64)">
|
||||
<summary>
|
||||
单用户登录通知用户下线
|
||||
</summary>
|
||||
<param name="userId">用户Id</param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthService.UpdateUser(ThingsGateway.Admin.Application.LoginEvent)">
|
||||
<summary>
|
||||
登录事件
|
||||
</summary>
|
||||
<param name="loginEvent"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.AuthService.WriteTokenToCache(ThingsGateway.Admin.Application.LoginPolicy,ThingsGateway.Admin.Application.LoginEvent)">
|
||||
<summary>
|
||||
写入用户verificat到cache
|
||||
</summary>
|
||||
<param name="loginPolicy">登录策略</param>
|
||||
<param name="loginEvent">登录事件参数</param>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Admin.Application.LoginEvent">
|
||||
<summary>
|
||||
登录事件参数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Admin.Application.LoginEvent.DateTime">
|
||||
<summary>
|
||||
时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Admin.Application.LoginEvent.Device">
|
||||
<summary>
|
||||
登录设备
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Admin.Application.LoginEvent.Expire">
|
||||
<summary>
|
||||
过期时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Admin.Application.LoginEvent.Ip">
|
||||
<summary>
|
||||
Ip地址
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Admin.Application.LoginEvent.SysUser">
|
||||
<summary>
|
||||
用户信息
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Admin.Application.LoginEvent.VerificatId">
|
||||
<summary>
|
||||
VerificatId
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.FileService.GetFileStreamResult(System.String,System.String,System.Boolean)">
|
||||
<summary>
|
||||
获取本地存储文件流
|
||||
</summary>
|
||||
<param name="path">文件夹</param>
|
||||
<param name="fileName">文件名称</param>
|
||||
<param name="isPathFolder">第一个参数是否是包含文件名称的全路径</param>
|
||||
<returns>文件流</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.FileService.GetFileStreamResult(System.Byte[],System.String)">
|
||||
<summary>
|
||||
按字节数组转为文件流
|
||||
</summary>
|
||||
<param name="byteArray">字节数组</param>
|
||||
<param name="fileName">文件名称</param>
|
||||
<returns>文件流</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.FileService.UploadFileAsync(Microsoft.AspNetCore.Components.Forms.IBrowserFile,System.String)">
|
||||
<summary>
|
||||
上传文件,保存在磁盘中
|
||||
</summary>
|
||||
<param name="pPath">保存路径</param>
|
||||
<param name="file">文件</param>
|
||||
<returns>最终全路径</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.FileService.Verification(Microsoft.AspNetCore.Components.Forms.IBrowserFile,System.Int32,System.String[])">
|
||||
<summary>
|
||||
验证文件信息
|
||||
</summary>
|
||||
<param name="file">文件</param>
|
||||
<param name="maxSize">最大文件大小</param>
|
||||
<param name="allowTypes">扩展名称匹配</param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.IFileService.GetFileStreamResult(System.String,System.String,System.Boolean)">
|
||||
<summary>
|
||||
获取本地存储文件流
|
||||
</summary>
|
||||
<param name="path">文件夹路径</param>
|
||||
<param name="fileName">文件名称</param>
|
||||
<param name="isPathFolder">路径是否包含文件名称</param>
|
||||
<returns>文件流</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.IFileService.GetFileStreamResult(System.Byte[],System.String)">
|
||||
<summary>
|
||||
按字节数组转为文件流
|
||||
</summary>
|
||||
<param name="byteArray">字节数组</param>
|
||||
<param name="fileName">文件名称</param>
|
||||
<returns>文件流</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.IFileService.UploadFileAsync(Microsoft.AspNetCore.Components.Forms.IBrowserFile,System.String)">
|
||||
<summary>
|
||||
上传文件,保存在磁盘中
|
||||
</summary>
|
||||
<param name="pPath">保存路径</param>
|
||||
<param name="file">文件流</param>
|
||||
<returns>最终全路径</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.IFileService.Verification(Microsoft.AspNetCore.Components.Forms.IBrowserFile,System.Int32,System.String[])">
|
||||
<summary>
|
||||
验证文件信息
|
||||
</summary>
|
||||
<param name="file">文件流</param>
|
||||
<param name="maxSize">最大文件大小(单位:MB)</param>
|
||||
<param name="allowTypes">允许上传的文件类型</param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.IImportExportService.ExportAsync``1(System.Object,System.String,System.Boolean)">
|
||||
<summary>
|
||||
导出excel文件流
|
||||
</summary>
|
||||
<typeparam name="T">实体</typeparam>
|
||||
<param name="input">实体对象或者IDataReader</param>
|
||||
<param name="fileName">文件名称</param>
|
||||
<param name="isDynamicExcelColumn">动态excel列,根据实体的<see cref="T:ThingsGateway.Core.IgnoreExcelAttribute"/>属性判断是否生成 </param>
|
||||
<returns>导出的文件流</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.IImportExportService.GetUrlEncodeFileName(System.String)">
|
||||
<summary>
|
||||
获取文件名,默认xlsx类型
|
||||
</summary>
|
||||
<param name="fileName">文件名称,不含类型名称的话默认xlsx</param>
|
||||
<returns>编码后的文件名</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.IImportExportService.UploadFileAsync(Microsoft.AspNetCore.Components.Forms.IBrowserFile)">
|
||||
<summary>
|
||||
上传文件
|
||||
</summary>
|
||||
<param name="file">文件</param>
|
||||
<returns>保存全路径</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.ImportExportService.ExportAsync``1(System.Object,System.String,System.Boolean)">
|
||||
<summary>
|
||||
导出excel文件流
|
||||
</summary>
|
||||
<typeparam name="T">实体</typeparam>
|
||||
<param name="input">实体对象或者IDataReader</param>
|
||||
<param name="fileName">文件名称</param>
|
||||
<param name="isDynamicExcelColumn">动态excel列,根据实体的<see cref="T:ThingsGateway.Core.IgnoreExcelAttribute"/>属性判断是否生成 </param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.ImportExportService.UploadFileAsync(Microsoft.AspNetCore.Components.Forms.IBrowserFile)">
|
||||
<summary>
|
||||
上传文件
|
||||
</summary>
|
||||
<param name="file">文件</param>
|
||||
<returns>保存全路径</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Admin.Application.ImportExportService.GetUrlEncodeFileName(System.String)">
|
||||
<summary>
|
||||
获取文件名,默认xlsx类型
|
||||
</summary>
|
||||
<param name="fileName">文件名称,不含类型名称的话默认xlsx</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ApiPermissionService.ApiPermissionTreeSelector">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
@@ -13,7 +13,10 @@ using ThingsGateway.Admin.Application;
|
||||
|
||||
public interface IApiPermissionService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// 获取API树
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<OpenApiPermissionTreeSelector> ApiPermissionTreeSelector();
|
||||
|
||||
}
|
||||
|
@@ -18,12 +18,26 @@ namespace ThingsGateway.Admin.Application;
|
||||
|
||||
public interface IAppService
|
||||
{
|
||||
/// <summary>
|
||||
/// ClientInfo
|
||||
/// </summary>
|
||||
public ClientInfo? ClientInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ClaimsPrincipal
|
||||
/// </summary>
|
||||
public ClaimsPrincipal? User { get; }
|
||||
|
||||
/// <summary>
|
||||
/// RemoteIpAddress
|
||||
/// </summary>
|
||||
public IPAddress? RemoteIpAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// GetReturnUrl
|
||||
/// </summary>
|
||||
/// <param name="returnUrl"></param>
|
||||
/// <returns></returns>
|
||||
public string GetReturnUrl(string returnUrl);
|
||||
|
||||
|
||||
|
@@ -9,6 +9,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.Core;
|
||||
|
||||
namespace ThingsGateway.Admin.NetCore;
|
||||
|
||||
|
@@ -41,32 +41,6 @@
|
||||
|
||||
|
||||
|
||||
"ThingsGateway.Admin.Razor.MainLayout": {
|
||||
"About": "About",
|
||||
"FullScreenButton": "Full Screen",
|
||||
"UserCenter": "User Center",
|
||||
"ChoiceModule": "Switch Module",
|
||||
"GiteePostTitleText": "Code Commit Push Notification",
|
||||
|
||||
"LoginErrorh1": "Login Error",
|
||||
"LoginSuccessh1": "Login Success",
|
||||
"LoginSuccessc1": "Redirecting to the page",
|
||||
"LoginErrorh2": "Login Failed",
|
||||
"LoginErrorc2": "Please contact the administrator!",
|
||||
"Logout": "Logout",
|
||||
|
||||
"系统首页": "Home",
|
||||
"权限管理": "Permission",
|
||||
"用户管理": "User",
|
||||
"角色管理": "Role",
|
||||
"菜单管理": "Menu",
|
||||
"系统运维": "SystemOperation",
|
||||
"系统配置": "System",
|
||||
"字典管理": "Dictionary",
|
||||
"操作日志": "Operation",
|
||||
"会话管理": "Session",
|
||||
"硬件信息": "HardwareInfo"
|
||||
},
|
||||
"ThingsGateway.Admin.Razor.OperLogPage": {
|
||||
"Date": "Date",
|
||||
"Count": "Count",
|
||||
|
@@ -42,32 +42,6 @@
|
||||
},
|
||||
|
||||
|
||||
"ThingsGateway.Admin.Razor.MainLayout": {
|
||||
"About": "关于",
|
||||
"FullScreenButton": "全屏",
|
||||
"UserCenter": "个人中心",
|
||||
"ChoiceModule": "切换模块",
|
||||
"GiteePostTitleText": "代码提交推送通知",
|
||||
|
||||
"LoginErrorh1": "登录异常",
|
||||
"LoginSuccessh1": "登录成功",
|
||||
"LoginSuccessc1": "即将跳转页面",
|
||||
"LoginErrorh2": "登录失败",
|
||||
"LoginErrorc2": "请联系管理员!",
|
||||
"Logout": "注销",
|
||||
|
||||
"系统首页": "系统首页",
|
||||
"权限管理": "权限管理",
|
||||
"用户管理": "用户管理",
|
||||
"角色管理": "角色管理",
|
||||
"菜单管理": "菜单管理",
|
||||
"系统运维": "系统运维",
|
||||
"系统配置": "系统配置",
|
||||
"字典管理": "字典管理",
|
||||
"操作日志": "操作日志",
|
||||
"会话管理": "会话管理",
|
||||
"硬件信息": "硬件信息"
|
||||
},
|
||||
"ThingsGateway.Admin.Razor.OperLogPage": {
|
||||
"Date": "日期",
|
||||
"Count": "数量",
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(SolutionDir)\tools\ThingsGateway.Razor\ThingsGateway.Razor.csproj" />
|
||||
<ProjectReference Include="$(SolutionDir)\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj" />
|
||||
<PackageReference Include="BootstrapBlazor.Chart" Version="8.1.9" />
|
||||
<PackageReference Include="BootstrapBlazor.Chart" Version="8.2.0" />
|
||||
<PackageReference Include="BootstrapBlazor.TableExport" Version="8.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@@ -11,6 +11,8 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.Core;
|
||||
|
||||
@@ -19,13 +21,14 @@ namespace ThingsGateway.Gateway.Application;
|
||||
/// <summary>
|
||||
/// 采集设备
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings("ThingsGateway.OpenApi", Order = 200)]
|
||||
[DisplayName("获取配置信息")]
|
||||
[Route("openApi/configInfo")]
|
||||
[RolePermission]
|
||||
[LoggingMonitor]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
public class ConfigInfoControler : ControllerBase
|
||||
{
|
||||
/// <inheritdoc cref="ConfigInfoControler"/>
|
||||
public ConfigInfoControler(
|
||||
IChannelService channelService,
|
||||
IVariableService variableService,
|
||||
@@ -45,6 +48,7 @@ public class ConfigInfoControler : ControllerBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("channelList")]
|
||||
[DisplayName("获取通道信息")]
|
||||
public Task<SqlSugarPagedList<Channel>> GetChannelList([FromQuery] ChannelPageInput input)
|
||||
{
|
||||
return _channelService.PageAsync(input);
|
||||
@@ -55,6 +59,7 @@ public class ConfigInfoControler : ControllerBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("deviceList")]
|
||||
[DisplayName("获取设备信息")]
|
||||
public Task<SqlSugarPagedList<Device>> GetCollectDeviceList([FromQuery] DevicePageInput input)
|
||||
{
|
||||
return _collectDeviceService.PageAsync(input);
|
||||
@@ -65,6 +70,7 @@ public class ConfigInfoControler : ControllerBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("variableList")]
|
||||
[DisplayName("获取变量信息")]
|
||||
public Task<SqlSugarPagedList<Variable>> GetVariableList([FromQuery] VariablePageInput input)
|
||||
{
|
||||
return _variableService.PageAsync(input);
|
||||
|
@@ -11,7 +11,10 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.ASPNetCore;
|
||||
using ThingsGateway.Foundation;
|
||||
|
||||
namespace ThingsGateway.Gateway.Application;
|
||||
@@ -19,13 +22,13 @@ namespace ThingsGateway.Gateway.Application;
|
||||
/// <summary>
|
||||
/// 设备控制
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings("ThingsGateway.OpenApi", Order = 200)]
|
||||
[Route("openApi/control")]
|
||||
[RolePermission]
|
||||
[LoggingMonitor]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
public class ControlControler : ControllerBase
|
||||
{
|
||||
/// <inheritdoc cref="ControlControler"/>
|
||||
public ControlControler(IRpcService rpcService)
|
||||
{
|
||||
_rpcService = rpcService;
|
||||
@@ -38,6 +41,7 @@ public class ControlControler : ControllerBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("pasueBusinessThread")]
|
||||
[DisplayName("控制业务线程启停")]
|
||||
public void PasueBusinessThread(long id, bool isStart)
|
||||
{
|
||||
HostedServiceUtil.BusinessDeviceHostedService.PasueThread(id, isStart);
|
||||
@@ -48,6 +52,7 @@ public class ControlControler : ControllerBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("pasueCollectThread")]
|
||||
[DisplayName("控制采集线程启停")]
|
||||
public void PasueCollectThread(long id, bool isStart)
|
||||
{
|
||||
HostedServiceUtil.CollectDeviceHostedService.PasueThread(id, isStart);
|
||||
@@ -58,6 +63,7 @@ public class ControlControler : ControllerBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("restartBusinessThread")]
|
||||
[DisplayName("重启业务线程")]
|
||||
public async Task RestartBusinessDeviceThread(long id)
|
||||
{
|
||||
if (id <= 0)
|
||||
@@ -75,6 +81,7 @@ public class ControlControler : ControllerBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("restartCollectThread")]
|
||||
[DisplayName("重启采集线程")]
|
||||
public async Task RestartCollectDeviceThread(long id)
|
||||
{
|
||||
if (id <= 0)
|
||||
@@ -91,6 +98,7 @@ public class ControlControler : ControllerBase
|
||||
/// 写入多个变量
|
||||
/// </summary>
|
||||
[HttpPost("writeVariables")]
|
||||
[DisplayName("写入变量")]
|
||||
public async Task<Dictionary<string, OperResult>> WriteDeviceMethods(Dictionary<string, string> objs)
|
||||
{
|
||||
var result = await _rpcService.InvokeDeviceMethodAsync($"WebApi-{UserManager.UserAccount}-{App.HttpContext.Connection.RemoteIpAddress.MapToIPv4()}", objs);
|
||||
|
@@ -19,6 +19,7 @@ namespace ThingsGateway.Gateway.Application;
|
||||
/// <summary>
|
||||
/// 导出文件
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(false)]
|
||||
[Route("api/gatewayExport")]
|
||||
[LoggingMonitor]
|
||||
public class GatewayExportController : ControllerBase
|
||||
@@ -31,9 +32,6 @@ public class GatewayExportController : ControllerBase
|
||||
private readonly IImportExportService _importExportService;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="GatewayExportController"/>
|
||||
/// </summary>
|
||||
public GatewayExportController(
|
||||
IChannelService channelService,
|
||||
IDeviceService deviceService,
|
||||
|
@@ -15,6 +15,8 @@ using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
using SqlSugar;
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.Core;
|
||||
using ThingsGateway.NewLife.X.Extension;
|
||||
@@ -23,6 +25,8 @@ namespace ThingsGateway.Gateway.Application;
|
||||
/// <summary>
|
||||
/// 采集状态信息
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings("ThingsGateway.OpenApi", Order = 200)]
|
||||
[DisplayName("数据状态")]
|
||||
[Route("openApi/runtimeInfo")]
|
||||
[RolePermission]
|
||||
[LoggingMonitor]
|
||||
@@ -34,6 +38,7 @@ public class RuntimeInfoControler : ControllerBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("deviceList")]
|
||||
[DisplayName("获取设备信息")]
|
||||
public SqlSugarPagedList<DeviceData> GetCollectDeviceList([FromQuery] DevicePageInput input)
|
||||
{
|
||||
var data = GlobalData.ReadOnlyCollectDevices.Select(a => a.Value)
|
||||
@@ -50,6 +55,7 @@ public class RuntimeInfoControler : ControllerBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("realAlarmList")]
|
||||
[DisplayName("获取实时报警信息")]
|
||||
public SqlSugarPagedList<VariableData> GetRealAlarmList([FromQuery] VariablePageInput input)
|
||||
{
|
||||
var data = GlobalData.ReadOnlyRealAlarmVariables
|
||||
@@ -64,6 +70,7 @@ public class RuntimeInfoControler : ControllerBase
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("variableList")]
|
||||
[DisplayName("获取变量信息")]
|
||||
public SqlSugarPagedList<VariableData> GetVariableList([FromQuery] VariablePageInput input)
|
||||
{
|
||||
var data = GlobalData.ReadOnlyVariables.Select(a => a.Value)
|
||||
|
@@ -1,12 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(SolutionDir)Version.props" />
|
||||
<Import Project="$(SolutionDir)PackNuget.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(SolutionDir)\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
|
||||
<ProjectReference Include="$(SolutionDir)\ThingsGateway.Admin.ASPNetCore\ThingsGateway.Admin.ASPNetCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
@@ -27,46 +27,6 @@
|
||||
"WriteVariable": "Write",
|
||||
"WriteValue": "Value"
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.MainLayout": {
|
||||
"About": "About",
|
||||
"FullScreenButton": "Full Screen",
|
||||
"UserCenter": "User Center",
|
||||
"ChoiceModule": "Switch Module",
|
||||
"GiteePostTitleText": "Code Commit Push Notification",
|
||||
|
||||
"LoginErrorh1": "Login Error",
|
||||
"LoginSuccessh1": "Login Success",
|
||||
"LoginSuccessc1": "Redirecting to the page",
|
||||
"LoginErrorh2": "Login Failed",
|
||||
"LoginErrorc2": "Please contact the administrator!",
|
||||
"Logout": "Logout",
|
||||
|
||||
"系统首页": "Home",
|
||||
"权限管理": "Permission",
|
||||
"用户管理": "User",
|
||||
"角色管理": "Role",
|
||||
"菜单管理": "Menu",
|
||||
"系统运维": "SystemOperation",
|
||||
"系统配置": "System",
|
||||
"字典管理": "Dictionary",
|
||||
"操作日志": "Operation",
|
||||
"会话管理": "Session",
|
||||
"硬件信息": "HardwareInfo",
|
||||
"网关管理": "GatewayManagement",
|
||||
"插件管理": "PluginManagement",
|
||||
"插件调试": "PluginDebugging",
|
||||
"通道管理": "Channel",
|
||||
"采集设备": "CollectionDevices",
|
||||
"业务设备": "BusinessDevices",
|
||||
"变量管理": "Variable",
|
||||
"网关状态": "GatewayStatus",
|
||||
"设备状态": "Device",
|
||||
"实时数据": "RealTimeData",
|
||||
"实时报警": "RealTimeAlarms",
|
||||
"网关日志": "GatewayLogs",
|
||||
"后台日志": "Backend",
|
||||
"RPC日志": "RPC"
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.DriverDebugPage": {
|
||||
"PluginUINotNull": "This plugin does not implement a debug page",
|
||||
"New": "New"
|
||||
|
@@ -25,46 +25,6 @@
|
||||
"WriteVariable": "写入",
|
||||
"WriteValue": "写入值"
|
||||
},
|
||||
"ThingsGateway.Gateway.Razor.MainLayout": {
|
||||
"About": "关于",
|
||||
"FullScreenButton": "全屏",
|
||||
"UserCenter": "个人中心",
|
||||
"ChoiceModule": "切换模块",
|
||||
"GiteePostTitleText": "代码提交推送通知",
|
||||
|
||||
"LoginErrorh1": "登录异常",
|
||||
"LoginSuccessh1": "登录成功",
|
||||
"LoginSuccessc1": "即将跳转页面",
|
||||
"LoginErrorh2": "登录失败",
|
||||
"LoginErrorc2": "请联系管理员!",
|
||||
"Logout": "注销",
|
||||
|
||||
"系统首页": "系统首页",
|
||||
"权限管理": "权限管理",
|
||||
"用户管理": "用户管理",
|
||||
"角色管理": "角色管理",
|
||||
"菜单管理": "菜单管理",
|
||||
"系统运维": "系统运维",
|
||||
"系统配置": "系统配置",
|
||||
"字典管理": "字典管理",
|
||||
"操作日志": "操作日志",
|
||||
"会话管理": "会话管理",
|
||||
"硬件信息": "硬件信息",
|
||||
"网关管理": "网关管理",
|
||||
"插件管理": "插件管理",
|
||||
"插件调试": "插件调试",
|
||||
"通道管理": "通道管理",
|
||||
"采集设备": "采集设备",
|
||||
"业务设备": "业务设备",
|
||||
"变量管理": "变量管理",
|
||||
"网关状态": "网关状态",
|
||||
"设备状态": "设备状态",
|
||||
"实时数据": "实时数据",
|
||||
"实时报警": "实时报警",
|
||||
"网关日志": "网关日志",
|
||||
"后台日志": "后台日志",
|
||||
"RPC日志": "RPC日志"
|
||||
},
|
||||
|
||||
"ThingsGateway.Gateway.Razor.DriverDebugPage": {
|
||||
"PluginUINotNull": "此插件未实现调试页面",
|
||||
|
@@ -1,88 +0,0 @@
|
||||
@inherits LayoutComponentBase
|
||||
@layout BaseLayout
|
||||
@namespace ThingsGateway.Gateway.Razor
|
||||
@using ThingsGateway.Admin.Application
|
||||
@using ThingsGateway.Admin.Razor
|
||||
@using ThingsGateway.Core.Extension
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<SysSignalR />
|
||||
<CascadingValue Value="ReloadMenu" Name="ReloadMenu" IsFixed="true">
|
||||
<CascadingValue Value="ReloadUser" Name="ReloadUser" IsFixed="true">
|
||||
|
||||
<div class="mainlayout">
|
||||
|
||||
<Layout SideWidth="0" IsPage="true" IsFullSide="true" IsFixedHeader="true"
|
||||
ShowGotoTop="true" ShowCollapseBar="true" Menus="@MenuService.MenuItems"
|
||||
AdditionalAssemblies=NetCoreApp.RazorAssemblies AllowDragTab=true
|
||||
UseTabSet="false" TabDefaultUrl="/">
|
||||
<Header>
|
||||
<div class="flex-fill"></div>
|
||||
|
||||
@* 搜索框 *@
|
||||
<GlobalSearch Menus=@(MenuService.SameLevelMenuItems) />
|
||||
|
||||
@* 语言选择 *@
|
||||
<div class="d-none d-xl-flex ">
|
||||
<CultureChooser />
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<Logout ImageUrl="@(AppContext.CurrentUser.Avatar??$"{WebsiteConst.DefaultResourceUrl}images/defaultUser.svg")" ShowUserName=false DisplayName="@UserManager.UserAccount" UserName="@UserManager.UserAccount">
|
||||
<LinkTemplate>
|
||||
@* 切换模块 *@
|
||||
<a @onclick="ChoiceModule"><i class="fas fa-arrow-right-arrow-left me-2" />@Localizer["ChoiceModule"]</a>
|
||||
<a @onclick="@OnUserInfoDialog"><i class="fa-solid fa-suitcase me-2"></i>@Localizer["UserCenter"]</a>
|
||||
<a @onclick="@LogoutAsync"><i class="fa-solid fa-key me-2"></i>@Localizer["Logout"]</a>
|
||||
|
||||
</LinkTemplate>
|
||||
</Logout>
|
||||
|
||||
@* 全屏按钮 *@
|
||||
<FullScreenButton class="layout-header-bar d-none d-lg-flex px-2" Icon="fa fa-arrows-alt"
|
||||
TooltipPlacement=Placement.Bottom TooltipText="@Localizer[nameof(FullScreenButton)]" />
|
||||
@if (WebsiteOption.Value.IsShowAbout)
|
||||
{
|
||||
<Button @onclick="ShowAbout" class="layout-header-bar d-none d-lg-flex px-2" Icon="fa fa-info" Color="Color.None" TooltipText="@Localizer[nameof(About)]" />
|
||||
}
|
||||
@* 版本号 *@
|
||||
<div class="px-1 navbar-header-text d-none d-lg-block">@_versionString</div>
|
||||
|
||||
@* 主题切换 *@
|
||||
@* <ThemeToggle /> *@
|
||||
<ThemeProvider class="layout-header-bar d-none d-lg-flex px-0"></ThemeProvider>
|
||||
|
||||
</Header>
|
||||
<Side>
|
||||
<div class="layout-banner">
|
||||
<span class="avatar">
|
||||
@WebsiteOption.Value.Title?.GetNameLen2()
|
||||
</span>
|
||||
|
||||
<div class="layout-title d-flex align-items-center justify-content-center">
|
||||
<span>@WebsiteOption.Value.Title</span>
|
||||
</div>
|
||||
</div>
|
||||
</Side>
|
||||
<Main>
|
||||
<Tab ClickTabToNavigation="true" ShowExtendButtons="true" ShowClose="true" AllowDrag=true
|
||||
AdditionalAssemblies="@NetCoreApp.RazorAssemblies" Menus="@MenuService.MenuItems"
|
||||
DefaultUrl=@("/") Body=@(Body!)>
|
||||
</Tab>
|
||||
|
||||
</Main>
|
||||
<NotAuthorized>
|
||||
<Redirect Url="/Account/Login" />
|
||||
</NotAuthorized>
|
||||
</Layout>
|
||||
|
||||
@if (AppContext.IsHasButtonWithRole(string.Empty, "快捷按钮"))
|
||||
{
|
||||
<QuickActions></QuickActions>
|
||||
}
|
||||
</div>
|
||||
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
|
@@ -1,252 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://kimdiego2098.github.io/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using SqlSugar;
|
||||
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.Admin.Razor;
|
||||
using ThingsGateway.Core;
|
||||
using ThingsGateway.Razor;
|
||||
|
||||
namespace ThingsGateway.Gateway.Razor;
|
||||
|
||||
public partial class MainLayout : IDisposable
|
||||
{
|
||||
#region 全局通知
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IDispatchService<MessageItem>? DispatchService { get; set; }
|
||||
|
||||
private async Task Dispatch(DispatchEntry<MessageItem> entry)
|
||||
{
|
||||
if (entry.Entry != null)
|
||||
{
|
||||
await ToastService.Show(new ToastOption()
|
||||
{
|
||||
Title = $"{entry.Entry.Title} ",
|
||||
Content = $"{entry.Entry.Message}",
|
||||
Category = ToastCategory.Information,
|
||||
Delay = 10 * 1000,
|
||||
ForceDelay = true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#endregion 全局通知
|
||||
|
||||
#region Gitee通知
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IDispatchService<GiteePostBody>? CommitDispatchService { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private string? GiteePostTitleText { get; set; }
|
||||
|
||||
private async Task NotifyCommit(DispatchEntry<GiteePostBody> payload)
|
||||
{
|
||||
if (payload.CanDispatch())
|
||||
{
|
||||
var option = new ToastOption()
|
||||
{
|
||||
Category = ToastCategory.Information,
|
||||
Title = GiteePostTitleText,
|
||||
Delay = 10 * 1000,
|
||||
ForceDelay = true,
|
||||
ChildContent = BootstrapDynamicComponent.CreateComponent<CommitItem>(new Dictionary<string, object?>
|
||||
{
|
||||
[nameof(CommitItem.Item)] = payload.Entry
|
||||
}).Render()
|
||||
};
|
||||
await ToastService.Show(option);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Gitee通知
|
||||
|
||||
#region 切换模块
|
||||
|
||||
[Inject]
|
||||
private ISysResourceService SysResourceService { get; set; }
|
||||
|
||||
[Inject]
|
||||
private IUserCenterService UserCenterService { get; set; }
|
||||
|
||||
private async Task ChoiceModule()
|
||||
{
|
||||
DialogOption? op = null;
|
||||
|
||||
op = new DialogOption()
|
||||
{
|
||||
IsScrolling = true,
|
||||
Size = Size.ExtraLarge,
|
||||
ShowFooter = false,
|
||||
Title = Localizer["ChoiceModule"],
|
||||
BodyTemplate = BootstrapDynamicComponent.CreateComponent<ChoiceModuleComponent>(new Dictionary<string, object?>
|
||||
{
|
||||
[nameof(ChoiceModuleComponent.ModuleList)] = AppContext.CurrentUser.ModuleList.ToList(),
|
||||
[nameof(ChoiceModuleComponent.Value)] = AppContext.CurrentUser.DefaultModule,
|
||||
[nameof(ChoiceModuleComponent.OnSave)] = new Func<long, Task>(async v =>
|
||||
{
|
||||
if (op != null)
|
||||
{
|
||||
await op.CloseDialogAsync();
|
||||
}
|
||||
await UserCenterService.SetDefaultModule(v);
|
||||
NavigationManager.NavigateTo("/", true);
|
||||
})
|
||||
}).Render(),
|
||||
};
|
||||
await DialogService.Show(op);
|
||||
}
|
||||
|
||||
#endregion 切换模块
|
||||
|
||||
#region 注销
|
||||
|
||||
[Inject]
|
||||
private AjaxService AjaxService { get; set; }
|
||||
|
||||
[Inject]
|
||||
private IAppService AppService { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IAuthRazorService? AuthRazorService { get; set; }
|
||||
|
||||
private async Task LogoutAsync()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
var ret = await AuthRazorService.LoginOutAsync();
|
||||
if (ret.Code != 200)
|
||||
{
|
||||
await ToastService.Error(Localizer["LoginErrorh1"], $"{ret.Msg}");
|
||||
}
|
||||
else
|
||||
{
|
||||
await ToastService.Information(Localizer["LoginSuccessh1"], Localizer["LoginSuccessc1"]);
|
||||
await Task.Delay(1000);
|
||||
var url = AppService.GetReturnUrl(NavigationManager.ToBaseRelativePath(NavigationManager.Uri));
|
||||
await AjaxService.Goto(url);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
await ToastService.Error(Localizer["LoginErrorh2"], Localizer["LoginErrorc2"]);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion 注销
|
||||
|
||||
private string _versionString = string.Empty;
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private BlazorAppContext? AppContext { get; set; }
|
||||
|
||||
[Inject]
|
||||
private DialogService DialogService { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private FullScreenService FullScreenService { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IStringLocalizer<MainLayout>? Localizer { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IMenuService? MenuService { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private ToastService? ToastService { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IAppVersionService? VersionService { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IOptions<WebsiteOptions>? WebsiteOption { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
GiteePostTitleText = Localizer[nameof(GiteePostTitleText)];
|
||||
_versionString = $"v{VersionService.Version}";
|
||||
DispatchService.Subscribe(Dispatch);
|
||||
CommitDispatchService.Subscribe(NotifyCommit);
|
||||
await AppContext.InitUserAsync();
|
||||
await AppContext.InitMenus(NavigationManager.ToBaseRelativePath(NavigationManager.Uri));
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
DispatchService.UnSubscribe(Dispatch);
|
||||
CommitDispatchService.UnSubscribe(NotifyCommit);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReloadMenu()
|
||||
{
|
||||
await AppContext.InitMenus(NavigationManager.ToBaseRelativePath(NavigationManager.Uri));
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task ReloadUser()
|
||||
{
|
||||
await AppContext.InitUserAsync();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task ShowAbout()
|
||||
{
|
||||
DialogOption? op = null;
|
||||
|
||||
op = new DialogOption()
|
||||
{
|
||||
IsScrolling = true,
|
||||
Size = Size.Medium,
|
||||
ShowFooter = false,
|
||||
Title = Localizer["About"],
|
||||
BodyTemplate = BootstrapDynamicComponent.CreateComponent<About>().Render(),
|
||||
};
|
||||
await DialogService.Show(op);
|
||||
}
|
||||
|
||||
#region 个人信息修改
|
||||
|
||||
private Task OnUserInfoDialog() => DialogService.Show(new DialogOption()
|
||||
{
|
||||
Title = Localizer["UserCenter"],
|
||||
ShowFooter = false,
|
||||
Component = BootstrapDynamicComponent.CreateComponent<UserCenterPage>(new Dictionary<string, object?>()
|
||||
{
|
||||
})
|
||||
});
|
||||
|
||||
#endregion 个人信息修改
|
||||
}
|
@@ -1,138 +0,0 @@
|
||||
::deep .avatar {
|
||||
border-radius: 1.5rem;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background-color: var(--bs-green);
|
||||
color: #fff;
|
||||
flex: 0 0 auto;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .menu-icon {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .layout-main > .tabs > .tabs-body {
|
||||
background-color: var(--tabs-body-bg);
|
||||
}
|
||||
|
||||
.mainlayout ::deep .layout-main > .tabs > .tabs-body > .tabs-body-content {
|
||||
height: var(--bb-layout-body-height);
|
||||
background-color: var(--bs-body-bg);
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs {
|
||||
--bb-tabs-item-height: 32px;
|
||||
--bb-tabs-body-padding: 0.5rem;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs.tabs-border-card {
|
||||
box-shadow: 0 0px 0px 0 rgba(0,0,0,0),0 0 6px 0 rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs .extend .nav-link-bar.left {
|
||||
border-width: 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs-nav-wrap > .nav-link-bar.dropdown {
|
||||
border-width: 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs .extend .nav-link-bar.right {
|
||||
border-width: 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs .tabs-item-fix {
|
||||
border-width: 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs.tabs-card > .tabs-header .tabs-item {
|
||||
border-width: 0px 0px 0px 0px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs.tabs-border-card > .tabs-header .tabs-item {
|
||||
border-width: 0px 0px 0px 0px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs.tabs-card .tabs-header .tabs-item.active {
|
||||
border-width: 0px 0px 1px 0px;
|
||||
border-style: solid;
|
||||
border-color: var(--bb-tabs-item-active-color);
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs.tabs-border-card .tabs-header .tabs-item.active {
|
||||
border-width: 0px 0px 1px 0px;
|
||||
border-style: solid;
|
||||
border-color: var(--bb-tabs-item-active-color);
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs.tabs-card .tabs-header .tabs-item.active {
|
||||
background-color: var(--bs-primary-bg1);
|
||||
}
|
||||
|
||||
.mainlayout ::deep.tabs.tabs-card .tabs-header .tabs-item:hover {
|
||||
background-color: var(--bs-primary-bg1);
|
||||
}
|
||||
|
||||
.mainlayout ::deep.tabs.tabs-border-card .tabs-header .tabs-item:hover {
|
||||
background-color: var(--bs-primary-bg1);
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs-nav-wrap .nav-link-bar {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .tabs-item .tabs-item-close {
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .table-wrapper {
|
||||
border-radius: unset;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .layout-side {
|
||||
box-shadow: inset -1px 0 0px 0px var(--bs-border-color); /* 下内阴影 */
|
||||
}
|
||||
|
||||
.mainlayout ::deep .layout-banner {
|
||||
box-shadow: inset -1px 0 0px 0px var(--bs-border-color); /* 下内阴影 */
|
||||
}
|
||||
|
||||
.mainlayout ::deep .layout {
|
||||
--bb-layout-header-height: 44px;
|
||||
--bb-layout-headerbar-background: transparent;
|
||||
--bs-navbar-color: var(--bb-layout-header-color);
|
||||
--bs-navbar-hover-color: var(--bs-primary);
|
||||
--bb-layout-header-background: var(--tg-nav-bg);
|
||||
--bb-layout-sidebar-background: var(--tg-nav-bg);
|
||||
--bb-layout-footer-background: var(--tg-nav-bg);
|
||||
--bb-layout-sidebar-banner-background: var(--tg-nav-bg);
|
||||
--bb-layout-banner-font-size: 1.2rem;
|
||||
--bb-layout-banner-logo-width: 36px;
|
||||
--bb-layout-banner-logo-height: 36px;
|
||||
--line-chart-height: 350px;
|
||||
--bb-layout-body-height: calc(100vh - var(--bs-header-height) - var(--bb-layout-header-height) - 20px);
|
||||
--line-chart-table-height: calc(100vh - var(--bs-header-height) - var(--bb-layout-header-height) - var(--line-chart-height) - 30px);
|
||||
--table-height: calc(100vh - var(--bs-header-height) - var(--bb-layout-header-height) - 30px);
|
||||
--bs-header-height: 30px;
|
||||
}
|
||||
|
||||
.mainlayout ::deep .dropdown-logout {
|
||||
--bb-logout-avatar-width: 32px;
|
||||
--bb-logout-avatar-height: 32px;
|
||||
--bb-logout-user-bg: rgba(52,58,64,0.7);
|
||||
--bb-logout-menu-border-color: var(--bs-border-color);
|
||||
}
|
||||
|
||||
.mainlayout ::deep .layout-header-bar {
|
||||
border-color: transparent;
|
||||
border: 0px;
|
||||
color: var(--bb-layout-header-color);
|
||||
}
|
||||
|
||||
.mainlayout ::deep .layout-header-bar:hover {
|
||||
color: var(--bs-navbar-hover-color);
|
||||
}
|
@@ -63,9 +63,9 @@ internal class Program
|
||||
app.MainWindow.GrantBrowserPermissions = true;
|
||||
app.MainWindow.SetUseOsDefaultLocation(false);
|
||||
app.MainWindow.SetUseOsDefaultSize(false);
|
||||
app.MainWindow.SetSize(new System.Drawing.Size(1600, 900));
|
||||
app.MainWindow.SetSize(new System.Drawing.Size(1920, 1080));
|
||||
app.MainWindow.SetTitle("ThingsGateway");
|
||||
app.MainWindow.SetIconFile("wwwroot/favicon.ico");
|
||||
app.MainWindow.SetIconFile("favicon.ico");
|
||||
AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
|
||||
{
|
||||
};
|
||||
|
@@ -5,17 +5,8 @@
|
||||
<CascadingAuthenticationState>
|
||||
<Router AppAssembly="@typeof(Routes).Assembly" AdditionalAssemblies="NetCoreApp.RazorAssemblies.Where(a=>a!=typeof(Routes).Assembly)">
|
||||
<Found Context="routeData">
|
||||
@{
|
||||
#if Admin
|
||||
}
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Admin.Razor.MainLayout)" />
|
||||
@{
|
||||
#else
|
||||
}
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Gateway.Razor.MainLayout)" />
|
||||
@{
|
||||
#endif
|
||||
}
|
||||
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Razor.MainLayout)" />
|
||||
|
||||
</Found>
|
||||
<NotFound>
|
||||
|
@@ -43,12 +43,7 @@ public class Startup : AppStartup
|
||||
var userCenterService = a.GetService<IUserCenterService>();
|
||||
var userService = a.GetService<ISysUserService>();
|
||||
var appContext = new BlazorAppContext(sysResourceService, userCenterService, userService);
|
||||
#if Admin
|
||||
appContext.TitleLocalizer = a.GetRequiredService<IStringLocalizer<ThingsGateway.Admin.Razor.MainLayout>>();
|
||||
#else
|
||||
appContext.TitleLocalizer = a.GetRequiredService<IStringLocalizer<ThingsGateway.Gateway.Razor.MainLayout>>();
|
||||
#endif
|
||||
|
||||
appContext.TitleLocalizer = a.GetRequiredService<IStringLocalizer<ThingsGateway.Razor.MainLayout>>();
|
||||
return appContext;
|
||||
});
|
||||
services.AddAuthorizationCore();
|
||||
|
@@ -59,7 +59,11 @@
|
||||
<Content Include="..\ThingsGateway.Server\Index\GatewayIndex.razor" Link="Index\GatewayIndex.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\Index\AdminIndex.razor.cs" Link="Index\AdminIndex.razor.cs" />
|
||||
<Compile Include="..\ThingsGateway.Server\Index\GatewayIndex.razor.cs" Link="Index\GatewayIndex.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\MainLayout.razor" Link="MainLayout.razor" />
|
||||
<Compile Include="..\ThingsGateway.Server\MainLayout.razor.cs" Link="MainLayout.razor.cs" />
|
||||
<Content Include="..\ThingsGateway.Server\MainLayout.razor.css" Link="MainLayout.razor.css" />
|
||||
<Content Include="..\ThingsGateway.Server\Index\GatewayIndexComponent.razor" Link="Index\GatewayIndexComponent.razor" />
|
||||
|
||||
<Compile Include="..\ThingsGateway.Server\Index\GatewayIndexComponent.razor.cs" Link="Index\GatewayIndexComponent.razor.cs" />
|
||||
<None Include="..\ThingsGateway.Server\Index\AdminIndex.razor.css" Link="Index\AdminIndex.razor.css" />
|
||||
<None Include="..\ThingsGateway.Server\Index\GatewayIndex.razor.css" Link="Index\GatewayIndex.razor.css" />
|
||||
@@ -72,7 +76,7 @@
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="wwwroot\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
@@ -84,6 +88,11 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="favicon.ico" />
|
||||
<Content Include="favicon.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
<None Update="pm2-windows.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
@@ -1,127 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://kimdiego2098.github.io/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
|
||||
namespace ThingsGateway.Server;
|
||||
|
||||
/// <summary>
|
||||
/// 安全定义需求子项
|
||||
/// </summary>
|
||||
public sealed class SpecificationOpenApiSecurityRequirementItem
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public SpecificationOpenApiSecurityRequirementItem()
|
||||
{
|
||||
Accesses = System.Array.Empty<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 权限
|
||||
/// </summary>
|
||||
public string[] Accesses { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 安全Schema
|
||||
/// </summary>
|
||||
public OpenApiSecurityScheme Scheme { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 规范化文档安全配置
|
||||
/// </summary>
|
||||
public sealed class SpecificationOpenApiSecurityScheme : OpenApiSecurityScheme
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public SpecificationOpenApiSecurityScheme()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 唯一Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 安全需求
|
||||
/// </summary>
|
||||
public SpecificationOpenApiSecurityRequirementItem Requirement { get; set; }
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal static class SwaggerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 配置JWT授权
|
||||
/// </summary>
|
||||
/// <param name="swaggerGenOptions">Swagger 生成器配置</param>
|
||||
internal static void ConfigureSecurities(this SwaggerGenOptions swaggerGenOptions)
|
||||
{
|
||||
var openApiSecurityRequirement = new OpenApiSecurityRequirement();
|
||||
var SecurityDefinitions = new SpecificationOpenApiSecurityScheme[]
|
||||
{
|
||||
new SpecificationOpenApiSecurityScheme
|
||||
{
|
||||
Id="Bearer",
|
||||
Type= SecuritySchemeType.Http,
|
||||
Name="Authorization",
|
||||
Description="JWT Authorization header using the Bearer scheme.",
|
||||
BearerFormat="JWT",
|
||||
Scheme="bearer",
|
||||
In= ParameterLocation.Header,
|
||||
Requirement=new SpecificationOpenApiSecurityRequirementItem
|
||||
{
|
||||
Scheme=new OpenApiSecurityScheme
|
||||
{
|
||||
Reference=new OpenApiReference
|
||||
{
|
||||
Id="Bearer",
|
||||
Type= ReferenceType.SecurityScheme
|
||||
}
|
||||
},
|
||||
Accesses=Array.Empty<string>()
|
||||
}
|
||||
}
|
||||
};
|
||||
// 生成安全定义
|
||||
foreach (var securityDefinition in SecurityDefinitions)
|
||||
{
|
||||
// Id 必须定义
|
||||
if (string.IsNullOrWhiteSpace(securityDefinition.Id)
|
||||
|| swaggerGenOptions.SwaggerGeneratorOptions.SecuritySchemes.ContainsKey(securityDefinition.Id)) continue;
|
||||
|
||||
// 添加安全定义
|
||||
var openApiSecurityScheme = securityDefinition as OpenApiSecurityScheme;
|
||||
swaggerGenOptions.AddSecurityDefinition(securityDefinition.Id, openApiSecurityScheme);
|
||||
|
||||
// 添加安全需求
|
||||
var securityRequirement = securityDefinition.Requirement;
|
||||
|
||||
// C# 9.0 模式匹配新语法
|
||||
if (securityRequirement is { Scheme.Reference: not null })
|
||||
{
|
||||
securityRequirement.Scheme.Reference.Id ??= securityDefinition.Id;
|
||||
openApiSecurityRequirement.Add(securityRequirement.Scheme, securityRequirement.Accesses);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加安全需求
|
||||
if (openApiSecurityRequirement.Count > 0)
|
||||
{
|
||||
swaggerGenOptions.AddSecurityRequirement(openApiSecurityRequirement);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,43 @@
|
||||
{
|
||||
"ThingsGateway.Razor.MainLayout": {
|
||||
"About": "About",
|
||||
"FullScreenButton": "Full Screen",
|
||||
"UserCenter": "User Center",
|
||||
"ChoiceModule": "Switch Module",
|
||||
|
||||
"LoginErrorh1": "Login Error",
|
||||
"LoginSuccessh1": "Login Success",
|
||||
"LoginSuccessc1": "Redirecting to the page",
|
||||
"LoginErrorh2": "Login Failed",
|
||||
"LoginErrorc2": "Please contact the administrator!",
|
||||
"Logout": "Logout",
|
||||
|
||||
"系统首页": "Home",
|
||||
"权限管理": "Permission",
|
||||
"用户管理": "User",
|
||||
"角色管理": "Role",
|
||||
"菜单管理": "Menu",
|
||||
"系统运维": "SystemOperation",
|
||||
"系统配置": "System",
|
||||
"字典管理": "Dictionary",
|
||||
"操作日志": "Operation",
|
||||
"会话管理": "Session",
|
||||
"硬件信息": "HardwareInfo",
|
||||
"网关管理": "GatewayManagement",
|
||||
"插件管理": "PluginManagement",
|
||||
"插件调试": "PluginDebugging",
|
||||
"通道管理": "Channel",
|
||||
"采集设备": "CollectionDevices",
|
||||
"业务设备": "BusinessDevices",
|
||||
"变量管理": "Variable",
|
||||
"网关状态": "GatewayStatus",
|
||||
"设备状态": "Device",
|
||||
"实时数据": "RealTimeData",
|
||||
"实时报警": "RealTimeAlarms",
|
||||
"网关日志": "GatewayLogs",
|
||||
"后台日志": "Backend",
|
||||
"RPC日志": "RPC"
|
||||
},
|
||||
|
||||
"ThingsGateway.Admin.Razor.AdminIndex": {
|
||||
"CollectDevice": "Collect Device",
|
||||
|
@@ -1,4 +1,45 @@
|
||||
{
|
||||
"ThingsGateway.Razor.MainLayout": {
|
||||
"About": "关于",
|
||||
"FullScreenButton": "全屏",
|
||||
"UserCenter": "个人中心",
|
||||
"ChoiceModule": "切换模块",
|
||||
|
||||
"LoginErrorh1": "登录异常",
|
||||
"LoginSuccessh1": "登录成功",
|
||||
"LoginSuccessc1": "即将跳转页面",
|
||||
"LoginErrorh2": "登录失败",
|
||||
"LoginErrorc2": "请联系管理员!",
|
||||
"Logout": "注销",
|
||||
|
||||
"系统首页": "系统首页",
|
||||
"权限管理": "权限管理",
|
||||
"用户管理": "用户管理",
|
||||
"角色管理": "角色管理",
|
||||
"菜单管理": "菜单管理",
|
||||
"系统运维": "系统运维",
|
||||
"系统配置": "系统配置",
|
||||
"字典管理": "字典管理",
|
||||
"操作日志": "操作日志",
|
||||
"会话管理": "会话管理",
|
||||
"硬件信息": "硬件信息",
|
||||
"网关管理": "网关管理",
|
||||
"插件管理": "插件管理",
|
||||
"插件调试": "插件调试",
|
||||
"通道管理": "通道管理",
|
||||
"采集设备": "采集设备",
|
||||
"业务设备": "业务设备",
|
||||
"变量管理": "变量管理",
|
||||
"网关状态": "网关状态",
|
||||
"设备状态": "设备状态",
|
||||
"实时数据": "实时数据",
|
||||
"实时报警": "实时报警",
|
||||
"网关日志": "网关日志",
|
||||
"后台日志": "后台日志",
|
||||
"RPC日志": "RPC日志"
|
||||
},
|
||||
|
||||
|
||||
"ThingsGateway.Admin.Razor.AdminIndex": {
|
||||
"CollectDevice": "采集设备",
|
||||
"BusinessDevice": "业务设备",
|
||||
|
@@ -1,8 +1,25 @@
|
||||
@inherits LayoutComponentBase
|
||||
@layout BaseLayout
|
||||
@namespace ThingsGateway.Admin.Razor
|
||||
@namespace ThingsGateway.Razor
|
||||
@using BootstrapBlazor.Components
|
||||
@using ThingsGateway.Admin.Application
|
||||
@using ThingsGateway.Admin.Razor
|
||||
@using ThingsGateway.Core.Extension
|
||||
@using ThingsGateway.Razor
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.Extensions.Localization
|
||||
|
||||
@using System.ComponentModel
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<SysSignalR />
|
||||
@@ -47,6 +64,7 @@
|
||||
@* 全屏按钮 *@
|
||||
<FullScreenButton class="layout-header-bar d-none d-lg-flex px-2" Icon="fa fa-arrows-alt"
|
||||
TooltipPlacement=Placement.Bottom TooltipText="@Localizer[nameof(FullScreenButton)]" />
|
||||
|
||||
@if (WebsiteOption.Value.IsShowAbout)
|
||||
{
|
||||
<Button @onclick="ShowAbout" class="layout-header-bar d-none d-lg-flex px-2" Icon="fa fa-info" Color="Color.None" TooltipText="@Localizer[nameof(About)]" />
|
||||
@@ -82,6 +100,18 @@
|
||||
</NotAuthorized>
|
||||
</Layout>
|
||||
|
||||
@{
|
||||
#if !Admin
|
||||
{
|
||||
if (AppContext.IsHasButtonWithRole(string.Empty, "快捷按钮"))
|
||||
{
|
||||
<ThingsGateway.Gateway.Razor.QuickActions></ThingsGateway.Gateway.Razor.QuickActions>
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
</CascadingValue>
|
@@ -8,10 +8,19 @@
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.Admin.Razor;
|
||||
using ThingsGateway.Core;
|
||||
|
||||
namespace ThingsGateway.Admin.Razor;
|
||||
namespace ThingsGateway.Razor;
|
||||
|
||||
public partial class MainLayout : IDisposable
|
||||
{
|
||||
@@ -29,7 +38,7 @@ public partial class MainLayout : IDisposable
|
||||
{
|
||||
Title = $"{entry.Entry.Title} ",
|
||||
Content = $"{entry.Entry.Message}",
|
||||
Category = ToastCategory.Information,
|
||||
Category = entry.Entry.Category,
|
||||
Delay = 10 * 1000,
|
||||
ForceDelay = true
|
||||
});
|
||||
@@ -38,36 +47,6 @@ public partial class MainLayout : IDisposable
|
||||
|
||||
#endregion 全局通知
|
||||
|
||||
#region Gitee通知
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IDispatchService<GiteePostBody>? CommitDispatchService { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private string? GiteePostTitleText { get; set; }
|
||||
|
||||
private async Task NotifyCommit(DispatchEntry<GiteePostBody> payload)
|
||||
{
|
||||
if (payload.CanDispatch())
|
||||
{
|
||||
var option = new ToastOption()
|
||||
{
|
||||
Category = ToastCategory.Information,
|
||||
Title = GiteePostTitleText,
|
||||
Delay = 10 * 1000,
|
||||
ForceDelay = true,
|
||||
ChildContent = BootstrapDynamicComponent.CreateComponent<CommitItem>(new Dictionary<string, object?>
|
||||
{
|
||||
[nameof(CommitItem.Item)] = payload.Entry
|
||||
}).Render()
|
||||
};
|
||||
await ToastService.Show(option);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Gitee通知
|
||||
|
||||
#region 切换模块
|
||||
|
||||
[Inject]
|
||||
@@ -108,14 +87,17 @@ public partial class MainLayout : IDisposable
|
||||
|
||||
#region 个人信息修改
|
||||
|
||||
private Task OnUserInfoDialog() => DialogService.Show(new DialogOption()
|
||||
private Task OnUserInfoDialog()
|
||||
{
|
||||
Title = Localizer["UserCenter"],
|
||||
ShowFooter = false,
|
||||
Component = BootstrapDynamicComponent.CreateComponent<UserCenterPage>(new Dictionary<string, object?>()
|
||||
return DialogService.Show(new DialogOption()
|
||||
{
|
||||
})
|
||||
});
|
||||
Title = Localizer["UserCenter"],
|
||||
ShowFooter = false,
|
||||
Component = BootstrapDynamicComponent.CreateComponent<UserCenterPage>(new Dictionary<string, object?>()
|
||||
{
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#endregion 个人信息修改
|
||||
|
||||
@@ -197,10 +179,8 @@ public partial class MainLayout : IDisposable
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
GiteePostTitleText = Localizer[nameof(GiteePostTitleText)];
|
||||
_versionString = $"v{VersionService.Version}";
|
||||
DispatchService.Subscribe(Dispatch);
|
||||
CommitDispatchService.Subscribe(NotifyCommit);
|
||||
await AppContext.InitUserAsync();
|
||||
await AppContext.InitMenus(NavigationManager.ToBaseRelativePath(NavigationManager.Uri));
|
||||
await base.OnInitializedAsync();
|
||||
@@ -211,7 +191,6 @@ public partial class MainLayout : IDisposable
|
||||
if (disposing)
|
||||
{
|
||||
DispatchService.UnSubscribe(Dispatch);
|
||||
CommitDispatchService.UnSubscribe(NotifyCommit);
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,9 @@ using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Unicode;
|
||||
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.ASPNetCore;
|
||||
|
||||
using Console = System.Console;
|
||||
|
||||
namespace ThingsGateway.Server;
|
||||
|
||||
@@ -105,9 +107,7 @@ public class Program
|
||||
options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true;
|
||||
});
|
||||
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(a => a.ConfigureSecurities());
|
||||
builder.Services.AddSpecificationDocuments();
|
||||
|
||||
|
||||
builder.Services
|
||||
@@ -147,6 +147,7 @@ public class Program
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseServices();
|
||||
app.UseSpecificationDocuments();
|
||||
|
||||
#region build
|
||||
|
||||
@@ -168,11 +169,7 @@ public class Program
|
||||
app.UseResponseCompression();
|
||||
app.UseStaticFiles(new StaticFileOptions { OnPrepareResponse = ctx => ctx.ProcessCache(app.Configuration) });
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
|
@@ -3,17 +3,9 @@
|
||||
|
||||
<Router AppAssembly="@typeof(Routes).Assembly" AdditionalAssemblies="NetCoreApp.RazorAssemblies.Where(a=>a!=typeof(Routes).Assembly)">
|
||||
<Found Context="routeData">
|
||||
@{
|
||||
#if Admin
|
||||
}
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Admin.Razor.MainLayout)" />
|
||||
@{
|
||||
#else
|
||||
}
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Gateway.Razor.MainLayout)" />
|
||||
@{
|
||||
#endif
|
||||
}
|
||||
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Razor.MainLayout)" />
|
||||
|
||||
|
||||
</Found>
|
||||
<NotFound>
|
||||
|
@@ -9,8 +9,8 @@
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if !Admin
|
||||
using CSScriptLib;
|
||||
using ThingsGateway.Gateway.Application;
|
||||
using ThingsGateway.Gateway.Application;
|
||||
|
||||
#endif
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
@@ -23,6 +23,8 @@ using ThingsGateway.Logging;
|
||||
|
||||
using UAParser;
|
||||
|
||||
using ThingsGateway.ASPNetCore;
|
||||
|
||||
namespace ThingsGateway.Server;
|
||||
|
||||
[AppStartup(-99999)]
|
||||
@@ -124,11 +126,7 @@ public class Startup : AppStartup
|
||||
var userCenterService = a.GetService<IUserCenterService>();
|
||||
var userService = a.GetService<ISysUserService>();
|
||||
var appContext = new BlazorAppContext(sysResourceService, userCenterService, userService);
|
||||
#if Admin
|
||||
appContext.TitleLocalizer = a.GetRequiredService<IStringLocalizer<ThingsGateway.Admin.Razor.MainLayout>>();
|
||||
#else
|
||||
appContext.TitleLocalizer = a.GetRequiredService<IStringLocalizer<ThingsGateway.Gateway.Razor.MainLayout>>();
|
||||
#endif
|
||||
appContext.TitleLocalizer = a.GetRequiredService<IStringLocalizer<ThingsGateway.Razor.MainLayout>>();
|
||||
|
||||
return appContext;
|
||||
});
|
||||
|
@@ -19,13 +19,6 @@
|
||||
<!--<PlatformTarget>x86</PlatformTarget>-->
|
||||
</PropertyGroup>
|
||||
|
||||
<!--<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<AllowedReferenceRelatedFileExtensions>
|
||||
--><!-- 阻止默认的 XML 和 PDB 文件复制到 RELEASE 的输出目录. 只有*.allowedextension 扩展名的文件可以被包含, 当然这个扩展的文件并不存在.--><!--
|
||||
.allowedextension
|
||||
</AllowedReferenceRelatedFileExtensions>
|
||||
</PropertyGroup>-->
|
||||
|
||||
<PropertyGroup Condition="'$(SolutionName)'=='ThingsGateway - Admin'">
|
||||
<DefineConstants>Admin</DefineConstants>
|
||||
</PropertyGroup>
|
||||
@@ -69,7 +62,6 @@
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.0" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
|
||||
</ItemGroup>
|
||||
@@ -81,6 +73,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="favicon.ico" />
|
||||
<Content Include="favicon.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Update="Dockerfile">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
@@ -12,6 +12,34 @@
|
||||
"SignalRSupport": true
|
||||
},
|
||||
|
||||
//swagger设置
|
||||
"SpecificationDocumentSettings": {
|
||||
"DocumentTitle": "ThingsGateway",
|
||||
"DocExpansionState": "None",
|
||||
"GroupOpenApiInfos": [
|
||||
{
|
||||
"Group": "ThingsGateway.OpenApi", //分组唯一标识,string 类型,必填
|
||||
"Order": 99, //分组排序,int 类型,数字越大排前面,默认 0
|
||||
"Title": "ThingsGateway物联网关接口", //配置分组标题,string 类型
|
||||
"Description": "物联网关Swagger",
|
||||
"Version": "1.0.0", //配置分组版本,默认 1.0
|
||||
"TermsOfService": "https://gitee.com/diego2098/ThingsGateway", //配置相关链接地址,Uri 类型
|
||||
"Contact": {
|
||||
//配置联系方式
|
||||
"Name": "Diego",
|
||||
"Url": "https://gitee.com/diego2098/ThingsGateway",
|
||||
"Email": "2248356998@qq.com"
|
||||
},
|
||||
"License": {
|
||||
//配置协议,OpenApiLicense 类型
|
||||
"Name": "Apache-2.0",
|
||||
"Url": "https://gitee.com/diego2098/ThingsGateway/blob/master/LICENSE.txt"
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
"EnableEnumSchemaFilter": true
|
||||
},
|
||||
|
||||
//冗余配置
|
||||
"ManagementOptions": {
|
||||
|
@@ -9,6 +9,34 @@
|
||||
"SignalRSupport": true
|
||||
},
|
||||
|
||||
//swagger设置
|
||||
"SpecificationDocumentSettings": {
|
||||
"DocumentTitle": "ThingsGateway",
|
||||
"DocExpansionState": "None",
|
||||
"GroupOpenApiInfos": [
|
||||
{
|
||||
"Group": "ThingsGateway.OpenApi", //分组唯一标识,string 类型,必填
|
||||
"Order": 99, //分组排序,int 类型,数字越大排前面,默认 0
|
||||
"Title": "ThingsGateway物联网关接口", //配置分组标题,string 类型
|
||||
"Description": "物联网关Swagger",
|
||||
"Version": "1.0.0", //配置分组版本,默认 1.0
|
||||
"TermsOfService": "https://gitee.com/diego2098/ThingsGateway", //配置相关链接地址,Uri 类型
|
||||
"Contact": {
|
||||
//配置联系方式
|
||||
"Name": "Diego",
|
||||
"Url": "https://gitee.com/diego2098/ThingsGateway",
|
||||
"Email": "2248356998@qq.com"
|
||||
},
|
||||
"License": {
|
||||
//配置协议,OpenApiLicense 类型
|
||||
"Name": "Apache-2.0",
|
||||
"Url": "https://gitee.com/diego2098/ThingsGateway/blob/master/LICENSE.txt"
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
"EnableEnumSchemaFilter": true
|
||||
},
|
||||
|
||||
//冗余配置
|
||||
"ManagementOptions": {
|
||||
|
BIN
src/ThingsGateway.Server/favicon.ico
Normal file
BIN
src/ThingsGateway.Server/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>6.0.5.7</Version>
|
||||
<Version>6.0.5.9</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -6,9 +6,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ThingsGateway.Foundation.Variable" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.SiemensS7" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Modbus" Version="*" />
|
||||
<ProjectReference Include="..\ThingsGateway.Foundation.Modbus\ThingsGateway.Foundation.Modbus.csproj" />
|
||||
<ProjectReference Include="..\ThingsGateway.Foundation.SiemensS7\ThingsGateway.Foundation.SiemensS7.csproj" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Variable" Version="8.8.7" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
@@ -24,37 +24,7 @@ public class ModbusRtuSlaveMessage : MessageBase, IResultMessage
|
||||
public override int HeaderLength => 7;
|
||||
|
||||
public ModbusRequest Request { get; set; } = new();
|
||||
//主站发送的报文最低也有8个字节
|
||||
|
||||
public override FilterResult CheckBody<TByteBlock>(ref TByteBlock byteBlock)
|
||||
{
|
||||
var pos = byteBlock.Position - HeaderLength;
|
||||
var crcLen = 0;
|
||||
Bytes = byteBlock.AsSegment(pos, HeaderLength + BodyLength);
|
||||
|
||||
if (Request.FunctionCode == 15)
|
||||
{
|
||||
Request.Data = byteBlock.AsSegmentTake(Request.Length).AsSpan().ByteToBoolArray(Request.Length).Select(a => a ? (byte)0xff : (byte)0).ToArray();
|
||||
}
|
||||
else if (Request.FunctionCode == 16)
|
||||
{
|
||||
Request.Data = byteBlock.AsSegmentTake(Request.Length);
|
||||
}
|
||||
|
||||
crcLen = HeaderLength + BodyLength - 2;
|
||||
|
||||
var crc = CRC16Utils.Crc16Only(byteBlock.Span.Slice(pos, crcLen));
|
||||
|
||||
//Crc
|
||||
var checkCrc = byteBlock.Span.Slice(pos + crcLen, 2).ToArray();
|
||||
if (crc.SequenceEqual(checkCrc))
|
||||
{
|
||||
OperCode = 0;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
|
||||
return FilterResult.GoOn;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool CheckHead<TByteBlock>(ref TByteBlock byteBlock)
|
||||
@@ -100,4 +70,36 @@ public class ModbusRtuSlaveMessage : MessageBase, IResultMessage
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override FilterResult CheckBody<TByteBlock>(ref TByteBlock byteBlock)
|
||||
{
|
||||
var pos = byteBlock.Position - HeaderLength;
|
||||
var crcLen = 0;
|
||||
Bytes = byteBlock.AsSegment(pos, HeaderLength + BodyLength);
|
||||
|
||||
if (Request.FunctionCode == 15)
|
||||
{
|
||||
Request.Data = byteBlock.AsSegmentTake(Request.Length).AsSpan().ByteToBoolArray(Request.Length).Select(a => a ? (byte)0xff : (byte)0).ToArray();
|
||||
}
|
||||
else if (Request.FunctionCode == 16)
|
||||
{
|
||||
Request.Data = byteBlock.AsSegmentTake(Request.Length);
|
||||
}
|
||||
|
||||
crcLen = HeaderLength + BodyLength - 2;
|
||||
|
||||
var crc = CRC16Utils.Crc16Only(byteBlock.Span.Slice(pos, crcLen));
|
||||
|
||||
//Crc
|
||||
var checkCrc = byteBlock.Span.Slice(pos + crcLen, 2).ToArray();
|
||||
if (crc.SequenceEqual(checkCrc))
|
||||
{
|
||||
OperCode = 0;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
|
||||
return FilterResult.GoOn;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -25,27 +25,6 @@ public class ModbusTcpSlaveMessage : MessageBase, IResultMessage
|
||||
|
||||
public ModbusRequest Request { get; set; } = new();
|
||||
|
||||
public override FilterResult CheckBody<TByteBlock>(ref TByteBlock byteBlock)
|
||||
{
|
||||
var pos = byteBlock.Position - HeaderLength;
|
||||
Bytes = byteBlock.AsSegment(pos, HeaderLength + BodyLength);
|
||||
|
||||
|
||||
if (Request.FunctionCode == 15)
|
||||
{
|
||||
byteBlock.Position += 1;
|
||||
Request.Data = byteBlock.AsSegmentTake(Request.Length).AsSpan().ByteToBoolArray(Request.Length).Select(a => a ? (byte)0xff : (byte)0).ToArray();
|
||||
}
|
||||
else if (Request.FunctionCode == 16)
|
||||
{
|
||||
byteBlock.Position += 1;
|
||||
Request.Data = byteBlock.AsSegmentTake(Request.Length);
|
||||
}
|
||||
|
||||
OperCode = 0;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
|
||||
public override bool CheckHead<TByteBlock>(ref TByteBlock byteBlock)
|
||||
{
|
||||
Sign = byteBlock.ReadUInt16(EndianType.Big);
|
||||
@@ -88,4 +67,27 @@ public class ModbusTcpSlaveMessage : MessageBase, IResultMessage
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public override FilterResult CheckBody<TByteBlock>(ref TByteBlock byteBlock)
|
||||
{
|
||||
var pos = byteBlock.Position - HeaderLength;
|
||||
Bytes = byteBlock.AsSegment(pos, HeaderLength + BodyLength);
|
||||
|
||||
|
||||
if (Request.FunctionCode == 15)
|
||||
{
|
||||
byteBlock.Position += 1;
|
||||
Request.Data = byteBlock.AsSegmentTake(Request.Length).AsSpan().ByteToBoolArray(Request.Length).Select(a => a ? (byte)0xff : (byte)0).ToArray();
|
||||
}
|
||||
else if (Request.FunctionCode == 16)
|
||||
{
|
||||
byteBlock.Position += 1;
|
||||
Request.Data = byteBlock.AsSegmentTake(Request.Length);
|
||||
}
|
||||
|
||||
OperCode = 0;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -33,12 +33,12 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ThingsGateway.Foundation.Razor" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Modbus" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.OpcUa" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.OpcDa" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.SiemensS7" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Dlt645" Version="*" />
|
||||
<ProjectReference Include="..\..\adapter\ThingsGateway.Foundation.Dlt645\ThingsGateway.Foundation.Dlt645.csproj" />
|
||||
<ProjectReference Include="..\..\adapter\ThingsGateway.Foundation.Modbus\ThingsGateway.Foundation.Modbus.csproj" />
|
||||
<ProjectReference Include="..\..\adapter\ThingsGateway.Foundation.OpcDa\ThingsGateway.Foundation.OpcDa.csproj" />
|
||||
<ProjectReference Include="..\..\adapter\ThingsGateway.Foundation.OpcUa\ThingsGateway.Foundation.OpcUa.csproj" />
|
||||
<ProjectReference Include="..\..\adapter\ThingsGateway.Foundation.SiemensS7\ThingsGateway.Foundation.SiemensS7.csproj" />
|
||||
<ProjectReference Include="..\..\tools\ThingsGateway.Foundation.Razor\ThingsGateway.Foundation.Razor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
@@ -14,7 +14,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <summary>
|
||||
/// App静态类
|
@@ -13,7 +13,7 @@ using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static class CacheExtensions
|
@@ -12,7 +12,7 @@ using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.ASPNetCore;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder;
|
||||
|
@@ -14,7 +14,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using ThingsGateway;
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.ASPNetCore;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
|
@@ -9,14 +9,107 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <summary>
|
||||
/// 常量、公共方法配置类
|
||||
/// </summary>
|
||||
internal static class Penetrates
|
||||
{
|
||||
/// <summary>
|
||||
/// 分组分隔符
|
||||
/// </summary>
|
||||
internal const string GroupSeparator = "##";
|
||||
|
||||
/// <summary>
|
||||
/// 请求动词映射字典
|
||||
/// </summary>
|
||||
internal static ConcurrentDictionary<string, string> VerbToHttpMethods { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 控制器排序集合
|
||||
/// </summary>
|
||||
internal static ConcurrentDictionary<string, (string, int, Type)> ControllerOrderCollection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
static Penetrates()
|
||||
{
|
||||
ControllerOrderCollection = new ConcurrentDictionary<string, (string, int, Type)>();
|
||||
|
||||
VerbToHttpMethods = new ConcurrentDictionary<string, string>
|
||||
{
|
||||
["post"] = "POST",
|
||||
["add"] = "POST",
|
||||
["create"] = "POST",
|
||||
["insert"] = "POST",
|
||||
["submit"] = "POST",
|
||||
|
||||
["get"] = "GET",
|
||||
["find"] = "GET",
|
||||
["fetch"] = "GET",
|
||||
["query"] = "GET",
|
||||
//["getlist"] = "GET",
|
||||
//["getall"] = "GET",
|
||||
|
||||
["put"] = "PUT",
|
||||
["update"] = "PUT",
|
||||
|
||||
["delete"] = "DELETE",
|
||||
["remove"] = "DELETE",
|
||||
["clear"] = "DELETE",
|
||||
|
||||
["patch"] = "PATCH"
|
||||
};
|
||||
|
||||
IsApiControllerCached = new ConcurrentDictionary<Type, bool>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IsApiController(Type)"/> 缓存集合
|
||||
/// </summary>
|
||||
private static readonly ConcurrentDictionary<Type, bool> IsApiControllerCached;
|
||||
|
||||
/// <summary>
|
||||
/// 是否是Api控制器
|
||||
/// </summary>
|
||||
/// <param name="type">type</param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsApiController(Type type)
|
||||
{
|
||||
return IsApiControllerCached.GetOrAdd(type, Function);
|
||||
|
||||
// 本地静态方法
|
||||
static bool Function(Type type)
|
||||
{
|
||||
// 排除 OData 控制器
|
||||
if (type.Assembly.GetName().Name.StartsWith("Microsoft.AspNetCore.OData")) return false;
|
||||
|
||||
// 不能是非公开、基元类型、值类型、抽象类、接口、泛型类
|
||||
if (!type.IsPublic || type.IsPrimitive || type.IsValueType || type.IsAbstract || type.IsInterface || type.IsGenericType) return false;
|
||||
|
||||
// 继承 ControllerBase
|
||||
if ((!typeof(Controller).IsAssignableFrom(type) && typeof(ControllerBase).IsAssignableFrom(type))
|
||||
// 支持没有继承 ControllerBase 且贴了 [Route] 特性的情况
|
||||
|| (type.IsDefined(typeof(RouteAttribute), true)))
|
||||
{
|
||||
// 处理运行时动态生成程序集问题
|
||||
if (type.Assembly?.ManifestModule?.Name == "<Unknown>") return true;
|
||||
|
||||
// 解决 ASP.NET Core 启动时自动载入 NuGet 包导致模块化配置 SupportPackageNamePrefixs 出现非预期的结果
|
||||
if (!App.EffectiveTypes.Any(t => t == type)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 默认跨域导出响应头 Key
|
||||
/// </summary>
|
@@ -12,7 +12,7 @@ using Microsoft.Extensions.Configuration;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <summary>
|
||||
/// 跨域配置选项
|
@@ -0,0 +1,86 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://kimdiego2098.github.io/
|
||||
// QQ群:605534569
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace Microsoft.Extensions.Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// IConfiguration 接口拓展
|
||||
/// </summary>
|
||||
public static class IConfigurationExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 判断配置节点是否存在
|
||||
/// </summary>
|
||||
/// <param name="configuration">配置对象</param>
|
||||
/// <param name="key">节点路径</param>
|
||||
/// <returns>是否存在</returns>
|
||||
public static bool Exists(this IConfiguration configuration, string key)
|
||||
{
|
||||
return configuration.GetSection(key).Exists();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取配置节点并转换成指定类型
|
||||
/// </summary>
|
||||
/// <typeparam name="T">节点类型</typeparam>
|
||||
/// <param name="configuration">配置对象</param>
|
||||
/// <param name="key">节点路径</param>
|
||||
/// <returns>节点类型实例</returns>
|
||||
public static T Get<T>(this IConfiguration configuration, string key)
|
||||
{
|
||||
return configuration.GetSection(key).Get<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取配置节点并转换成指定类型
|
||||
/// </summary>
|
||||
/// <typeparam name="T">节点类型</typeparam>
|
||||
/// <param name="configuration">配置对象</param>
|
||||
/// <param name="key">节点路径</param>
|
||||
/// <param name="configureOptions">配置值绑定到指定类型额外配置</param>
|
||||
/// <returns>节点类型实例</returns>
|
||||
public static T Get<T>(this IConfiguration configuration
|
||||
, string key
|
||||
, Action<BinderOptions> configureOptions)
|
||||
{
|
||||
return configuration.GetSection(key).Get<T>(configureOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点配置
|
||||
/// </summary>
|
||||
/// <param name="configuration">配置对象</param>
|
||||
/// <param name="key">节点路径</param>
|
||||
/// <param name="type">节点类型</param>
|
||||
/// <returns><see cref="object"/> 实例</returns>
|
||||
public static object Get(this IConfiguration configuration
|
||||
, string key
|
||||
, Type type)
|
||||
{
|
||||
return configuration.GetSection(key).Get(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点配置
|
||||
/// </summary>
|
||||
/// <param name="configuration">配置对象</param>
|
||||
/// <param name="key">节点路径</param>
|
||||
/// <param name="type">节点类型</param>
|
||||
/// <param name="configureOptions">配置值绑定到指定类型额外配置</param>
|
||||
/// <returns><see cref="object"/> 实例</returns>
|
||||
public static object Get(this IConfiguration configuration
|
||||
, string key
|
||||
, Type type
|
||||
, Action<BinderOptions> configureOptions)
|
||||
{
|
||||
return configuration.GetSection(key).Get(type, configureOptions);
|
||||
}
|
||||
}
|
@@ -13,15 +13,6 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using ThingsGateway;
|
||||
using ThingsGateway.Logging;
|
||||
// ------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://kimdiego2098.github.io/
|
||||
// QQ群:605534569
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
public static class LoggingServiceCollectionExtensions
|
||||
{
|
@@ -27,7 +27,7 @@ using System.Text.Json;
|
||||
|
||||
using ThingsGateway.Core.Json.Extension;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <summary>
|
||||
/// 规范化RESTful风格返回值
|
@@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <summary>
|
||||
/// 规范化结果提供器
|
@@ -18,7 +18,7 @@ using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <summary>
|
||||
/// 规范化结果上下文
|
@@ -14,9 +14,10 @@ using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
using ThingsGateway.Core;
|
||||
using ThingsGateway.NewLife.X;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <summary>
|
||||
/// 规范化RESTful风格返回值
|
@@ -27,7 +27,7 @@ using System.Text.Json;
|
||||
|
||||
using JwtRegisteredClaimNames = Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <summary>
|
||||
/// JWT 加解密
|
@@ -8,7 +8,7 @@
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <summary>
|
||||
/// 日志常量
|
@@ -8,7 +8,7 @@
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
/// <summary>
|
||||
/// 认证信息
|
@@ -34,7 +34,7 @@ using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
using ThingsGateway;
|
||||
using ThingsGateway.Admin.Application;
|
||||
using ThingsGateway.ASPNetCore;
|
||||
using ThingsGateway.Core.Extension;
|
||||
using ThingsGateway.Logging;
|
||||
using ThingsGateway.NewLife.X;
|
@@ -11,7 +11,7 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace ThingsGateway.Admin.Application;
|
||||
namespace ThingsGateway.ASPNetCore;
|
||||
|
||||
public abstract class AppAuthorizeHandler : IAuthorizationHandler
|
||||
{
|
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user