mirror of
				https://gitee.com/ThingsGateway/ThingsGateway.git
				synced 2025-10-31 23:53:58 +08:00 
			
		
		
		
	Compare commits
	
		
			6 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | ad299d0dbb | ||
|   | 8b124d1050 | ||
|   | ff41080dbd | ||
|   | 0e28606e3d | ||
|   | 6a025ceee5 | ||
|   | 6b2e53d6dc | 
| @@ -21,29 +21,36 @@ using System.Logging; | |||||||
| using ThingsGateway.FriendlyException; | using ThingsGateway.FriendlyException; | ||||||
| using ThingsGateway.Logging; | using ThingsGateway.Logging; | ||||||
| using ThingsGateway.NewLife.Json.Extension; | using ThingsGateway.NewLife.Json.Extension; | ||||||
|  | using ThingsGateway.UnifyResult; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Admin.Application; | namespace ThingsGateway.Admin.Application; | ||||||
|  |  | ||||||
| public class RequestAuditFilter : IAsyncActionFilter | public class RequestAuditFilter : IAsyncActionFilter, IOrderedFilter | ||||||
| { | { | ||||||
|  |     private const int FilterOrder = -3000; | ||||||
|  |     public int Order => FilterOrder; | ||||||
|  |  | ||||||
|     public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) |     public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) | ||||||
|     { |     { | ||||||
|  |         var timeOperation = Stopwatch.StartNew(); | ||||||
|  |         var resultContext = await next().ConfigureAwait(false); | ||||||
|  |         // 计算接口执行时间 | ||||||
|  |         timeOperation.Stop(); | ||||||
|  |  | ||||||
|         var controllerActionDescriptor = (context.ActionDescriptor as ControllerActionDescriptor); |         var controllerActionDescriptor = (context.ActionDescriptor as ControllerActionDescriptor); | ||||||
|         // 获取动作方法描述器 |         // 获取动作方法描述器 | ||||||
|         var actionMethod = controllerActionDescriptor?.MethodInfo; |         var actionMethod = controllerActionDescriptor?.MethodInfo; | ||||||
|  |  | ||||||
|  |  | ||||||
|         // 处理 Blazor Server |         // 处理 Blazor Server | ||||||
|         if (actionMethod == null) |         if (actionMethod == null) | ||||||
|         { |         { | ||||||
|             _ = await next.Invoke().ConfigureAwait(false); |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 排除 WebSocket 请求处理 |         // 排除 WebSocket 请求处理 | ||||||
|         if (context.HttpContext.IsWebSocketRequest()) |         if (context.HttpContext.IsWebSocketRequest()) | ||||||
|         { |         { | ||||||
|             _ = await next().ConfigureAwait(false); |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -51,7 +58,6 @@ public class RequestAuditFilter : IAsyncActionFilter | |||||||
|         if (actionMethod.IsDefined(typeof(SuppressRequestAuditAttribute), true) |         if (actionMethod.IsDefined(typeof(SuppressRequestAuditAttribute), true) | ||||||
|             || actionMethod.DeclaringType.IsDefined(typeof(SuppressRequestAuditAttribute), true)) |             || actionMethod.DeclaringType.IsDefined(typeof(SuppressRequestAuditAttribute), true)) | ||||||
|         { |         { | ||||||
|             _ = await next().ConfigureAwait(false); |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -65,10 +71,7 @@ public class RequestAuditFilter : IAsyncActionFilter | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 计算接口执行时间 |  | ||||||
|         var timeOperation = Stopwatch.StartNew(); |  | ||||||
|         var resultContext = await next().ConfigureAwait(false); |  | ||||||
|         timeOperation.Stop(); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         var logData = new RequestAuditData(); |         var logData = new RequestAuditData(); | ||||||
| @@ -88,21 +91,29 @@ public class RequestAuditFilter : IAsyncActionFilter | |||||||
|         var requestUrl = Uri.UnescapeDataString(httpRequest.GetRequestUrlAddress()); |         var requestUrl = Uri.UnescapeDataString(httpRequest.GetRequestUrlAddress()); | ||||||
|         logData.RequestUrl = requestUrl; |         logData.RequestUrl = requestUrl; | ||||||
|  |  | ||||||
|  |         object returnValue = null; | ||||||
|  |         Type finalReturnType; | ||||||
|         var result = resultContext.Result as IActionResult; |         var result = resultContext.Result as IActionResult; | ||||||
|         var data = result switch |         // 解析返回值 | ||||||
|  |         if (UnifyContext.CheckVaildResult(result, out var data)) | ||||||
|         { |         { | ||||||
|             // 处理内容结果 |             returnValue = data; | ||||||
|             ContentResult content => content.Content, |             finalReturnType = data?.GetType(); | ||||||
|             // 处理对象结果 |         } | ||||||
|             ObjectResult obj => obj.Value, |         // 处理文件类型 | ||||||
|             // 处理 JSON 对象 |         else if (result is FileResult fresult) | ||||||
|             JsonResult json => json.Value, |         { | ||||||
|             _ => null, |             returnValue = new | ||||||
|         }; |             { | ||||||
|         logData.ReturnInformation = data; |                 FileName = fresult.FileDownloadName, | ||||||
|  |                 fresult.ContentType, | ||||||
|  |                 Length = fresult is FileContentResult cresult ? (object)cresult.FileContents.Length : null | ||||||
|  |             }; | ||||||
|  |             finalReturnType = fresult?.GetType(); | ||||||
|  |         } | ||||||
|  |         else finalReturnType = result?.GetType(); | ||||||
|  |  | ||||||
|  |         logData.ReturnInformation = returnValue; | ||||||
|  |  | ||||||
|         //获取客户端信息 |         //获取客户端信息 | ||||||
|         var client = App.GetService<IAppService>().UserAgent; |         var client = App.GetService<IAppService>().UserAgent; | ||||||
|   | |||||||
| @@ -16,7 +16,6 @@ using ThingsGateway.Extension; | |||||||
| using ThingsGateway.FriendlyException; | using ThingsGateway.FriendlyException; | ||||||
| using ThingsGateway.Logging; | using ThingsGateway.Logging; | ||||||
| using ThingsGateway.NewLife.Json.Extension; | using ThingsGateway.NewLife.Json.Extension; | ||||||
| using ThingsGateway.Razor; |  | ||||||
|  |  | ||||||
| namespace ThingsGateway.Admin.Application; | namespace ThingsGateway.Admin.Application; | ||||||
|  |  | ||||||
| @@ -160,8 +159,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter | |||||||
|         if (path == "/api/auth/login") |         if (path == "/api/auth/login") | ||||||
|         { |         { | ||||||
|             //如果是登录,用户信息就从返回值里拿 |             //如果是登录,用户信息就从返回值里拿 | ||||||
|             var result = requestAuditData.ReturnInformation?.ToSystemTextJsonString();//返回值转json |             dynamic userInfo = requestAuditData.ReturnInformation; | ||||||
|             var userInfo = result.FromJsonNetString<UnifyResult<LoginOutput>>();//格式化成user表 |  | ||||||
|             opAccount = userInfo.Data.Account;//赋值账号 |             opAccount = userInfo.Data.Account;//赋值账号 | ||||||
|             verificatId = userInfo.Data.VerificatId; |             verificatId = userInfo.Data.VerificatId; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -117,6 +117,25 @@ public class SugarAopService : ISugarAopService | |||||||
|         db.Aop.DataExecuted = (value, entity) => |         db.Aop.DataExecuted = (value, entity) => | ||||||
|         { |         { | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         db.Aop.OnLogExecuted = (sql, pars) => | ||||||
|  |         { | ||||||
|  |             //执行时间超过1秒 | ||||||
|  |             if (db.Ado.SqlExecutionTime.TotalSeconds > 1) | ||||||
|  |             { | ||||||
|  |                 //代码CS文件名 | ||||||
|  |                 var fileName = db.Ado.SqlStackTrace.FirstFileName; | ||||||
|  |                 //代码行数 | ||||||
|  |                 var fileLine = db.Ado.SqlStackTrace.FirstLine; | ||||||
|  |                 //方法名 | ||||||
|  |                 var FirstMethodName = db.Ado.SqlStackTrace.FirstMethodName; | ||||||
|  |  | ||||||
|  |                 DbContext.WriteLog($"{fileName}-{FirstMethodName}-{fileLine} 执行时间超过1秒"); | ||||||
|  |                 DbContext.WriteLogWithSql(UtilMethods.GetNativeSql(sql, pars)); | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ public sealed class SqlSugarOption : ConnectionConfig | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 是否控制台显示Sql语句 |     /// 是否控制台显示Sql语句 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public bool IsShowSql { get; set; } |     public bool? IsShowSql { get; set; } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 更新数据 |     /// 更新数据 | ||||||
|   | |||||||
| @@ -98,6 +98,18 @@ public class Startup : AppStartup | |||||||
|         CodeFirstUtils.CodeFirst(fullName!);//CodeFirst |         CodeFirstUtils.CodeFirst(fullName!);//CodeFirst | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         try | ||||||
|  |         { | ||||||
|  |             using var db = DbContext.GetDB<SysOperateLog>(); | ||||||
|  |             if (!db.DbMaintenance.IsAnyIndex("idx_operatelog_optime_date")) | ||||||
|  |             { | ||||||
|  |                 var indexsql = "CREATE INDEX idx_operatelog_optime_date ON sys_operatelog(strftime('%Y-%m-%d', OpTime));"; | ||||||
|  |                 db.Ado.ExecuteCommand(indexsql); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         catch { } | ||||||
|  |  | ||||||
|  |  | ||||||
|         //删除在线用户统计 |         //删除在线用户统计 | ||||||
|         var verificatInfoService = App.RootServices.GetService<IVerificatInfoService>(); |         var verificatInfoService = App.RootServices.GetService<IVerificatInfoService>(); | ||||||
|         verificatInfoService.RemoveAllClientId(); |         verificatInfoService.RemoveAllClientId(); | ||||||
|   | |||||||
| @@ -88,6 +88,7 @@ public class Startup : AppStartup | |||||||
|         } |         } | ||||||
|         ; |         ; | ||||||
|  |  | ||||||
|  |         services.AddMvcFilter<RequestAuditFilter>(); | ||||||
|         services.AddControllers() |         services.AddControllers() | ||||||
|             .AddNewtonsoftJson(options => SetNewtonsoftJsonSetting(options.SerializerSettings)) |             .AddNewtonsoftJson(options => SetNewtonsoftJsonSetting(options.SerializerSettings)) | ||||||
|             //.AddXmlSerializerFormatters() |             //.AddXmlSerializerFormatters() | ||||||
| @@ -237,7 +238,6 @@ public class Startup : AppStartup | |||||||
|         //        logContext.Set(LoggingConst.Method, httpContext.Request.Method);//请求方法 |         //        logContext.Set(LoggingConst.Method, httpContext.Request.Method);//请求方法 | ||||||
|         //    }); |         //    }); | ||||||
|         //}); |         //}); | ||||||
|         services.AddMvcFilter<RequestAuditFilter>(); |  | ||||||
|  |  | ||||||
|         //日志写入数据库配置 |         //日志写入数据库配置 | ||||||
|         services.AddDatabaseLogging<DatabaseLoggingWriter>(options => |         services.AddDatabaseLogging<DatabaseLoggingWriter>(options => | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ public static class ILoggerExtensions | |||||||
|     /// <param name="logger"></param> |     /// <param name="logger"></param> | ||||||
|     /// <param name="properties">建议使用 ConcurrentDictionary 类型</param> |     /// <param name="properties">建议使用 ConcurrentDictionary 类型</param> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     public static IDisposable ScopeContext(this ILogger logger, IDictionary<object, object> properties) |     public static IDisposable ScopeContext(this ILogger logger, IDictionary<string, object> properties) | ||||||
|     { |     { | ||||||
|         if (logger == null) throw new ArgumentNullException(nameof(logger)); |         if (logger == null) throw new ArgumentNullException(nameof(logger)); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,11 +26,11 @@ public static class LogContextExtensions | |||||||
|     /// <param name="key">键</param> |     /// <param name="key">键</param> | ||||||
|     /// <param name="value">值</param> |     /// <param name="value">值</param> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     public static LogContext Set(this LogContext logContext, object key, object value) |     public static LogContext Set(this LogContext logContext, string key, object value) | ||||||
|     { |     { | ||||||
|         if (logContext == null || key == null) return logContext; |         if (logContext == null || key == null) return logContext; | ||||||
|  |  | ||||||
|         logContext.Properties ??= new Dictionary<object, object>(); |         logContext.Properties ??= new Dictionary<string, object>(); | ||||||
|  |  | ||||||
|         logContext.Properties.Remove(key); |         logContext.Properties.Remove(key); | ||||||
|         logContext.Properties.Add(key, value); |         logContext.Properties.Add(key, value); | ||||||
| @@ -43,7 +43,7 @@ public static class LogContextExtensions | |||||||
|     /// <param name="logContext"></param> |     /// <param name="logContext"></param> | ||||||
|     /// <param name="properties"></param> |     /// <param name="properties"></param> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     public static LogContext SetRange(this LogContext logContext, IDictionary<object, object> properties) |     public static LogContext SetRange(this LogContext logContext, IDictionary<string, object> properties) | ||||||
|     { |     { | ||||||
|         if (logContext == null |         if (logContext == null | ||||||
|             || properties == null |             || properties == null | ||||||
| @@ -63,7 +63,7 @@ public static class LogContextExtensions | |||||||
|     /// <param name="logContext"></param> |     /// <param name="logContext"></param> | ||||||
|     /// <param name="key">键</param> |     /// <param name="key">键</param> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     public static object Get(this LogContext logContext, object key) |     public static object Get(this LogContext logContext, string key) | ||||||
|     { |     { | ||||||
|         if (logContext == null |         if (logContext == null | ||||||
|             || key == null |             || key == null | ||||||
| @@ -80,7 +80,7 @@ public static class LogContextExtensions | |||||||
|     /// <param name="logContext"></param> |     /// <param name="logContext"></param> | ||||||
|     /// <param name="key">键</param> |     /// <param name="key">键</param> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     public static T Get<T>(this LogContext logContext, object key) |     public static T Get<T>(this LogContext logContext, string key) | ||||||
|     { |     { | ||||||
|         var value = logContext.Get(key); |         var value = logContext.Get(key); | ||||||
|         return value.ChangeType<T>(); |         return value.ChangeType<T>(); | ||||||
|   | |||||||
| @@ -84,7 +84,7 @@ public static class StringLoggingExtensions | |||||||
|     /// <param name="message"></param> |     /// <param name="message"></param> | ||||||
|     /// <param name="properties">建议使用 ConcurrentDictionary 类型</param> |     /// <param name="properties">建议使用 ConcurrentDictionary 类型</param> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     public static StringLoggingPart ScopeContext(this string message, IDictionary<object, object> properties) |     public static StringLoggingPart ScopeContext(this string message, IDictionary<string, object> properties) | ||||||
|     { |     { | ||||||
|         return StringLoggingPart.Default().SetMessage(message).ScopeContext(properties); |         return StringLoggingPart.Default().SetMessage(message).ScopeContext(properties); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ public sealed class LogContext : IDisposable | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 日志上下文数据 |     /// 日志上下文数据 | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public IDictionary<object, object> Properties { get; set; } |     public IDictionary<string, object> Properties { get; set; } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// 原生日志上下文数据 |     /// 原生日志上下文数据 | ||||||
|   | |||||||
| @@ -96,7 +96,7 @@ public sealed partial class StringLoggingPart | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <param name="properties">建议使用 ConcurrentDictionary 类型</param> |     /// <param name="properties">建议使用 ConcurrentDictionary 类型</param> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     public StringLoggingPart ScopeContext(IDictionary<object, object> properties) |     public StringLoggingPart ScopeContext(IDictionary<string, object> properties) | ||||||
|     { |     { | ||||||
|         if (properties == null) return this; |         if (properties == null) return this; | ||||||
|         LogContext = new LogContext { Properties = properties }; |         LogContext = new LogContext { Properties = properties }; | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ public static class Log | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <param name="properties">建议使用 ConcurrentDictionary 类型</param> |     /// <param name="properties">建议使用 ConcurrentDictionary 类型</param> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     public static (ILogger logger, IDisposable scope) ScopeContext(IDictionary<object, object> properties) |     public static (ILogger logger, IDisposable scope) ScopeContext(IDictionary<string, object> properties) | ||||||
|     { |     { | ||||||
|         return GetLogger(StringLoggingPart.Default().ScopeContext(properties)); |         return GetLogger(StringLoggingPart.Default().ScopeContext(properties)); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -349,7 +349,7 @@ public static class UnifyContext | |||||||
|     /// <param name="result"></param> |     /// <param name="result"></param> | ||||||
|     /// <param name="data"></param> |     /// <param name="data"></param> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     internal static bool CheckVaildResult(IActionResult result, out object data) |     public static bool CheckVaildResult(IActionResult result, out object data) | ||||||
|     { |     { | ||||||
|         data = default; |         data = default; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -37,7 +37,8 @@ public static class SystemTextJsonExtension | |||||||
|         { |         { | ||||||
|             Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, |             Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, | ||||||
|             WriteIndented = true, // 缩进 |             WriteIndented = true, // 缩进 | ||||||
|             DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull // 忽略 null |             DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, // 忽略 null | ||||||
|  |             NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals, | ||||||
|         }; |         }; | ||||||
|         // 如有自定义Converter,这里添加 |         // 如有自定义Converter,这里添加 | ||||||
|         // IndentedOptions.Converters.Add(new ByteArrayJsonConverter()); |         // IndentedOptions.Converters.Add(new ByteArrayJsonConverter()); | ||||||
| @@ -50,7 +51,8 @@ public static class SystemTextJsonExtension | |||||||
|         { |         { | ||||||
|             Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, |             Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, | ||||||
|             WriteIndented = false, // 不缩进 |             WriteIndented = false, // 不缩进 | ||||||
|             DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull |             DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, | ||||||
|  |             NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals, | ||||||
|         }; |         }; | ||||||
|         NoneIndentedOptions.Converters.Add(new ByteArrayToNumberArrayConverterSystemTextJson()); |         NoneIndentedOptions.Converters.Add(new ByteArrayToNumberArrayConverterSystemTextJson()); | ||||||
|         NoneIndentedOptions.Converters.Add(new JTokenSystemTextJsonConverter()); |         NoneIndentedOptions.Converters.Add(new JTokenSystemTextJsonConverter()); | ||||||
|   | |||||||
| @@ -27,6 +27,13 @@ public class Startup : AppStartup | |||||||
|     { |     { | ||||||
|         services.AddBootstrapBlazor( |         services.AddBootstrapBlazor( | ||||||
|             option => option.JSModuleVersion = Random.Shared.Next(10000).ToString() |             option => option.JSModuleVersion = Random.Shared.Next(10000).ToString() | ||||||
|  |             , jsonLocalizationOptions => | ||||||
|  |             { | ||||||
|  |                 jsonLocalizationOptions.DisableGetLocalizerFromResourceManager = true; | ||||||
|  |                 jsonLocalizationOptions.DisableGetLocalizerFromService = true; | ||||||
|  |                 jsonLocalizationOptions.IgnoreLocalizerMissing = true; | ||||||
|  |                 jsonLocalizationOptions.UseKeyWhenValueIsNull = true; | ||||||
|  |             } | ||||||
|             ); |             ); | ||||||
|         services.AddConfigurableOptions<MenuOptions>(); |         services.AddConfigurableOptions<MenuOptions>(); | ||||||
|         services.ConfigureIconThemeOptions(options => options.ThemeKey = "fa"); |         services.ConfigureIconThemeOptions(options => options.ThemeKey = "fa"); | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| //下载文件 | //下载文件 | ||||||
| export function blazor_downloadFile(url, fileName, dtoObject) { | export async function blazor_downloadFile(url, fileName, dtoObject) { | ||||||
|     const params = new URLSearchParams(); |     const params = new URLSearchParams(); | ||||||
|  |  | ||||||
|     // 将 dtoObject 的属性添加到 URLSearchParams 中 |     // 将 dtoObject 的属性添加到 URLSearchParams 中 | ||||||
| @@ -12,97 +12,92 @@ export function blazor_downloadFile(url, fileName, dtoObject) { | |||||||
|     // 构建完整的 URL |     // 构建完整的 URL | ||||||
|     const fullUrl = `${url}?${params.toString()}`; |     const fullUrl = `${url}?${params.toString()}`; | ||||||
|  |  | ||||||
|     // 发起 fetch 请求 |     try { | ||||||
|     fetch(fullUrl) |         // 发起 fetch 请求 | ||||||
|         .then(response => { |         const response = await fetch(fullUrl); | ||||||
|             // 获取响应头中的 content-disposition |  | ||||||
|             const dispositionHeader = response.headers.get('content-disposition'); |  | ||||||
|             let resolvedFileName = fileName; |  | ||||||
|  |  | ||||||
|             if (dispositionHeader) { |         // 获取响应头中的 content-disposition | ||||||
|                 // 解析出文件名 |         const dispositionHeader = response.headers.get('content-disposition'); | ||||||
|                 const match = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(dispositionHeader); |         let resolvedFileName = fileName; | ||||||
|                 const serverFileName = match && match[1] ? match[1].replace(/['"]/g, '') : null; |  | ||||||
|                 if (serverFileName) { |         if (dispositionHeader) { | ||||||
|                     resolvedFileName = serverFileName; |             // 解析出文件名 | ||||||
|                 } |             const match = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(dispositionHeader); | ||||||
|  |             const serverFileName = match && match[1] ? match[1].replace(/['"]/g, '') : null; | ||||||
|  |             if (serverFileName) { | ||||||
|  |                 resolvedFileName = serverFileName; | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|             // 将响应转换为 blob 对象 |         // 将响应转换为 blob 对象 | ||||||
|             return response.blob().then(blob => { |         const blob = await response.blob(); | ||||||
|                 // 创建临时的文件 URL |  | ||||||
|                 const fileUrl = window.URL.createObjectURL(blob); |  | ||||||
|  |  | ||||||
|                 // 创建一个 <a> 元素并设置下载链接和文件名 |         // 创建临时的文件 URL | ||||||
|                 const anchorElement = document.createElement('a'); |         const fileUrl = window.URL.createObjectURL(blob); | ||||||
|                 anchorElement.href = fileUrl; |  | ||||||
|                 anchorElement.download = resolvedFileName; |  | ||||||
|                 anchorElement.style.display = 'none'; |  | ||||||
|  |  | ||||||
|                 // 将 <a> 元素添加到 body 中并触发下载 |         // 创建一个 <a> 元素并设置下载链接和文件名 | ||||||
|                 document.body.appendChild(anchorElement); |         const anchorElement = document.createElement('a'); | ||||||
|                 anchorElement.click(); |         anchorElement.href = fileUrl; | ||||||
|                 document.body.removeChild(anchorElement); |         anchorElement.download = resolvedFileName; | ||||||
|  |         anchorElement.style.display = 'none'; | ||||||
|  |  | ||||||
|                 // 撤销临时的文件 URL |         // 将 <a> 元素添加到 body 中并触发下载 | ||||||
|                 window.URL.revokeObjectURL(fileUrl); |         document.body.appendChild(anchorElement); | ||||||
|             }); |         anchorElement.click(); | ||||||
|         }) |         document.body.removeChild(anchorElement); | ||||||
|         .catch(error => { |  | ||||||
|             console.error('DownFile error ', error); |         // 撤销临时的文件 URL | ||||||
|         }); |         window.URL.revokeObjectURL(fileUrl); | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     } catch (error) { | ||||||
|  |         console.error('DownFile error ', error); | ||||||
|  |         throw error; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //下载文件 | //下载文件 | ||||||
| export function postJson_downloadFile(url, fileName, jsonBody) { | export async function postJson_downloadFile(url, fileName, jsonBody) { | ||||||
|     const params = new URLSearchParams(); |  | ||||||
|  |  | ||||||
|  |     try { | ||||||
|     // 发起 fetch 请求 |         const response = await fetch(url, { | ||||||
|     fetch(url, { |             method: 'POST', | ||||||
|         method: 'POST', |             headers: { | ||||||
|         headers: { |                 'Content-Type': 'application/json' | ||||||
|             'Content-Type': 'application/json' |             }, | ||||||
|         }, |             body: jsonBody | ||||||
|         body: jsonBody |  | ||||||
|     }) |  | ||||||
|         .then(response => { |  | ||||||
|             // 获取响应头中的 content-disposition |  | ||||||
|             const dispositionHeader = response.headers.get('content-disposition'); |  | ||||||
|             let resolvedFileName = fileName; |  | ||||||
|  |  | ||||||
|             if (dispositionHeader) { |  | ||||||
|                 // 解析出文件名 |  | ||||||
|                 const match = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(dispositionHeader); |  | ||||||
|                 const serverFileName = match && match[1] ? match[1].replace(/['"]/g, '') : null; |  | ||||||
|                 if (serverFileName) { |  | ||||||
|                     resolvedFileName = serverFileName; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             // 将响应转换为 blob 对象 |  | ||||||
|             return response.blob().then(blob => { |  | ||||||
|                 // 创建临时的文件 URL |  | ||||||
|                 const fileUrl = window.URL.createObjectURL(blob); |  | ||||||
|  |  | ||||||
|                 // 创建一个 <a> 元素并设置下载链接和文件名 |  | ||||||
|                 const anchorElement = document.createElement('a'); |  | ||||||
|                 anchorElement.href = fileUrl; |  | ||||||
|                 anchorElement.download = resolvedFileName; |  | ||||||
|                 anchorElement.style.display = 'none'; |  | ||||||
|  |  | ||||||
|                 // 将 <a> 元素添加到 body 中并触发下载 |  | ||||||
|                 document.body.appendChild(anchorElement); |  | ||||||
|                 anchorElement.click(); |  | ||||||
|                 document.body.removeChild(anchorElement); |  | ||||||
|  |  | ||||||
|                 // 撤销临时的文件 URL |  | ||||||
|                 window.URL.revokeObjectURL(fileUrl); |  | ||||||
|             }); |  | ||||||
|         }) |  | ||||||
|         .catch(error => { |  | ||||||
|             console.error('downfile error ', error); |  | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  |         const dispositionHeader = response.headers.get('content-disposition'); | ||||||
|  |         let resolvedFileName = fileName; | ||||||
|  |  | ||||||
|  |         if (dispositionHeader) { | ||||||
|  |             const match = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(dispositionHeader); | ||||||
|  |             const serverFileName = match && match[1] ? match[1].replace(/['"]/g, '') : null; | ||||||
|  |             if (serverFileName) { | ||||||
|  |                 resolvedFileName = serverFileName; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const blob = await response.blob(); | ||||||
|  |         const fileUrl = window.URL.createObjectURL(blob); | ||||||
|  |  | ||||||
|  |         const anchorElement = document.createElement('a'); | ||||||
|  |         anchorElement.href = fileUrl; | ||||||
|  |         anchorElement.download = resolvedFileName; | ||||||
|  |         anchorElement.style.display = 'none'; | ||||||
|  |  | ||||||
|  |         document.body.appendChild(anchorElement); | ||||||
|  |         anchorElement.click(); | ||||||
|  |         document.body.removeChild(anchorElement); | ||||||
|  |  | ||||||
|  |         window.URL.revokeObjectURL(fileUrl); | ||||||
|  |  | ||||||
|  |         return true; // 唯一新增的返回值 | ||||||
|  |     } catch (error) { | ||||||
|  |         console.error('downfile error ', error); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| <Project> | <Project> | ||||||
|  |  | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
| 		<PluginVersion>10.6.21</PluginVersion> | 		<PluginVersion>10.6.26</PluginVersion> | ||||||
| 		<ProPluginVersion>10.6.21</ProPluginVersion> | 		<ProPluginVersion>10.6.26</ProPluginVersion> | ||||||
| 		<AuthenticationVersion>2.1.7</AuthenticationVersion> | 		<AuthenticationVersion>2.1.8</AuthenticationVersion> | ||||||
| 	</PropertyGroup> | 	</PropertyGroup> | ||||||
|  |  | ||||||
| 	<PropertyGroup> | 	<PropertyGroup> | ||||||
|   | |||||||
| @@ -90,6 +90,7 @@ public class RuntimeInfoController : ControllerBase | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     [HttpPost("checkRealAlarm")] |     [HttpPost("checkRealAlarm")] | ||||||
|  |     [RequestAudit] | ||||||
|     [DisplayName("确认实时报警")] |     [DisplayName("确认实时报警")] | ||||||
|     public async Task CheckRealAlarm(long variableId) |     public async Task CheckRealAlarm(long variableId) | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -26,28 +26,53 @@ internal sealed class GatewayExportService : IGatewayExportService | |||||||
|  |  | ||||||
|     private IJSRuntime JSRuntime { get; set; } |     private IJSRuntime JSRuntime { get; set; } | ||||||
|  |  | ||||||
|     public async Task OnChannelExport(ExportFilter exportFilter) |     public async Task<bool> OnChannelExport(ExportFilter exportFilter) | ||||||
|     { |     { | ||||||
|         await using var ajaxJS = await JSRuntime.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Razor/js/downloadFile.js"); |         try | ||||||
|         string url = "api/gatewayExport/channel"; |         { | ||||||
|         string fileName = $"{DateTime.Now.ToFileDateTimeFormat()}.xlsx"; |  | ||||||
|         await ajaxJS.InvokeVoidAsync("postJson_downloadFile", url, fileName, exportFilter.ToJsonString()); |             await using var ajaxJS = await JSRuntime.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Razor/js/downloadFile.js"); | ||||||
|  |             string url = "api/gatewayExport/channel"; | ||||||
|  |             string fileName = $"{DateTime.Now.ToFileDateTimeFormat()}.xlsx"; | ||||||
|  |             return await ajaxJS.InvokeAsync<bool>("postJson_downloadFile", url, fileName, exportFilter.ToJsonString()); | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         catch | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task OnDeviceExport(ExportFilter exportFilter) |     public async Task<bool> OnDeviceExport(ExportFilter exportFilter) | ||||||
|     { |     { | ||||||
|         await using var ajaxJS = await JSRuntime.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Razor/js/downloadFile.js"); |         try | ||||||
|         string url = "api/gatewayExport/device"; |         { | ||||||
|         string fileName = $"{DateTime.Now.ToFileDateTimeFormat()}.xlsx"; |  | ||||||
|         await ajaxJS.InvokeVoidAsync("postJson_downloadFile", url, fileName, exportFilter.ToJsonString()); |  | ||||||
|  |             await using var ajaxJS = await JSRuntime.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Razor/js/downloadFile.js"); | ||||||
|  |             string url = "api/gatewayExport/device"; | ||||||
|  |             string fileName = $"{DateTime.Now.ToFileDateTimeFormat()}.xlsx"; | ||||||
|  |             return await ajaxJS.InvokeAsync<bool>("postJson_downloadFile", url, fileName, exportFilter.ToJsonString()); | ||||||
|  |         } | ||||||
|  |         catch | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task OnVariableExport(ExportFilter exportFilter) |     public async Task<bool> OnVariableExport(ExportFilter exportFilter) | ||||||
|     { |     { | ||||||
|         await using var ajaxJS = await JSRuntime.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Razor/js/downloadFile.js"); |         try | ||||||
|         string url = "api/gatewayExport/variable"; |         { | ||||||
|         string fileName = $"{DateTime.Now.ToFileDateTimeFormat()}.xlsx"; |             await using var ajaxJS = await JSRuntime.InvokeAsync<IJSObjectReference>("import", $"/_content/ThingsGateway.Razor/js/downloadFile.js"); | ||||||
|         await ajaxJS.InvokeVoidAsync("postJson_downloadFile", url, fileName, exportFilter.ToJsonString()); |             string url = "api/gatewayExport/variable"; | ||||||
|  |             string fileName = $"{DateTime.Now.ToFileDateTimeFormat()}.xlsx"; | ||||||
|  |             return await ajaxJS.InvokeAsync<bool>("postJson_downloadFile", url, fileName, exportFilter.ToJsonString()); | ||||||
|  |         } | ||||||
|  |         catch | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -35,18 +35,30 @@ public sealed class HybridGatewayExportService : IGatewayExportService | |||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task OnChannelExport(ExportFilter exportFilter) |     public async Task<bool> OnChannelExport(ExportFilter exportFilter) | ||||||
|     { |     { | ||||||
|         exportFilter.QueryPageOptions.IsPage = false; |         try | ||||||
|         exportFilter.QueryPageOptions.IsVirtualScroll = false; |         { | ||||||
|  |  | ||||||
|         var sheets = await _channelService.ExportChannelAsync(exportFilter).ConfigureAwait(false); |  | ||||||
|         var path = await _importExportService.CreateFileAsync<Device>(sheets, "Channel", false).ConfigureAwait(false); |  | ||||||
|  |  | ||||||
|         Open(path); |             exportFilter.QueryPageOptions.IsPage = false; | ||||||
|  |             exportFilter.QueryPageOptions.IsVirtualScroll = false; | ||||||
|  |  | ||||||
|  |             var sheets = await _channelService.ExportChannelAsync(exportFilter).ConfigureAwait(false); | ||||||
|  |             var path = await _importExportService.CreateFileAsync<Device>(sheets, "Channel", false).ConfigureAwait(false); | ||||||
|  |  | ||||||
|  |             Open(path); | ||||||
|  |             return true; | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         catch | ||||||
|  |         { | ||||||
|  |  | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static void Open(string path) |     private static bool Open(string path) | ||||||
|     { |     { | ||||||
|         path = System.IO.Path.GetDirectoryName(path); // Ensure the path is absolute |         path = System.IO.Path.GetDirectoryName(path); // Ensure the path is absolute | ||||||
|  |  | ||||||
| @@ -63,25 +75,47 @@ public sealed class HybridGatewayExportService : IGatewayExportService | |||||||
|         { |         { | ||||||
|             System.Diagnostics.Process.Start("open", path); |             System.Diagnostics.Process.Start("open", path); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task OnDeviceExport(ExportFilter exportFilter) |     public async Task<bool> OnDeviceExport(ExportFilter exportFilter) | ||||||
|     { |     { | ||||||
|         exportFilter.QueryPageOptions.IsPage = false; |         try | ||||||
|         exportFilter.QueryPageOptions.IsVirtualScroll = false; |         { | ||||||
|         var sheets = await _deviceService.ExportDeviceAsync(exportFilter).ConfigureAwait(false); |  | ||||||
|         var path = await _importExportService.CreateFileAsync<Device>(sheets, "Device", false).ConfigureAwait(false); |  | ||||||
|         Open(path); |  | ||||||
|  |  | ||||||
|  |             exportFilter.QueryPageOptions.IsPage = false; | ||||||
|  |             exportFilter.QueryPageOptions.IsVirtualScroll = false; | ||||||
|  |             var sheets = await _deviceService.ExportDeviceAsync(exportFilter).ConfigureAwait(false); | ||||||
|  |             var path = await _importExportService.CreateFileAsync<Device>(sheets, "Device", false).ConfigureAwait(false); | ||||||
|  |             Open(path); | ||||||
|  |  | ||||||
|  |             return true; | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         catch | ||||||
|  |         { | ||||||
|  |  | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task OnVariableExport(ExportFilter exportFilter) |     public async Task<bool> OnVariableExport(ExportFilter exportFilter) | ||||||
|     { |     { | ||||||
|         exportFilter.QueryPageOptions.IsPage = false; |         try | ||||||
|         exportFilter.QueryPageOptions.IsVirtualScroll = false; |         { | ||||||
|         var sheets = await _variableService.ExportVariableAsync(exportFilter).ConfigureAwait(false); |  | ||||||
|         var path = await _importExportService.CreateFileAsync<Variable>(sheets, "Variable", false).ConfigureAwait(false); |             exportFilter.QueryPageOptions.IsPage = false; | ||||||
|         Open(path); |             exportFilter.QueryPageOptions.IsVirtualScroll = false; | ||||||
|  |             var sheets = await _variableService.ExportVariableAsync(exportFilter).ConfigureAwait(false); | ||||||
|  |             var path = await _importExportService.CreateFileAsync<Variable>(sheets, "Variable", false).ConfigureAwait(false); | ||||||
|  |             Open(path); | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         catch | ||||||
|  |         { | ||||||
|  |  | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ namespace ThingsGateway.Gateway.Application; | |||||||
|  |  | ||||||
| public interface IGatewayExportService | public interface IGatewayExportService | ||||||
| { | { | ||||||
|     Task OnChannelExport(ExportFilter exportFilter); |     Task<bool> OnChannelExport(ExportFilter exportFilter); | ||||||
|     Task OnDeviceExport(ExportFilter exportFilter); |     Task<bool> OnDeviceExport(ExportFilter exportFilter); | ||||||
|     Task OnVariableExport(ExportFilter exportFilter); |     Task<bool> OnVariableExport(ExportFilter exportFilter); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,6 +18,8 @@ using SqlSugar; | |||||||
|  |  | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
|  | using ThingsGateway.Authentication; | ||||||
|  |  | ||||||
| namespace ThingsGateway.Gateway.Application; | namespace ThingsGateway.Gateway.Application; | ||||||
|  |  | ||||||
| [AppStartup(-100)] | [AppStartup(-100)] | ||||||
| @@ -25,6 +27,9 @@ public class Startup : AppStartup | |||||||
| { | { | ||||||
|     public void Configure(IServiceCollection services) |     public void Configure(IServiceCollection services) | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  |         ProAuthentication.TryGetAuthorizeInfo(out var authorizeInfo); | ||||||
|  |  | ||||||
|         services.AddConfigurableOptions<ChannelThreadOptions>(); |         services.AddConfigurableOptions<ChannelThreadOptions>(); | ||||||
|         services.AddConfigurableOptions<GatewayLogOptions>(); |         services.AddConfigurableOptions<GatewayLogOptions>(); | ||||||
|         services.AddConfigurableOptions<RpcLogOptions>(); |         services.AddConfigurableOptions<RpcLogOptions>(); | ||||||
| @@ -125,8 +130,27 @@ public class Startup : AppStartup | |||||||
|         } |         } | ||||||
|         catch { } |         catch { } | ||||||
|  |  | ||||||
|  |         try | ||||||
|  |         { | ||||||
|  |             using var db = DbContext.GetDB<BackendLog>(); | ||||||
|  |             if (!db.DbMaintenance.IsAnyIndex("idx_backendlog_logtime_date")) | ||||||
|  |             { | ||||||
|  |                 var indexsql = "CREATE INDEX idx_backendlog_logtime_date ON backend_log(strftime('%Y-%m-%d', LogTime));"; | ||||||
|  |                 db.Ado.ExecuteCommand(indexsql); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         catch { } | ||||||
|  |  | ||||||
|  |         try | ||||||
|  |         { | ||||||
|  |             using var db = DbContext.GetDB<RpcLog>(); | ||||||
|  |             if (!db.DbMaintenance.IsAnyIndex("idx_rpclog_logtime_date")) | ||||||
|  |             { | ||||||
|  |                 var indexsql = "CREATE INDEX idx_rpclog_logtime_date ON rpc_log(strftime('%Y-%m-%d', LogTime));"; | ||||||
|  |                 db.Ado.ExecuteCommand(indexsql); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         catch { } | ||||||
|  |  | ||||||
|         serviceProvider.GetService<IHostApplicationLifetime>().ApplicationStarted.Register(() => |         serviceProvider.GetService<IHostApplicationLifetime>().ApplicationStarted.Register(() => | ||||||
|         { |         { | ||||||
|   | |||||||
| @@ -10,7 +10,8 @@ | |||||||
| 		<PackageReference Include="Rougamo.Fody" Version="5.0.0" /> | 		<PackageReference Include="Rougamo.Fody" Version="5.0.0" /> | ||||||
| 		<PackageReference Include="TouchSocket.Dmtp" Version="3.1.5" /> | 		<PackageReference Include="TouchSocket.Dmtp" Version="3.1.5" /> | ||||||
| 		<PackageReference Include="TouchSocket.WebApi.Swagger" Version="3.1.5" /> | 		<PackageReference Include="TouchSocket.WebApi.Swagger" Version="3.1.5" /> | ||||||
| 		<PackageReference Include="ThingsGateway.Authentication" Version="$(AuthenticationVersion)" /> | 		<!--<PackageReference Include="ThingsGateway.Authentication" Version="$(AuthenticationVersion)" />--> | ||||||
|  | 		<ProjectReference Include="..\..\PluginPro\ThingsGateway.Authentication\ThingsGateway.Authentication.csproj" /> | ||||||
|  |  | ||||||
| 	</ItemGroup> | 	</ItemGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -220,9 +220,10 @@ public partial class ChannelTable : IDisposable | |||||||
|  |  | ||||||
|     private async Task ExcelExportAsync(ITableExportContext<ChannelRuntime> tableExportContext, bool all = false) |     private async Task ExcelExportAsync(ITableExportContext<ChannelRuntime> tableExportContext, bool all = false) | ||||||
|     { |     { | ||||||
|  |         bool ret; | ||||||
|         if (all) |         if (all) | ||||||
|         { |         { | ||||||
|             await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() }); |             ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() }); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
| @@ -230,16 +231,16 @@ public partial class ChannelTable : IDisposable | |||||||
|             { |             { | ||||||
|  |  | ||||||
|                 case ChannelDevicePluginTypeEnum.PluginName: |                 case ChannelDevicePluginTypeEnum.PluginName: | ||||||
|                     await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new(), PluginName = SelectModel.PluginName }); |                     ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new(), PluginName = SelectModel.PluginName }); | ||||||
|                     break; |                     break; | ||||||
|                 case ChannelDevicePluginTypeEnum.Channel: |                 case ChannelDevicePluginTypeEnum.Channel: | ||||||
|                     await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new(), ChannelId = SelectModel.ChannelRuntime.Id }); |                     ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new(), ChannelId = SelectModel.ChannelRuntime.Id }); | ||||||
|                     break; |                     break; | ||||||
|                 case ChannelDevicePluginTypeEnum.Device: |                 case ChannelDevicePluginTypeEnum.Device: | ||||||
|                     await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new(), DeviceId = SelectModel.DeviceRuntime.Id, PluginType = SelectModel.DeviceRuntime.PluginType }); |                     ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new(), DeviceId = SelectModel.DeviceRuntime.Id, PluginType = SelectModel.DeviceRuntime.PluginType }); | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 default: | ||||||
|                     await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() }); |                     ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() }); | ||||||
|  |  | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
| @@ -247,7 +248,8 @@ public partial class ChannelTable : IDisposable | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 返回 true 时自动弹出提示框 |         // 返回 true 时自动弹出提示框 | ||||||
|         await ToastService.Default(); |         if (ret) | ||||||
|  |             await ToastService.Default(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async Task ExcelChannelAsync(ITableExportContext<ChannelRuntime> tableExportContext) |     async Task ExcelChannelAsync(ITableExportContext<ChannelRuntime> tableExportContext) | ||||||
|   | |||||||
| @@ -530,20 +530,21 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e => | |||||||
|     } |     } | ||||||
|     async Task ExportCurrentChannel(ContextMenuItem item, object value) |     async Task ExportCurrentChannel(ContextMenuItem item, object value) | ||||||
|     { |     { | ||||||
|  |         bool ret; | ||||||
|         if (value is not ChannelDeviceTreeItem channelDeviceTreeItem) return; |         if (value is not ChannelDeviceTreeItem channelDeviceTreeItem) return; | ||||||
|  |  | ||||||
|         if (channelDeviceTreeItem.TryGetChannelRuntime(out var channelRuntime)) |         if (channelDeviceTreeItem.TryGetChannelRuntime(out var channelRuntime)) | ||||||
|         { |         { | ||||||
|             await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new(), DeviceId = channelRuntime.Id }); |             ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new(), DeviceId = channelRuntime.Id }); | ||||||
|         } |         } | ||||||
|         else if (channelDeviceTreeItem.TryGetPluginName(out var pluginName)) |         else if (channelDeviceTreeItem.TryGetPluginName(out var pluginName)) | ||||||
|         { |         { | ||||||
|             //插件名称 |             //插件名称 | ||||||
|             await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new(), PluginName = pluginName }); |             ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new(), PluginName = pluginName }); | ||||||
|         } |         } | ||||||
|         else if (channelDeviceTreeItem.TryGetPluginType(out var pluginType)) |         else if (channelDeviceTreeItem.TryGetPluginType(out var pluginType)) | ||||||
|         { |         { | ||||||
|             await GatewayExportService.OnChannelExport(new ExportFilter() { QueryPageOptions = new(), PluginType = pluginType }); |             ret = await GatewayExportService.OnChannelExport(new ExportFilter() { QueryPageOptions = new(), PluginType = pluginType }); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
| @@ -551,14 +552,17 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e => | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 返回 true 时自动弹出提示框 |         // 返回 true 时自动弹出提示框 | ||||||
|         await ToastService.Default(); |         if (ret) | ||||||
|  |             await ToastService.Default(); | ||||||
|     } |     } | ||||||
|     async Task ExportAllChannel(ContextMenuItem item, object value) |     async Task ExportAllChannel(ContextMenuItem item, object value) | ||||||
|     { |     { | ||||||
|         await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() }); |         bool ret; | ||||||
|  |         ret = await GatewayExportService.OnChannelExport(new() { QueryPageOptions = new() }); | ||||||
|  |  | ||||||
|         // 返回 true 时自动弹出提示框 |         // 返回 true 时自动弹出提示框 | ||||||
|         await ToastService.Default(); |         if (ret) | ||||||
|  |             await ToastService.Default(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1065,25 +1069,26 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e => | |||||||
|  |  | ||||||
|     async Task ExportCurrentDevice(ContextMenuItem item, object value) |     async Task ExportCurrentDevice(ContextMenuItem item, object value) | ||||||
|     { |     { | ||||||
|  |         bool ret; | ||||||
|         if (value is not ChannelDeviceTreeItem channelDeviceTreeItem) return; |         if (value is not ChannelDeviceTreeItem channelDeviceTreeItem) return; | ||||||
|  |  | ||||||
|         if (channelDeviceTreeItem.TryGetDeviceRuntime(out var deviceRuntime)) |         if (channelDeviceTreeItem.TryGetDeviceRuntime(out var deviceRuntime)) | ||||||
|         { |         { | ||||||
|             await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), DeviceId = deviceRuntime.Id }); |             ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), DeviceId = deviceRuntime.Id }); | ||||||
|         } |         } | ||||||
|         else if (channelDeviceTreeItem.TryGetChannelRuntime(out var channelRuntime)) |         else if (channelDeviceTreeItem.TryGetChannelRuntime(out var channelRuntime)) | ||||||
|         { |         { | ||||||
|             await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), ChannelId = channelRuntime.Id }); |             ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), ChannelId = channelRuntime.Id }); | ||||||
|         } |         } | ||||||
|         else if (channelDeviceTreeItem.TryGetPluginName(out var pluginName)) |         else if (channelDeviceTreeItem.TryGetPluginName(out var pluginName)) | ||||||
|         { |         { | ||||||
|             //插件名称 |             //插件名称 | ||||||
|             await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), PluginName = pluginName }); |             ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), PluginName = pluginName }); | ||||||
|         } |         } | ||||||
|         else if (channelDeviceTreeItem.TryGetPluginType(out var pluginType)) |         else if (channelDeviceTreeItem.TryGetPluginType(out var pluginType)) | ||||||
|         { |         { | ||||||
|             //采集 |             //采集 | ||||||
|             await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), PluginType = pluginType }); |             ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), PluginType = pluginType }); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
| @@ -1091,14 +1096,17 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e => | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 返回 true 时自动弹出提示框 |         // 返回 true 时自动弹出提示框 | ||||||
|         await ToastService.Default(); |         if (ret) | ||||||
|  |             await ToastService.Default(); | ||||||
|     } |     } | ||||||
|     async Task ExportAllDevice(ContextMenuItem item, object value) |     async Task ExportAllDevice(ContextMenuItem item, object value) | ||||||
|     { |     { | ||||||
|         await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() }); |         bool ret; | ||||||
|  |         ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() }); | ||||||
|  |  | ||||||
|         // 返回 true 时自动弹出提示框 |         // 返回 true 时自动弹出提示框 | ||||||
|         await ToastService.Default(); |         if (ret) | ||||||
|  |             await ToastService.Default(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async Task ImportDevice(ContextMenuItem item, object value) |     async Task ImportDevice(ContextMenuItem item, object value) | ||||||
| @@ -1299,7 +1307,6 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e => | |||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 if (Disposed) return; |                 if (Disposed) return; | ||||||
|                 await Task.Delay(1000); |  | ||||||
|                 await OnClickSearch(SearchText); |                 await OnClickSearch(SearchText); | ||||||
|  |  | ||||||
|                 Value = GetValue(Value); |                 Value = GetValue(Value); | ||||||
| @@ -1311,6 +1318,7 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e => | |||||||
|             } |             } | ||||||
|             finally |             finally | ||||||
|             { |             { | ||||||
|  |                 await Task.Delay(1000); | ||||||
|                 _isExecuting = false; |                 _isExecuting = false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -221,9 +221,10 @@ public partial class DeviceTable : IDisposable | |||||||
|  |  | ||||||
|     private async Task ExcelExportAsync(ITableExportContext<DeviceRuntime> tableExportContext, bool all = false) |     private async Task ExcelExportAsync(ITableExportContext<DeviceRuntime> tableExportContext, bool all = false) | ||||||
|     { |     { | ||||||
|  |         bool ret; | ||||||
|         if (all) |         if (all) | ||||||
|         { |         { | ||||||
|             await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() }); |             ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() }); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
| @@ -231,16 +232,16 @@ public partial class DeviceTable : IDisposable | |||||||
|             { |             { | ||||||
|  |  | ||||||
|                 case ChannelDevicePluginTypeEnum.PluginName: |                 case ChannelDevicePluginTypeEnum.PluginName: | ||||||
|                     await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), PluginName = SelectModel.PluginName }); |                     ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), PluginName = SelectModel.PluginName }); | ||||||
|                     break; |                     break; | ||||||
|                 case ChannelDevicePluginTypeEnum.Channel: |                 case ChannelDevicePluginTypeEnum.Channel: | ||||||
|                     await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), ChannelId = SelectModel.ChannelRuntime.Id }); |                     ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), ChannelId = SelectModel.ChannelRuntime.Id }); | ||||||
|                     break; |                     break; | ||||||
|                 case ChannelDevicePluginTypeEnum.Device: |                 case ChannelDevicePluginTypeEnum.Device: | ||||||
|                     await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), DeviceId = SelectModel.DeviceRuntime.Id, PluginType = SelectModel.DeviceRuntime.PluginType }); |                     ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new(), DeviceId = SelectModel.DeviceRuntime.Id, PluginType = SelectModel.DeviceRuntime.PluginType }); | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 default: | ||||||
|                     await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() }); |                     ret = await GatewayExportService.OnDeviceExport(new() { QueryPageOptions = new() }); | ||||||
|  |  | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
| @@ -248,7 +249,8 @@ public partial class DeviceTable : IDisposable | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 返回 true 时自动弹出提示框 |         // 返回 true 时自动弹出提示框 | ||||||
|         await ToastService.Default(); |         if (ret) | ||||||
|  |             await ToastService.Default(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async Task ExcelDeviceAsync(ITableExportContext<DeviceRuntime> tableExportContext) |     async Task ExcelDeviceAsync(ITableExportContext<DeviceRuntime> tableExportContext) | ||||||
|   | |||||||
| @@ -268,9 +268,10 @@ public partial class VariableRuntimeInfo : IDisposable | |||||||
|  |  | ||||||
|     private async Task ExcelExportAsync(ITableExportContext<VariableRuntime> tableExportContext, bool all = false) |     private async Task ExcelExportAsync(ITableExportContext<VariableRuntime> tableExportContext, bool all = false) | ||||||
|     { |     { | ||||||
|  |         bool ret; | ||||||
|         if (all) |         if (all) | ||||||
|         { |         { | ||||||
|             await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new() }); |             ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new() }); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
| @@ -278,16 +279,16 @@ public partial class VariableRuntimeInfo : IDisposable | |||||||
|             { |             { | ||||||
|  |  | ||||||
|                 case ChannelDevicePluginTypeEnum.PluginName: |                 case ChannelDevicePluginTypeEnum.PluginName: | ||||||
|                     await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new(), PluginName = SelectModel.PluginName }); |                     ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new(), PluginName = SelectModel.PluginName }); | ||||||
|                     break; |                     break; | ||||||
|                 case ChannelDevicePluginTypeEnum.Channel: |                 case ChannelDevicePluginTypeEnum.Channel: | ||||||
|                     await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new(), ChannelId = SelectModel.ChannelRuntime.Id }); |                     ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new(), ChannelId = SelectModel.ChannelRuntime.Id }); | ||||||
|                     break; |                     break; | ||||||
|                 case ChannelDevicePluginTypeEnum.Device: |                 case ChannelDevicePluginTypeEnum.Device: | ||||||
|                     await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new(), DeviceId = SelectModel.DeviceRuntime.Id, PluginType = SelectModel.DeviceRuntime.PluginType }); |                     ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new(), DeviceId = SelectModel.DeviceRuntime.Id, PluginType = SelectModel.DeviceRuntime.PluginType }); | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 default: | ||||||
|                     await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new() }); |                     ret = await GatewayExportService.OnVariableExport(new() { QueryPageOptions = new() }); | ||||||
|  |  | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
| @@ -295,7 +296,8 @@ public partial class VariableRuntimeInfo : IDisposable | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 返回 true 时自动弹出提示框 |         // 返回 true 时自动弹出提示框 | ||||||
|         await ToastService.Default(); |         if (ret) | ||||||
|  |             await ToastService.Default(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async Task ExcelVariableAsync(ITableExportContext<VariableRuntime> tableExportContext) |     async Task ExcelVariableAsync(ITableExportContext<VariableRuntime> tableExportContext) | ||||||
|   | |||||||
| @@ -357,7 +357,7 @@ public partial class OpcUaServer : BusinessBase | |||||||
|             { |             { | ||||||
|                 StoreType = CertificateStoreType.X509Store, |                 StoreType = CertificateStoreType.X509Store, | ||||||
|                 StorePath = "CurrentUser\\UAServer_ThingsGateway", |                 StorePath = "CurrentUser\\UAServer_ThingsGateway", | ||||||
|                 SubjectName = _driverPropertys.BigTextSubjectName, |                 SubjectName = $"{_driverPropertys.BigTextSubjectName}{_driverPropertys.OpcUaStringUrl}", | ||||||
|                 //ValidationOptions = CertificateValidationOptions.SuppressHostNameInvalid, |                 //ValidationOptions = CertificateValidationOptions.SuppressHostNameInvalid, | ||||||
|             }, |             }, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -109,6 +109,7 @@ public class Startup : AppStartup | |||||||
|             // setting.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }); // 解决DateTimeOffset异常 |             // setting.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }); // 解决DateTimeOffset异常 | ||||||
|         } |         } | ||||||
|         ; |         ; | ||||||
|  |         services.AddMvcFilter<RequestAuditFilter>(); | ||||||
|  |  | ||||||
|         services.AddControllers() |         services.AddControllers() | ||||||
|             .AddNewtonsoftJson(options => SetNewtonsoftJsonSetting(options.SerializerSettings)) |             .AddNewtonsoftJson(options => SetNewtonsoftJsonSetting(options.SerializerSettings)) | ||||||
| @@ -215,7 +216,6 @@ public class Startup : AppStartup | |||||||
|         //    }); |         //    }); | ||||||
|         //}); |         //}); | ||||||
|  |  | ||||||
|         services.AddMvcFilter<RequestAuditFilter>(); |  | ||||||
|  |  | ||||||
|         //日志写入数据库配置 |         //日志写入数据库配置 | ||||||
|         services.AddDatabaseLogging<DatabaseLoggingWriter>(options => |         services.AddDatabaseLogging<DatabaseLoggingWriter>(options => | ||||||
|   | |||||||
| @@ -88,6 +88,8 @@ public class Startup : AppStartup | |||||||
|         } |         } | ||||||
|         ; |         ; | ||||||
|  |  | ||||||
|  |         services.AddMvcFilter<RequestAuditFilter>(); | ||||||
|  |  | ||||||
|         services.AddControllers() |         services.AddControllers() | ||||||
|             .AddNewtonsoftJson(options => SetNewtonsoftJsonSetting(options.SerializerSettings)) |             .AddNewtonsoftJson(options => SetNewtonsoftJsonSetting(options.SerializerSettings)) | ||||||
|             //.AddXmlSerializerFormatters() |             //.AddXmlSerializerFormatters() | ||||||
| @@ -237,7 +239,6 @@ public class Startup : AppStartup | |||||||
|         //        logContext.Set(LoggingConst.Method, httpContext.Request.Method);//请求方法 |         //        logContext.Set(LoggingConst.Method, httpContext.Request.Method);//请求方法 | ||||||
|         //    }); |         //    }); | ||||||
|         //}); |         //}); | ||||||
|         services.AddMvcFilter<RequestAuditFilter>(); |  | ||||||
|  |  | ||||||
|         //日志写入数据库配置 |         //日志写入数据库配置 | ||||||
|         services.AddDatabaseLogging<DatabaseLoggingWriter>(options => |         services.AddDatabaseLogging<DatabaseLoggingWriter>(options => | ||||||
|   | |||||||
| @@ -83,6 +83,7 @@ public class Startup : AppStartup | |||||||
|             // setting.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }); // 解决DateTimeOffset异常 |             // setting.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }); // 解决DateTimeOffset异常 | ||||||
|         } |         } | ||||||
|         ; |         ; | ||||||
|  |         services.AddMvcFilter<RequestAuditFilter>(); | ||||||
|  |  | ||||||
|         services.AddControllers() |         services.AddControllers() | ||||||
|             .AddNewtonsoftJson(options => SetNewtonsoftJsonSetting(options.SerializerSettings)) |             .AddNewtonsoftJson(options => SetNewtonsoftJsonSetting(options.SerializerSettings)) | ||||||
| @@ -233,7 +234,6 @@ public class Startup : AppStartup | |||||||
|         //        logContext.Set(LoggingConst.Method, httpContext.Request.Method);//请求方法 |         //        logContext.Set(LoggingConst.Method, httpContext.Request.Method);//请求方法 | ||||||
|         //    }); |         //    }); | ||||||
|         //}); |         //}); | ||||||
|         services.AddMvcFilter<RequestAuditFilter>(); |  | ||||||
|  |  | ||||||
|         //日志写入数据库配置 |         //日志写入数据库配置 | ||||||
|         services.AddDatabaseLogging<DatabaseLoggingWriter>(options => |         services.AddDatabaseLogging<DatabaseLoggingWriter>(options => | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <Project> | <Project> | ||||||
|   <PropertyGroup> |   <PropertyGroup> | ||||||
|     <Version>10.6.21</Version> |     <Version>10.6.26</Version> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user