From e1f0bd4c7d3a35fa9bae6de2a9c9185301b6c2ed Mon Sep 17 00:00:00 2001 From: MoYue Date: Tue, 8 Apr 2025 08:41:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UIStandardWebApi.Entity/Class1.cs | 7 + .../UIStandardWebApi.Entity.csproj | 9 + UIStandardWebApi.EntityDto/Class1.cs | 7 + .../UIStandardWebApi.EntityDto.csproj | 9 + .../AutoMapExtend/AutoMapperConfigs.cs | 23 + .../CorsExtend/CorsExtension.cs | 46 ++ .../StaticFiles/ReadStaticFilesExtensions.cs | 48 ++ .../SwaggerExtend/ApiVersions.cs | 19 + .../SwaggerExtend/SwaggerExtensions.cs | 92 +++ .../SwaggerExtend/SwaggerFileUploadFilter.cs | 56 ++ .../UIStandardWebApi.WebCore.csproj | 16 + UIStandardWebApi.sln | 43 + UIStandardWebApi/App.config | 11 + UIStandardWebApi/Common/ApiResult.cs | 36 + UIStandardWebApi/Common/AppSettingsJson.cs | 24 + UIStandardWebApi/Common/Appsettings.cs | 67 ++ UIStandardWebApi/Common/DataParsing.cs | 18 + .../Common/JwtService/JWTSwaggerGen.cs | 42 + .../Common/JwtService/JWTTokenOptions.cs | 11 + .../Common/JwtService/RSAHelper.cs | 58 ++ UIStandardWebApi/Common/MD5Encrypt.cs | 85 ++ UIStandardWebApi/Common/SocketModel/Client.cs | 194 +++++ .../Common/SocketModel/SocketListening.cs | 334 ++++++++ .../Common/SocketModel/SocketStatic.cs | 25 + .../Common/SocketModel/Sockets.cs | 107 +++ UIStandardWebApi/Common/tools.cs | 733 ++++++++++++++++++ .../Controllers/WeatherForecastController.cs | 35 + UIStandardWebApi/Program.cs | 69 ++ .../Properties/launchSettings.json | 41 + .../SqlSuggar/CustomConnectionConfig.cs | 53 ++ UIStandardWebApi/SqlSuggar/InitDatabaseExt.cs | 46 ++ UIStandardWebApi/SqlSuggar/InitSqlSugarExt.cs | 70 ++ UIStandardWebApi/UIStandardWebApi.csproj | 35 + .../RegisterExt/RegistServiceExtension.cs | 53 ++ UIStandardWebApi/WeatherForecast.cs | 13 + UIStandardWebApi/appsettings.Development.json | 8 + UIStandardWebApi/appsettings.json | 28 + 37 files changed, 2571 insertions(+) create mode 100644 UIStandardWebApi.Entity/Class1.cs create mode 100644 UIStandardWebApi.Entity/UIStandardWebApi.Entity.csproj create mode 100644 UIStandardWebApi.EntityDto/Class1.cs create mode 100644 UIStandardWebApi.EntityDto/UIStandardWebApi.EntityDto.csproj create mode 100644 UIStandardWebApi.WebCore/AutoMapExtend/AutoMapperConfigs.cs create mode 100644 UIStandardWebApi.WebCore/CorsExtend/CorsExtension.cs create mode 100644 UIStandardWebApi.WebCore/StaticFiles/ReadStaticFilesExtensions.cs create mode 100644 UIStandardWebApi.WebCore/SwaggerExtend/ApiVersions.cs create mode 100644 UIStandardWebApi.WebCore/SwaggerExtend/SwaggerExtensions.cs create mode 100644 UIStandardWebApi.WebCore/SwaggerExtend/SwaggerFileUploadFilter.cs create mode 100644 UIStandardWebApi.WebCore/UIStandardWebApi.WebCore.csproj create mode 100644 UIStandardWebApi.sln create mode 100644 UIStandardWebApi/App.config create mode 100644 UIStandardWebApi/Common/ApiResult.cs create mode 100644 UIStandardWebApi/Common/AppSettingsJson.cs create mode 100644 UIStandardWebApi/Common/Appsettings.cs create mode 100644 UIStandardWebApi/Common/DataParsing.cs create mode 100644 UIStandardWebApi/Common/JwtService/JWTSwaggerGen.cs create mode 100644 UIStandardWebApi/Common/JwtService/JWTTokenOptions.cs create mode 100644 UIStandardWebApi/Common/JwtService/RSAHelper.cs create mode 100644 UIStandardWebApi/Common/MD5Encrypt.cs create mode 100644 UIStandardWebApi/Common/SocketModel/Client.cs create mode 100644 UIStandardWebApi/Common/SocketModel/SocketListening.cs create mode 100644 UIStandardWebApi/Common/SocketModel/SocketStatic.cs create mode 100644 UIStandardWebApi/Common/SocketModel/Sockets.cs create mode 100644 UIStandardWebApi/Common/tools.cs create mode 100644 UIStandardWebApi/Controllers/WeatherForecastController.cs create mode 100644 UIStandardWebApi/Program.cs create mode 100644 UIStandardWebApi/Properties/launchSettings.json create mode 100644 UIStandardWebApi/SqlSuggar/CustomConnectionConfig.cs create mode 100644 UIStandardWebApi/SqlSuggar/InitDatabaseExt.cs create mode 100644 UIStandardWebApi/SqlSuggar/InitSqlSugarExt.cs create mode 100644 UIStandardWebApi/UIStandardWebApi.csproj create mode 100644 UIStandardWebApi/Utility/RegisterExt/RegistServiceExtension.cs create mode 100644 UIStandardWebApi/WeatherForecast.cs create mode 100644 UIStandardWebApi/appsettings.Development.json create mode 100644 UIStandardWebApi/appsettings.json diff --git a/UIStandardWebApi.Entity/Class1.cs b/UIStandardWebApi.Entity/Class1.cs new file mode 100644 index 0000000..eab2e5f --- /dev/null +++ b/UIStandardWebApi.Entity/Class1.cs @@ -0,0 +1,7 @@ +namespace UIStandardWebApi.Entity +{ + public class Class1 + { + + } +} diff --git a/UIStandardWebApi.Entity/UIStandardWebApi.Entity.csproj b/UIStandardWebApi.Entity/UIStandardWebApi.Entity.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/UIStandardWebApi.Entity/UIStandardWebApi.Entity.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/UIStandardWebApi.EntityDto/Class1.cs b/UIStandardWebApi.EntityDto/Class1.cs new file mode 100644 index 0000000..c6413a9 --- /dev/null +++ b/UIStandardWebApi.EntityDto/Class1.cs @@ -0,0 +1,7 @@ +namespace UIStandardWebApi.EntityDto +{ + public class Class1 + { + + } +} diff --git a/UIStandardWebApi.EntityDto/UIStandardWebApi.EntityDto.csproj b/UIStandardWebApi.EntityDto/UIStandardWebApi.EntityDto.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/UIStandardWebApi.EntityDto/UIStandardWebApi.EntityDto.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/UIStandardWebApi.WebCore/AutoMapExtend/AutoMapperConfigs.cs b/UIStandardWebApi.WebCore/AutoMapExtend/AutoMapperConfigs.cs new file mode 100644 index 0000000..13d6a59 --- /dev/null +++ b/UIStandardWebApi.WebCore/AutoMapExtend/AutoMapperConfigs.cs @@ -0,0 +1,23 @@ +using AutoMapper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UIStandardWebApi.WebCore.AutoMapExtend +{ + /// + /// Dto映射配置 + /// + public class AutoMapperConfigs : Profile + { + /// + /// 配置映射 + /// + public AutoMapperConfigs() + { + + } + } +} diff --git a/UIStandardWebApi.WebCore/CorsExtend/CorsExtension.cs b/UIStandardWebApi.WebCore/CorsExtend/CorsExtension.cs new file mode 100644 index 0000000..3ff6c34 --- /dev/null +++ b/UIStandardWebApi.WebCore/CorsExtend/CorsExtension.cs @@ -0,0 +1,46 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UIStandardWebApi.WebCore.CorsExtend +{ + /// + /// 跨域 + /// + public static class CorsExtension + { + + /// + /// 配置跨域策略 + /// + /// + public static void AddCorsExt(this IServiceCollection services) + { + services.AddCors(options => + { + // allcore: 策略名称 + options.AddPolicy("allcors", corsBuilder => + { + corsBuilder.AllowAnyHeader() + .AllowAnyOrigin() + .AllowAnyMethod(); + }); + }); + } + + /// + /// 配置跨域策略生效 + /// + /// + public static void UseCorsExt(this WebApplication app) + { + app.UseCors("allcors"); + } + + + } +} diff --git a/UIStandardWebApi.WebCore/StaticFiles/ReadStaticFilesExtensions.cs b/UIStandardWebApi.WebCore/StaticFiles/ReadStaticFilesExtensions.cs new file mode 100644 index 0000000..ec408d0 --- /dev/null +++ b/UIStandardWebApi.WebCore/StaticFiles/ReadStaticFilesExtensions.cs @@ -0,0 +1,48 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.FileProviders; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UIStandardWebApi.WebCore.StaticFiles +{ + /// + /// 读取图片信息 + /// + public static class ReadStaticFilesExtensions + { + /// + /// 读取图片信息 + /// + /// + /// + public static void ReadStaticFilesExt(this IApplicationBuilder app, string fileAddress) + { + if (string.IsNullOrWhiteSpace(fileAddress)) + { + throw new Exception("配置保存图片的地址不存在"); + } + if (!Directory.Exists(fileAddress)) + { + Directory.CreateDirectory(fileAddress); + } + var fileProvider = new PhysicalFileProvider(fileAddress); + var requestPath = $"/static"; + + app.UseStaticFiles(new StaticFileOptions() + { + FileProvider = fileProvider, + RequestPath = requestPath + }); + + //展示文件列表 + app.UseDirectoryBrowser(new DirectoryBrowserOptions + { + FileProvider = fileProvider, + RequestPath = requestPath + }); + } + } +} diff --git a/UIStandardWebApi.WebCore/SwaggerExtend/ApiVersions.cs b/UIStandardWebApi.WebCore/SwaggerExtend/ApiVersions.cs new file mode 100644 index 0000000..e68f634 --- /dev/null +++ b/UIStandardWebApi.WebCore/SwaggerExtend/ApiVersions.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UIStandardWebApi.WebCore.SwaggerExtend +{ + /// + /// Api版本枚举 + /// + public enum ApiVersions + { + V1, + V2, + V3, + V4 + } +} diff --git a/UIStandardWebApi.WebCore/SwaggerExtend/SwaggerExtensions.cs b/UIStandardWebApi.WebCore/SwaggerExtend/SwaggerExtensions.cs new file mode 100644 index 0000000..14dac12 --- /dev/null +++ b/UIStandardWebApi.WebCore/SwaggerExtend/SwaggerExtensions.cs @@ -0,0 +1,92 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UIStandardWebApi.WebCore.SwaggerExtend +{ + public static class SwaggerExtensions + { + /// + /// 配置Swagger的配置 + /// + /// + /// + /// + public static void AddSwaggerExt(this IServiceCollection service, string docName, string docDescription) + { + service.AddEndpointsApiExplorer(); + service.AddSwaggerGen(option => + { + foreach (var version in typeof(ApiVersions).GetEnumNames()) + { + option.SwaggerDoc(version, new OpenApiInfo() + { + Title = !string.IsNullOrWhiteSpace(docName) ? docName : $"Api文档", + Version = version, + Description = !string.IsNullOrWhiteSpace(docDescription) ? docDescription : $"Api版本v1" + }); + } + //option.OperationFilter(); + + // xml文档绝对路径 + var file = Path.Combine(AppContext.BaseDirectory, $"{AppDomain.CurrentDomain.FriendlyName}.xml"); + // true : 显示控制器层注释 + option.IncludeXmlComments(file, true); + // 对action的名称进行排序,如果有多个,就可以看见效果了。 + option.OrderActionsBy(o => o.RelativePath); + + //#region 支持jwt token授权 + //{ + // //添加安全定义--配置支持token授权机制 + // option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + // { + // Description = "请输入token,格式为 Bearer xxxxxxxx(注意中间必须有空格)", + // Name = "Authorization", + // In = ParameterLocation.Header, + // Type = SecuritySchemeType.ApiKey, + // BearerFormat = "JWT", + // Scheme = "Bearer" + // }); + // //添加安全要求 + // option.AddSecurityRequirement(new OpenApiSecurityRequirement + // { + // { + // new OpenApiSecurityScheme + // { + // Reference =new OpenApiReference() + // { + // Type = ReferenceType.SecurityScheme, + // Id ="Bearer" + // } + // }, + // new string[]{ } + // } + // }); + //} + //#endregion + }); + } + + + /// + /// 使用Swagger中间件 + /// + /// + public static void UseSwaggerExt(this WebApplication app, string docName) + { + app.UseSwagger(); + app.UseSwaggerUI(option => + { + foreach (string version in typeof(ApiVersions).GetEnumNames()) + { + option.SwaggerEndpoint($"/swagger/{version}/swagger.json", string.IsNullOrWhiteSpace(docName) ? docName : $"软件标准化Api文档【{version}】版本"); + } + }); + } + } +} diff --git a/UIStandardWebApi.WebCore/SwaggerExtend/SwaggerFileUploadFilter.cs b/UIStandardWebApi.WebCore/SwaggerExtend/SwaggerFileUploadFilter.cs new file mode 100644 index 0000000..d3772ce --- /dev/null +++ b/UIStandardWebApi.WebCore/SwaggerExtend/SwaggerFileUploadFilter.cs @@ -0,0 +1,56 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UIStandardWebApi.WebCore.SwaggerExtend +{ + public class SwaggerFileUploadFilter : IOperationFilter + { + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + const string FileUploadContentType = "multipart/form-data"; + if (operation.RequestBody == null || + !operation.RequestBody.Content.Any(x => + x.Key.Equals(FileUploadContentType, StringComparison.InvariantCultureIgnoreCase))) + { + return; + } + + if (context.ApiDescription.ParameterDescriptions[0].Type == typeof(HttpRequest)) + { + operation.RequestBody = new OpenApiRequestBody + { + Description = "文件上传", + Content = new Dictionary + { + { + FileUploadContentType, new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Type = "object", + Required = new HashSet{ "file" }, + Properties = new Dictionary + { + { + "file", new OpenApiSchema() + { + Type = "string", + Format = "binary" + } + } + } + } + } + } + } + }; + } + } + } +} diff --git a/UIStandardWebApi.WebCore/UIStandardWebApi.WebCore.csproj b/UIStandardWebApi.WebCore/UIStandardWebApi.WebCore.csproj new file mode 100644 index 0000000..92b8f09 --- /dev/null +++ b/UIStandardWebApi.WebCore/UIStandardWebApi.WebCore.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + + + + + + + + + + diff --git a/UIStandardWebApi.sln b/UIStandardWebApi.sln new file mode 100644 index 0000000..5eb7733 --- /dev/null +++ b/UIStandardWebApi.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35919.96 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UIStandardWebApi", "UIStandardWebApi\UIStandardWebApi.csproj", "{1A831663-E659-4584-B908-5D0C358E8887}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UIStandardWebApi.WebCore", "UIStandardWebApi.WebCore\UIStandardWebApi.WebCore.csproj", "{F926756D-DACD-43EA-8C56-E220E3C02820}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UIStandardWebApi.Entity", "UIStandardWebApi.Entity\UIStandardWebApi.Entity.csproj", "{E5D266AE-65A8-401C-8F6F-6ADB10BEB1C6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UIStandardWebApi.EntityDto", "UIStandardWebApi.EntityDto\UIStandardWebApi.EntityDto.csproj", "{F8D34A35-F030-48FF-927A-F370F803D46A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1A831663-E659-4584-B908-5D0C358E8887}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A831663-E659-4584-B908-5D0C358E8887}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A831663-E659-4584-B908-5D0C358E8887}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A831663-E659-4584-B908-5D0C358E8887}.Release|Any CPU.Build.0 = Release|Any CPU + {F926756D-DACD-43EA-8C56-E220E3C02820}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F926756D-DACD-43EA-8C56-E220E3C02820}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F926756D-DACD-43EA-8C56-E220E3C02820}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F926756D-DACD-43EA-8C56-E220E3C02820}.Release|Any CPU.Build.0 = Release|Any CPU + {E5D266AE-65A8-401C-8F6F-6ADB10BEB1C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5D266AE-65A8-401C-8F6F-6ADB10BEB1C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5D266AE-65A8-401C-8F6F-6ADB10BEB1C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5D266AE-65A8-401C-8F6F-6ADB10BEB1C6}.Release|Any CPU.Build.0 = Release|Any CPU + {F8D34A35-F030-48FF-927A-F370F803D46A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8D34A35-F030-48FF-927A-F370F803D46A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8D34A35-F030-48FF-927A-F370F803D46A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8D34A35-F030-48FF-927A-F370F803D46A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AE68BCD9-7F48-4EF2-8FB7-A612E7A4C9B9} + EndGlobalSection +EndGlobal diff --git a/UIStandardWebApi/App.config b/UIStandardWebApi/App.config new file mode 100644 index 0000000..d796617 --- /dev/null +++ b/UIStandardWebApi/App.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/UIStandardWebApi/Common/ApiResult.cs b/UIStandardWebApi/Common/ApiResult.cs new file mode 100644 index 0000000..7be6173 --- /dev/null +++ b/UIStandardWebApi/Common/ApiResult.cs @@ -0,0 +1,36 @@ +namespace UIStandardWebApi.Common +{ + /// + /// api + /// + public class ApiResult + { + /// + /// 是否正常返回 + /// + public bool Success { get; set; } + + /// + /// 处理消息 + /// + public string? Message { get; set; } + } + + + /// + /// api 数据结果 + /// + /// + public class ApiDataResult : ApiResult + { + /// + /// 结果集 + /// + public T? Data { get; set; } + + /// + /// 冗余结果 + /// + public object? OValue { get; set; } + } +} diff --git a/UIStandardWebApi/Common/AppSettingsJson.cs b/UIStandardWebApi/Common/AppSettingsJson.cs new file mode 100644 index 0000000..aa1471b --- /dev/null +++ b/UIStandardWebApi/Common/AppSettingsJson.cs @@ -0,0 +1,24 @@ +namespace UIStandardWebApi.Common +{ + /// + /// 读取AppSettings.Json文件内容 + /// + public static class AppSettingsJson + { + public static string ApplicationExeDirectory() + { + var location = System.Reflection.Assembly.GetExecutingAssembly().Location; + var appRoot = Path.GetDirectoryName(location); + return appRoot; + } + public static IConfigurationRoot GetAppSettings() + { + string applicationExeDirectory = ApplicationExeDirectory(); + var builder = new ConfigurationBuilder() + .SetBasePath(applicationExeDirectory) + .AddJsonFile("appsettings.json"); + return builder.Build(); + } + + } +} diff --git a/UIStandardWebApi/Common/Appsettings.cs b/UIStandardWebApi/Common/Appsettings.cs new file mode 100644 index 0000000..f16b0c8 --- /dev/null +++ b/UIStandardWebApi/Common/Appsettings.cs @@ -0,0 +1,67 @@ +using Microsoft.Extensions.Configuration.Json; + +namespace UIStandardWebApi.Common +{ + /// + /// appsettings.json操作类 + /// + public class Appsettings + { + static IConfiguration Configuration { get; set; } + static string contentPath { get; set; } + + public Appsettings(string contentPath) + { + string Path = "appsettings.json"; + + //如果你把配置文件 是 根据环境变量来分开了,可以这样写 + //Path = $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json"; + + Configuration = new ConfigurationBuilder() + .SetBasePath(contentPath) + .Add(new JsonConfigurationSource { Path = Path, Optional = false, ReloadOnChange = true })//这样的话,可以直接读目录里的json文件,而不是 bin 文件夹下的,所以不用修改复制属性 + .Build(); + } + + public Appsettings(IConfiguration configuration) + { + Configuration = configuration; + } + + /// + /// 封装要操作的字符 + /// + /// 节点配置 + /// + public static string app(params string[] sections) + { + try + { + + if (sections.Any()) + { + return Configuration[string.Join(":", sections)]; + } + } + catch (Exception) + { + + } + + return ""; + } + + /// + /// 递归获取配置信息数组 + /// + /// + /// + /// + public static List app(params string[] sections) + { + List list = new List(); + Configuration.Bind(string.Join(":", sections), list); + return list; + } + } +} diff --git a/UIStandardWebApi/Common/DataParsing.cs b/UIStandardWebApi/Common/DataParsing.cs new file mode 100644 index 0000000..e9a3405 --- /dev/null +++ b/UIStandardWebApi/Common/DataParsing.cs @@ -0,0 +1,18 @@ +namespace UIStandardWebApi.Common +{ + + /// + /// 数据解析 + /// + public class DataParsing + { + /// + /// 数据解析 + /// + /// + public void ParsingData(List byteList) + { + + } + } +} diff --git a/UIStandardWebApi/Common/JwtService/JWTSwaggerGen.cs b/UIStandardWebApi/Common/JwtService/JWTSwaggerGen.cs new file mode 100644 index 0000000..f31b5fc --- /dev/null +++ b/UIStandardWebApi/Common/JwtService/JWTSwaggerGen.cs @@ -0,0 +1,42 @@ +using Microsoft.OpenApi.Models; + +namespace UIStandardWebApi.Common.JwtService +{ + /// + /// JWT鉴权授权扩展 + /// + public static class JWTSwaggerGen + { + /// + /// 解决Swagger右上角的Authorize权限按钮不显示 + /// + /// + public static void AddJWTSwaggerGen(this WebApplicationBuilder builder) + { + builder.Services.AddSwaggerGen(c => + { + var security = new OpenApiSecurityRequirement() + { + { new OpenApiSecurityScheme + { + Reference = new OpenApiReference() + { + Id = "Bearer", + Type = ReferenceType.SecurityScheme + } + }, Array.Empty() } + }; + c.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", + Name = "Authorization",//jwt默认的参数名称 + In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中) + Type = SecuritySchemeType.ApiKey, + BearerFormat = "JWT", + Scheme = "Bearer" + }); + }); + } + } +} diff --git a/UIStandardWebApi/Common/JwtService/JWTTokenOptions.cs b/UIStandardWebApi/Common/JwtService/JWTTokenOptions.cs new file mode 100644 index 0000000..313b7e1 --- /dev/null +++ b/UIStandardWebApi/Common/JwtService/JWTTokenOptions.cs @@ -0,0 +1,11 @@ +namespace UIStandardWebApi.Common.JwtService +{ + public class JWTTokenOptions + { + public string? Audience { get; set; } + + public string? SecurityKey { get; set; } + + public string? Issuer { get; set; } + } +} diff --git a/UIStandardWebApi/Common/JwtService/RSAHelper.cs b/UIStandardWebApi/Common/JwtService/RSAHelper.cs new file mode 100644 index 0000000..98334b7 --- /dev/null +++ b/UIStandardWebApi/Common/JwtService/RSAHelper.cs @@ -0,0 +1,58 @@ +using Newtonsoft.Json; +using System.Security.Cryptography; + +namespace UIStandardWebApi.Common.JwtService +{ + public class RSAHelper + { + /// + /// 从本地文件中读取用来签发 Token 的 RSA Key + /// + /// 存放密钥的文件夹路径 + /// + /// + /// + public static bool TryGetKeyParameters(string filePath, bool withPrivate, out RSAParameters keyParameters) + { + string filename = withPrivate ? "key.json" : "key.public.json"; + string fileTotalPath = Path.Combine(filePath, filename); + keyParameters = default; + if (!File.Exists(fileTotalPath)) + { + return false; + } + else + { + keyParameters = JsonConvert.DeserializeObject(File.ReadAllText(fileTotalPath)); + return true; + } + } + + + /// + /// 生成并保存 RSA 公钥与私钥 + /// + /// 存放密钥的文件夹路径 + /// + public static RSAParameters GenerateAndSaveKey(string filePath, bool withPrivate = true) + { + RSAParameters publicKeys, privateKeys; + using (var rsa = new RSACryptoServiceProvider(2048))//即时生成 + { + try + { + privateKeys = rsa.ExportParameters(true); + publicKeys = rsa.ExportParameters(false); + } + finally + { + rsa.PersistKeyInCsp = false; + } + } + File.WriteAllText(Path.Combine(filePath, "key.json"), JsonConvert.SerializeObject(privateKeys)); + + File.WriteAllText(Path.Combine(filePath, "key.public.json"), JsonConvert.SerializeObject(publicKeys)); + return withPrivate ? privateKeys : publicKeys; + } + } +} diff --git a/UIStandardWebApi/Common/MD5Encrypt.cs b/UIStandardWebApi/Common/MD5Encrypt.cs new file mode 100644 index 0000000..2248e4d --- /dev/null +++ b/UIStandardWebApi/Common/MD5Encrypt.cs @@ -0,0 +1,85 @@ +using System.Security.Cryptography; +using System.Text; + +namespace UIStandardWebApi.Common +{ + /// + /// MD5加密 + /// + public class MD5Encrypt + { + #region MD5 + /// + /// MD5加密,和动网上的16/32位MD5加密结果相同, + /// 使用的UTF8编码 + /// + /// 待加密字串 + /// 16或32值之一,其它则采用.net默认MD5加密算法 + /// 加密后的字串 + public static string Encrypt(string source, int length = 32)//默认参数 + { + if (string.IsNullOrEmpty(source)) return string.Empty; + HashAlgorithm provider = CryptoConfig.CreateFromName("MD5") as HashAlgorithm; + byte[] bytes = Encoding.UTF8.GetBytes(source);//这里需要区别编码的 + byte[] hashValue = provider.ComputeHash(bytes); + StringBuilder sb = new StringBuilder(); + switch (length) + { + case 16://16位密文是32位密文的9到24位字符 + for (int i = 4; i < 12; i++) + { + sb.Append(hashValue[i].ToString("x2")); + } + break; + case 32: + for (int i = 0; i < 16; i++) + { + sb.Append(hashValue[i].ToString("x2")); + } + break; + default: + for (int i = 0; i < hashValue.Length; i++) + { + sb.Append(hashValue[i].ToString("x2")); + } + break; + } + return sb.ToString(); + } + #endregion MD5 + + #region MD5摘要 + /// + /// 获取文件的MD5摘要 + /// + /// + /// + public static string AbstractFile(string fileName) + { + using (FileStream file = new FileStream(fileName, FileMode.Open)) + { + return AbstractFile(file); + } + } + + + /// + /// 根据stream获取文件摘要 + /// + /// + /// + public static string AbstractFile(Stream stream) + { + MD5 md5 = new MD5CryptoServiceProvider(); + byte[] retVal = md5.ComputeHash(stream); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < retVal.Length; i++) + { + sb.Append(retVal[i].ToString("x2")); + } + return sb.ToString(); + } + #endregion + } +} diff --git a/UIStandardWebApi/Common/SocketModel/Client.cs b/UIStandardWebApi/Common/SocketModel/Client.cs new file mode 100644 index 0000000..0ee6c16 --- /dev/null +++ b/UIStandardWebApi/Common/SocketModel/Client.cs @@ -0,0 +1,194 @@ +using System.Net.Sockets; +using System.Net; +using static UIStandardWebApi.Common.SocketModel.Sockets; + +namespace UIStandardWebApi.Common.SocketModel +{ + /// + /// 客户端通信类 + /// + public class Client : SocketObject + { + public PushSockets pushSockets; + + bool IsClose = false; + /// + /// 当前管理对象 + /// + Sockets sk; + /// + /// 客户端 + /// + TcpClient client; + /// + /// 当前连接服务端地址 + /// + IPAddress Ipaddress; + /// + /// 当前连接服务端端口号 + /// + int Port; + /// + /// 服务端IP+端口 + /// + IPEndPoint ip; + /// + /// 发送与接收使用的流 + /// + NetworkStream nStream; + + /// + /// 初始化Socket + /// + /// + /// + public override void InitSocket(IPAddress ipaddress, int port) + { + Ipaddress = ipaddress; + Port = port; + ip = new IPEndPoint(Ipaddress, Port); + client = new TcpClient(); + } + /// + /// 初始化Socket + /// + /// ipd地址 + /// 端口 + public override void InitSocket(string ipaddress, int port) + { + Ipaddress = IPAddress.Parse(ipaddress); + Port = port; + ip = new IPEndPoint(Ipaddress, Port); + client = new TcpClient(); + } + /// + /// 重写Start方法,其实就是连接服务端 + /// + public override void Start() + { + Connect(); + } + /// + /// 连接 + /// + public bool Connect() + { + try + { + client.Connect(ip); + } + catch (Exception) + { + return false; + } + nStream = new NetworkStream(client.Client, true); + sk = new Sockets(ip, client, nStream); + sk.nStream.BeginRead(sk.RecBuffer, 0, sk.RecBuffer.Length, new AsyncCallback(EndReader), sk); + return true; + } + /// + /// 读取 + /// + private void EndReader(IAsyncResult ir) + { + Sockets s = ir.AsyncState as Sockets; + try + { + if (s != null) + { + if (IsClose && client == null) + { + sk.nStream.Close(); + sk.nStream.Dispose(); + return; + } + s.Offset = s.nStream.EndRead(ir); + if (pushSockets != null) + pushSockets.Invoke(s);//推送至UI + sk.nStream.BeginRead(sk.RecBuffer, 0, sk.RecBuffer.Length, new AsyncCallback(EndReader), sk); + } + } + catch (Exception skex) + { + Sockets sks = s; + sks.ex = skex; + sks.ClientDispose = true; + if (pushSockets != null) + pushSockets.Invoke(sks);//推送至UI + } + } + /// + /// 停止 + /// + public override void Stop() + { + Sockets sks = new Sockets(); + try + { + if (client != null) + { + client.Client.Shutdown(SocketShutdown.Both); + Thread.Sleep(10); + client.Close(); + IsClose = true; + client = null; + } + else + { + sks.ex = new Exception("客户端没有初始化.!"); + } + if (pushSockets != null) + pushSockets.Invoke(sks);//推送至UI + } + catch (Exception ex) + { + sks.ex = ex; + } + } + /// + /// 发送消息 + /// + public void SendData(byte[] SendData) + { + try + { + if (client == null || !client.Connected) + { + Sockets sks = new Sockets(); + sks.ex = new Exception("客户端无连接.."); + sks.ClientDispose = true; + if (pushSockets != null) + pushSockets.Invoke(sks);//推送至UI + } + if (client.Connected) //如果连接则发送 + { + if (nStream == null) + { + nStream = client.GetStream(); + } + nStream.Write(SendData, 0, SendData.Length); + } + } + catch (Exception skex) + { + Sockets sks = new Sockets(); + sks.ex = skex; + sks.ClientDispose = true; + if (pushSockets != null) + pushSockets.Invoke(sks);//推送至UI + } + } + + public bool Is_Connected() + { + return client.Connected; + } + + public bool IsOnline() + { + if (client == null) + return false; + return !(client.Client.Poll(1000, SelectMode.SelectRead) && client.Client.Available == 0 || !client.Client.Connected); + } + } +} diff --git a/UIStandardWebApi/Common/SocketModel/SocketListening.cs b/UIStandardWebApi/Common/SocketModel/SocketListening.cs new file mode 100644 index 0000000..be8eec7 --- /dev/null +++ b/UIStandardWebApi/Common/SocketModel/SocketListening.cs @@ -0,0 +1,334 @@ +using System.Net.Sockets; +using System.Net; +using System.Runtime.InteropServices; +using Socket = System.Net.Sockets.Socket; + +namespace UIStandardWebApi.Common.SocketModel +{ + /// + /// 开启服务器监听 便于Client连接 + /// + public class SocketListening + { + //通信定义 + private static Socket socket = null; + + /// + /// 创建负责监听的线程; + /// + Thread? trdConnect; + /// + /// Socket连接状态 + /// + public static bool g_Receive; + + //获取当前程序运行路径 + private string Save_Path = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"通信连接记录\"; + + /// + /// 定义公共Ip + /// + public static string? g_ip; + + + + /// + /// 键值对集合:键为IP地址,值为Socket + /// 将远程连接的客户端的IP地址和端口号存入集合中 + /// + public static Dictionary g_dicSocket = new Dictionary(); + + //监听客户端连接的标志 + private static bool Flag_Listen = true; + + //定义为任意IP + IPAddress ip = IPAddress.Any; + + //定义端口号 8899 + private int port = 8899; + + /// + /// 服务端开启即等待连接 + /// + public bool OpenServer(int port) + { + try + { + Flag_Listen = true; + + //在服务器端创建一个负责IP地址和端口号的Socket + socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + tools.AddLgoToTXT("通信连接记录信息.txt", Save_Path + DateTime.Now.ToString("yyyy_MM_dd") + @"\", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 创建端口号连接" + "\r\n"); + //创建端口号对象 + IPEndPoint point = new IPEndPoint(ip, port); + + try + { + //监听 + socket.Bind(point); + } + catch (Exception) + { + return false; + } + // 设置监听队列的长度; + socket.Listen(10); + // 创建负责监听的线程; + trdConnect = new Thread(ListenConnect); + trdConnect.IsBackground = true; + trdConnect.Start(); + + return true; + } + catch (Exception ex) + { + tools.AddLgoToTXT("通信连接异常记录信息.txt", Save_Path + DateTime.Now.ToString("yyyy_MM_dd") + @"\", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + ex.Message + "\r\n"); + return false; + } + } + + /// + /// 监听连接 + /// + /// + private void ListenConnect() + { + while (Flag_Listen) + { + try + { + //负责和客户端通信的Socket + SocketStatic.g_socketSend = socket.Accept(); + + SocketStatic.g_socketSend.IOControl(IOControlCode.KeepAliveValues, GetKeepAliveData(), null); + SocketStatic.g_socketSend.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); + + g_ip = SocketStatic.g_socketSend.RemoteEndPoint.ToString(); + + if (!g_dicSocket.ContainsKey(g_ip)) + { + //将远程连接的客户端的IP地址和端口号存入集合中 + g_dicSocket.Add(g_ip, SocketStatic.g_socketSend); + g_Receive = true; + + tools.AddLgoToTXT("通信连接记录信息.txt", Save_Path + DateTime.Now.ToString("yyyy_MM_dd") + @"\", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 新增的远程连接:" + g_ip + "\r\n"); + + + List list = new List + { + g_ip, + SocketStatic.g_socketSend + }; + + SocketStatic.IsConnection = true; + + //开启一个新线程不停接收客户端的数据 + Thread trdReceive = new Thread(DataReceive); + trdReceive.IsBackground = true; + trdReceive.Start(list); + } + } + catch (Exception ex) + { + tools.AddLgoToTXT("通信连接异常记录信息.txt", Save_Path + DateTime.Now.ToString("yyyy_MM_dd") + @"\", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + ex.Message + "\r\n"); + } + + } + + } + + private byte[] GetKeepAliveData() + { + uint dummy = 0; + byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3]; + BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0); + BitConverter.GetBytes((uint)3000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));//keep-alive间隔 + BitConverter.GetBytes((uint)500).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);// 尝试间隔 + return inOptionValues; + } + + /// + /// 数据接收 + /// + /// + private void DataReceive(object sokConnectionparn) + { + List list = sokConnectionparn as List; + MySession tcpClient = sokConnectionparn as MySession; + string g_ipNew = (string)list[0]; + Socket socketSend = (Socket)list[1]; + + + bool flag = true; + while (flag) + { + try + { + //客户端连接成功后,服务器接收客户端发来的消息 + byte[] arrMsgRec = new byte[1024 * 1024 * 2]; + // 将接受到的数据存入到输入 arrMsgRec中; + int length = -1; + + //判断ip是否被移除 + if (!g_dicSocket.ContainsKey(g_ipNew)) + { + g_Receive = false; + flag = false; + continue; + } + + //判断是否连接 + if (socketSend.Poll(1000, SelectMode.SelectRead) && socketSend.Available == 0) + { + //连接断开 + socketSend.Close(); + if (g_dicSocket.ContainsKey(g_ipNew)) + { + g_dicSocket.Remove(g_ipNew); + } + tools.AddLgoToTXT("通信连接记录信息.txt", Save_Path + DateTime.Now.ToString("yyyy_MM_dd") + @"\", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " ReceiveError移除远程连接:" + g_ipNew + "\r\n"); + + if (g_ipNew == g_ip) + { + g_Receive = false; + SocketStatic.g_socketSend = null; + } + else + { + g_Receive = true; + } + flag = false; + SocketStatic.IsConnection = false; + continue; + } + else + { + try + { + //实际接收到的有效字节数,,并返回数据的长度 + length = socketSend.Receive(arrMsgRec); + } + catch (Exception ex) + { + tools.AddLgoToTXT("通信连接异常记录信息.txt", Save_Path + DateTime.Now.ToString("yyyy_MM_dd") + @"\", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 断开连接时产生的信息:" + ex.Message + "\r\n"); + flag = false; + tcpClient = null; + socketSend = null; + CloseServer();//关闭服务器 + OpenServer(8899); + break; + } + } + byte[] buf = new byte[length]; + Array.Copy(arrMsgRec, buf, length); + + SocketStatic.dataParsing.ParsingData(new List(buf)); + + } + catch (Exception) + { + + throw; + } + + } + } + + + public class MySession + { + public Socket TcpSocket;//socket对象 + public List m_Buffer = new List();//数据缓存区 + + public MySession() + { + + } + + /// + /// 发送数据 + /// + /// + public void Send(byte[] buf) + { + if (buf != null) + { + try + { + TcpSocket.Send(buf); + } + catch (Exception err) + { + Console.WriteLine("发送指令失败,当前设备未连接"); + } + + } + } + /// + /// 获取连接的ip + /// + /// + public string GetIp() + { + IPEndPoint clientipe = (IPEndPoint)TcpSocket.RemoteEndPoint; + string _ip = clientipe.Address.ToString(); + return _ip; + } + /// + /// 关闭连接 + /// + public void Close() + { + TcpSocket.Shutdown(SocketShutdown.Both); + } + /// + /// 提取正确数据包 + /// + public byte[] GetBuffer(int startIndex, int size) + { + byte[] buf = new byte[size]; + m_Buffer.CopyTo(startIndex, buf, 0, size); + m_Buffer.RemoveRange(0, startIndex + size); + return buf; + } + + /// + /// 添加队列数据 + /// + /// + public void AddQueue(byte[] buffer) + { + m_Buffer.AddRange(buffer); + } + /// + /// 清除缓存 + /// + public void ClearQueue() + { + m_Buffer.Clear(); + } + } + + + /// + /// 关闭服务 + /// + public static void CloseServer() + { + lock (g_dicSocket) + { + foreach (var item in g_dicSocket) + { + item.Value.Close();//关闭每一个连接 + } + g_dicSocket.Clear(); + } + SocketStatic.IsConnection = false; + Flag_Listen = true; + if (socket != null) + socket.Close(); + + } + } +} diff --git a/UIStandardWebApi/Common/SocketModel/SocketStatic.cs b/UIStandardWebApi/Common/SocketModel/SocketStatic.cs new file mode 100644 index 0000000..8517cdb --- /dev/null +++ b/UIStandardWebApi/Common/SocketModel/SocketStatic.cs @@ -0,0 +1,25 @@ +using System.Net.Sockets; + +namespace UIStandardWebApi.Common.SocketModel +{ + /// + /// 定义一个Socket静态类,用于连接,断开 ,接收,发送 + /// + public static class SocketStatic + { + /// + /// 定义数据解析类 + /// + public static DataParsing dataParsing = new DataParsing(); + + /// + /// 负责和客户端通信的Socket + /// + public static Socket? g_socketSend; + + /// + /// 服务端判断是否有客户端连接 + /// + public static bool IsConnection; + } +} diff --git a/UIStandardWebApi/Common/SocketModel/Sockets.cs b/UIStandardWebApi/Common/SocketModel/Sockets.cs new file mode 100644 index 0000000..2fa0c1c --- /dev/null +++ b/UIStandardWebApi/Common/SocketModel/Sockets.cs @@ -0,0 +1,107 @@ +using System.Net.Sockets; +using System.Net; + +namespace UIStandardWebApi.Common.SocketModel +{ + /// + /// Sockets 通信类 + /// + public class Sockets + { + public delegate void PushSockets(Sockets sockets); + + /// + /// + /// + public Sockets() + { + + } + /// + /// 创建Sockets对象 + /// + /// Ip地址 + /// TcpClient + /// 承载客户端Socket的网络流 + public Sockets(IPEndPoint ip, TcpClient client, NetworkStream ns) + { + Ip = ip; + Client = client; + nStream = ns; + } + /// + /// 创建Sockets对象 + /// + /// 用户名 + /// 密码 + /// Ip地址 + /// TcpClient + /// 承载客户端Socket的网络流 + public Sockets(string name, string pass, IPEndPoint ip, TcpClient client, NetworkStream ns) + { + UserName = name; + Password = pass; + Ip = ip; + Client = client; + nStream = ns; + } + /// + /// 接收缓冲区 + /// + public byte[] RecBuffer = new byte[8 * 1024]; + /// + /// 发送缓冲区 + /// + public byte[] SendBuffer = new byte[8 * 1024]; + /// + /// 异步接收后包的大小 + /// + public int Offset { get; set; } + /// + /// 用户名 + /// + public string UserName { get; set; } + /// + /// 密码 + /// + public string Password { get; set; } + /// + /// 当前IP地址,端口号 + /// + public IPEndPoint Ip { get; set; } + /// + /// 客户端主通信程序 + /// + public TcpClient Client { get; set; } + /// + /// 承载客户端Socket的网络流 + /// + public NetworkStream nStream { get; set; } + /// + /// 发生异常时不为null + /// + public Exception ex { get; set; } + /// + /// 新客户端标识.如果推送器发现此标识为true,那么认为是客户端上线 仅服务端有效 + /// + public bool NewClientFlag { get; set; } + /// + /// 客户端退出标识.如果服务端发现此标识为true,那么认为客户端下线 + /// 客户端接收此标识时,认为客户端异常. + /// + public bool ClientDispose { get; set; } + + } + /// + /// Socket基类(抽象类) + /// 抽象3个方法,初始化Socket(含一个构造),停止,启动方法. + /// 此抽象类为TcpServer与TcpClient的基类,前者实现后者抽象方法 + /// + public abstract class SocketObject + { + public abstract void InitSocket(IPAddress ipaddress, int port); + public abstract void InitSocket(string ipaddress, int port); + public abstract void Start(); + public abstract void Stop(); + } +} diff --git a/UIStandardWebApi/Common/tools.cs b/UIStandardWebApi/Common/tools.cs new file mode 100644 index 0000000..8f92ea3 --- /dev/null +++ b/UIStandardWebApi/Common/tools.cs @@ -0,0 +1,733 @@ +using System.Configuration; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Net; +using System.Text; + +namespace UIStandardWebApi.Common +{ + public static class tools + { + #region PING IP是否ping通 + /// + /// IP地址是否ping通 + /// + /// IP地址例如“10.8.2.1” + /// + public static bool PingIp(string strIP) + { + bool bRet = false; + try + { + Ping pingSend = new Ping(); + PingReply reply = pingSend.Send(strIP, 1000); + if (reply.Status == IPStatus.Success) + bRet = true; + } + catch (Exception) + { + bRet = false; + } + return bRet; + } + #endregion + + #region 添加日志 + public static void AddLog(string logstring) + { + AddLgoToTXT("解析数据.txt", System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"数据记录\" + System.DateTime.Now.ToString("yyyy_MM_dd") + @"\", logstring); + } + #endregion + + #region 生成并保存本地文件 + /// + /// 文件自动保存 + /// + /// 文件名称 + /// 保存路径 + /// 文件内容 + public static void AddLgoToTXT(string _file_name, string path, string logstring) + { + //检查是否存在该路径 + if (!System.IO.Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + + path = path + _file_name; + //检查该路径下是否存在该文件 + if (!System.IO.File.Exists(path)) + { + FileStream stream = null; + try + { + stream = System.IO.File.Create(path); + stream.Close(); + stream.Dispose(); + } + catch (Exception ex) + { + + } + finally + { + if (stream != null) + { + stream.Close(); + stream.Dispose(); + } + } + + } + if (!Txt_Used.ContainsKey(path)) + { + Txt_Used.Add(path, true); + } + else + { + if (Txt_Used[path]) + { + return; + } + else + { + Txt_Used[path] = true; + } + } + FileStream fs = null; + try + { + //[1]创建文件流 文件路径 和枚举类型的文件操作类型 + fs = new FileStream(path, FileMode.Append); + //[2]创建写入器 + StreamWriter sw = new StreamWriter(fs); + //[3]以流的方式写入数据 + sw.Write(logstring); + //[4]关闭写入器 + sw.Close(); + //[5]关闭文件流 + fs.Close(); + Txt_Used[path] = false; + } + catch (Exception ex) + { + + } + finally + { + if (fs != null) + { + fs.Close(); + fs.Dispose(); + } + } + } + #endregion + static Dictionary Txt_Used = new Dictionary(); + #region 读取本地TXT文件 + + public static string ReadFromTXT(string _file_name, string path) + { + //检查是否存在该路径 + if (!System.IO.Directory.Exists(path)) + return "所选时间段没有系统日志"; + path = path + _file_name; + //检查该路径下是否存在该文件 + if (!System.IO.File.Exists(path)) + return "所选时间段没有系统日志"; + //如果文件占用就 + if (FileIsInUse(new FileInfo(path))) + return ""; + //[1]创建文件流 + FileStream fs = new FileStream(path, FileMode.Open); + //【2】创建读取器 + //Encoding.Default 读取未知文件是使用default格式 + //StreamReader sr = new StreamReader(fs,Encoding.Default); + StreamReader sr = new StreamReader(fs); + //【3】以流的方式读取数据 + string txt = sr.ReadToEnd(); + //[4]关闭读取器 + sr.Close(); + //【5】关闭文件流 + fs.Close(); + + return txt; + } + #endregion + + #region + static bool FileIsInUse(FileInfo file) + { + FileStream stream = null; + try + { + stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); + } + catch (IOException) + { + //如果文件被占用,即 + //1.文件正在被另一个线程处理 + //2.或者正在被另一个线程处理 + //3.或者文件不存在 + return true; + } + finally + { + if (stream != null) + stream.Close(); + } + return false; + } + #endregion + + #region CRC校验 + private static readonly byte[] aucCRCHi = { + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40 + }; + private static readonly byte[] aucCRCLo = { + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, + 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, + 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, + 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, + 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, + 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, + 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, + 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, + 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, + 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, + 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, + 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, + 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, + 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, + 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, + 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, + 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, + 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, + 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, + 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, + 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, + 0x41, 0x81, 0x80, 0x40 + }; + public static byte[] Crc16(byte[] pucFrame, int usLen) + { + int i = 0; + byte crcHi = 0xFF; + byte crcLo = 0xFF; + UInt16 iIndex = 0x0000; + + while (usLen-- > 0) + { + iIndex = (UInt16)(crcLo ^ pucFrame[i++]); + crcLo = (byte)(crcHi ^ aucCRCHi[iIndex]); + crcHi = aucCRCLo[iIndex]; + } + + return new byte[] { crcLo, crcHi }; + } + + + #endregion + + #region 16进制转字符串ASCII + /// + /// 16进制转字符串ASCII + /// + /// + /// + /// + public static string HexStringToString(string hs, Encoding encode) + { + StringBuilder strTemp = new StringBuilder(); + byte[] b = new byte[hs.Length / 2]; + for (int i = 0; i < hs.Length / 2; i++) + { + strTemp.Clear(); + strTemp.Append(hs.Substring(i * 2, 2)); + b[i] = Convert.ToByte(strTemp.ToString(), 16); + } + return encode.GetString(b); + } + #endregion + + + #region 字节数组转16进制字符串 + /// + /// 字节数组转16进制字符串 + /// + /// + /// + public static string byteToHexStr(byte[] bytes) + { + string returnStr = ""; + if (bytes != null) + { + for (int i = 0; i < bytes.Length; i++) + { + returnStr += bytes[i].ToString("X2"); + } + } + return returnStr; + } + #endregion + + #region 16进制原码字符串转字节数组 + /// + /// 16进制原码字符串转字节数组 + /// + /// "AABBCC"或"AA BB CC"格式的字符串 + /// + public static byte[] ConvertHexStringToBytes(string hexString) + { + hexString = hexString.Replace(" ", ""); + if (hexString.Length % 2 != 0) + { + throw new ArgumentException("参数长度不正确"); + } + + byte[] returnBytes = new byte[hexString.Length / 2]; + for (int i = 0; i < returnBytes.Length; i++) + { + returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); + } + + return returnBytes; + } + #endregion + + #region 16进制转2进制 + /// + /// //16转2方法 + /// + /// + /// + public static string HexString2BinString(string hexString) + { + try + { + string result = string.Empty; + foreach (char c in hexString) + { + int v = Convert.ToInt32(c.ToString(), 16); + int v2 = int.Parse(Convert.ToString(v, 2)); + // 去掉格式串中的空格,即可去掉每个4位二进制数之间的空格, + result += string.Format("{0:d4} ", v2); + } + return result; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + throw; + } + } + #endregion + + /// + /// 将传入的byte数组 从指定位置倒置 -- bytetofloat + /// + /// + /// + public static float bytetofloat(List b, int start) + { + return BitConverter.ToSingle(new byte[] { b[start + 3], b[start + 2], b[start + 1], b[start] }, 0); + } + + /// + /// 将传入的byte数组 从指定位置倒置 -- bytetoInt + /// + /// + /// + public static int bytetoInt(List b, int start) + { + return BitConverter.ToInt16(new byte[] { b[start + 1], b[start] }, 0); + } + + /// + /// 将传入的byte数组 -- bytetoUInt + /// + /// + /// + public static UInt32 bytetoUInt(List b, int start) + { + return BitConverter.ToUInt32(new byte[] { b[start], b[start + 1], b[start + 2], b[start + 3] }, 0); + } + + /// + /// 将传入的byte数组 -- bytetoInt + /// + /// + /// + public static int bytetoInt32(List b, int start) + { + return BitConverter.ToInt32(new byte[] { b[start], b[start + 1], b[start + 2], b[start + 3] }, 0); + } + + + /// + /// 将传入的byte数组 -- bytetofloat + /// + /// + /// + public static float bytetoSingle(List b, int start) + { + return BitConverter.ToSingle(new byte[] { b[start], b[start + 1], b[start + 2], b[start + 3] }, 0); + } + /// + /// 计算按位异或校验和(返回校验和值) + /// + /// + /// + public static byte GetXOR(byte[] Cmd) + { + byte check = (byte)(Cmd[0] ^ Cmd[1]); + for (int i = 2; i < Cmd.Length; i++) + { + check = (byte)(check ^ Cmd[i]); + } + return check; + } + + + public static List O_C(string o_c) + { + o_c = o_c.Trim(); + List result = new List(); + for (int i = 0; i < o_c.Length; i++) + { + if (o_c.Substring(i, 1).Equals("1")) + { + result.Add(true); + } + else if (o_c.Substring(i, 1).Equals("0")) + { + result.Add(false); + } + } + + return result; + } + + + public static List Q_C(string o_c) + { + o_c = o_c.Trim(); + List result = new List(); + for (int i = o_c.Length - 1; i >= 0; i--) + { + if (o_c.Substring(i, 1).Equals("1")) + { + result.Add(1); + } + else if (o_c.Substring(i, 1).Equals("0")) + { + result.Add(0); + } + } + + return result; + } + + #region 16进制转ASI码字符串 + /// + /// 将一条十六进制字符串转换为ASCII + /// + /// 一条十六进制字符串 + /// 返回一条ASCII码 + public static string HexStringToASCII(string hexstring) + { + byte[] bt = HexStringToBinary(hexstring); + string lin = ""; + for (int i = 0; i < bt.Length; i++) + { + lin = lin + bt[i] + " "; + } + + + string[] ss = lin.Trim().Split(new char[] { ' ' }); + char[] c = new char[ss.Length]; + int a; + for (int i = 0; i < c.Length; i++) + { + a = Convert.ToInt32(ss[i]); + c[i] = Convert.ToChar(a); + } + + string b = new string(c); + return b; + } + + /**/ + /// + /// 16进制字符串转换为二进制数组 + /// + /// 用空格切割字符串 + /// 返回一个二进制字符串 + public static byte[] HexStringToBinary(string hexstring) + { + + string[] tmpary = hexstring.Trim().Split(' '); + byte[] buff = new byte[tmpary.Length]; + for (int i = 0; i < buff.Length; i++) + { + buff[i] = Convert.ToByte(tmpary[i], 16); + } + return buff; + } + #endregion + + #region 配置文件操作 + private static Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + /// + /// 获取配置文件 + /// + /// + /// + public static string GetAppSetting(string key) + { + if (System.Configuration.ConfigurationManager.AppSettings.AllKeys.Contains(key)) + { + string value = config.AppSettings.Settings[key].Value; + return value; + } + else + { + return null; + } + } + /// + /// 更新配置文件信息 + /// + /// + /// + public static void UpdateAppSettings(string key, string value) + { + if (GetAppSetting(key) == value) //如果写入的配置文件和之前一致 就不写入了 + return; + if (System.Configuration.ConfigurationManager.AppSettings.AllKeys.Contains(key)) + { + config.AppSettings.Settings[key].Value = value; + config.Save(ConfigurationSaveMode.Modified); + System.Configuration.ConfigurationManager.RefreshSection("appSettings");//刷新数据 + } + else + { + Console.WriteLine("当前节点不存在!"); + } + } + #endregion + + #region Telnet 判断某个端口是否开放 + + public static bool TelnetPort(string ip, int port) + { + if (checkPingEnable(ip)) + { + if (checkPortEnable(ip, port)) + { + return true; + } + } + return false; + } + + //检查是否ping通 + public static bool checkPingEnable(string _ip) + { + bool _isEnable = false; + try + { + Ping pingSender = new Ping(); + PingReply reply = pingSender.Send(_ip, 120);//第一个参数为ip地址,第二个参数为ping的时间 + if (reply.Status == IPStatus.Success) + { + _isEnable = true; + } + else + { + _isEnable = false; + } + } + catch (Exception) + { + + _isEnable = false; + } + return _isEnable; + } + + /// + /// telnet port + /// + /// + /// + /// + public static bool checkPortEnable(string _ip, int _port) + { + //将IP和端口替换成为你要检测的 + string ipAddress = _ip; + int portNum = _port; + IPAddress ip = IPAddress.Parse(ipAddress); + IPEndPoint point = new IPEndPoint(ip, portNum); + + bool _portEnable = false; + try + { + using (Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + sock.Connect(point); + //Console.WriteLine("连接{0}成功!", point); + sock.Close(); + + _portEnable = true; + } + } + catch (SocketException e) + { + //Console.WriteLine("连接{0}失败", point); + _portEnable = false; + } + return _portEnable; + } + #endregion + + + #region 内存清理 + /// + ///设置线程工作的空间 + /// + /// 线程 + /// 最小空间 + /// 最大空间 + /// + [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)] + private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize); + public static void ClearMemory(object o) + { + GC.Collect(); + GC.SuppressFinalize(o); + + + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + { + SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1); + } + } + #endregion + + + public static byte[] intoBytes(int value) + { + byte[] src = new byte[4] + { + (byte)((value) & 0xFF), + (byte)((value >> 8) & 0xFF), + (byte)((value >> 16) & 0xFF), + (byte)(value >> 24 & 0xFF) + }; + return src; + } + + public static byte[] shortoBytes(int value) + { + byte[] src = new byte[2] + { + (byte)((value) & 0xFF), + (byte)((value >> 8) & 0xFF) + }; + return src; + } + + /// + /// TcpClient检测 + /// + /// ip地址 + /// 端口号 + public static bool TcpClientCheck(string ip, int port) + { + IPAddress ipa = IPAddress.Parse(ip); + IPEndPoint point = new IPEndPoint(ipa, port); + TcpClient tcp = null; + + try + { + tcp = new TcpClient(); + tcp.Connect(point); + //Console.WriteLine("端口打开"); + return true; + } + catch (Exception ex) + { + //Console.WriteLine("计算机端口检测失败,错误消息为:" + ex.Message); + return false; + } + finally + { + if (tcp != null) + { + tcp.Close(); + } + } + } + /// + /// Socket检测 + /// + /// ip地址 + /// 端口号 + public static bool SocketCheck(string ip, int port) + { + Socket sock = null; + try + { + IPAddress ipa = IPAddress.Parse(ip); + IPEndPoint point = new IPEndPoint(ipa, port); + sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + sock.Connect(point); + //Console.WriteLine("端口打开"); + return true; + } + catch (SocketException ex) + { + //Console.WriteLine("计算机端口检测失败,错误消息为:" + ex.Message); + return false; + } + finally + { + if (sock != null) + { + sock.Close(); + sock.Dispose(); + } + } + } + + //获取当前程序运行路径 + private static string Save_Path = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"数据记录\"; + + public static void Logging(string message) + { + AddLgoToTXT("Log.txt", Save_Path + System.DateTime.Now.ToString("yyyy_MM_dd") + @"\", System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " ---- " + message + "\r\n"); + } + + } +} diff --git a/UIStandardWebApi/Controllers/WeatherForecastController.cs b/UIStandardWebApi/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..f343a01 --- /dev/null +++ b/UIStandardWebApi/Controllers/WeatherForecastController.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Mvc; +using UIStandardWebApi.WebCore.SwaggerExtend; + +namespace UIStandardWebApi.Controllers +{ + [ApiController] + [ApiExplorerSettings(IgnoreApi = false, GroupName = nameof(ApiVersions.V1))] + [Route("api/[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/UIStandardWebApi/Program.cs b/UIStandardWebApi/Program.cs new file mode 100644 index 0000000..43e97bc --- /dev/null +++ b/UIStandardWebApi/Program.cs @@ -0,0 +1,69 @@ + +using UIStandardWebApi.SqlSuggar; +using UIStandardWebApi.Utility.RegisterExt; +using UIStandardWebApi.WebCore.AutoMapExtend; +using UIStandardWebApi.WebCore.CorsExtend; +using UIStandardWebApi.WebCore.SwaggerExtend; + +namespace UIStandardWebApi +{ + public class Program + { + public static void Main(string[] args) + { + var builder = WebApplication.CreateBuilder(args); + + // Add services to the container. + + builder.Services.AddControllers(); + + //ע + builder.RegistService(); + + //ý + builder.RegistControllers(); + + //Swagger + builder.Services.AddSwaggerExt("׼Apiĵ", "׼Apiĵ"); + + //Automapperע + builder.Services.AddAutoMapper(typeof(AutoMapperConfigs)); + + builder.Services.AddMemoryCache(); + + // + builder.Services.AddCorsExt(); + + builder.InitSqlSugar(); //עSqlSugar + + if (builder.Configuration["IsInitDatabase"] == "1") + { + builder.InitDatabase(); + } + + + + var app = builder.Build(); + + //ʹSwagger + app.UseSwaggerExt("׼Apiĵ"); + + //ʹÿ + app.UseCorsExt(); + + //ӳĬϵ MVC · + app.MapControllers(); + + //Ӧó HTTP ض HTTPS ԴǿӦóİȫ + app.UseHttpsRedirection(); + + // ʹ֤м + app.UseAuthentication(); + // ʹȨм + app.UseAuthorization(); + + + app.Run(); + } + } +} diff --git a/UIStandardWebApi/Properties/launchSettings.json b/UIStandardWebApi/Properties/launchSettings.json new file mode 100644 index 0000000..8c6c6e6 --- /dev/null +++ b/UIStandardWebApi/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:21734", + "sslPort": 44376 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5047", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7224;http://localhost:5047", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/UIStandardWebApi/SqlSuggar/CustomConnectionConfig.cs b/UIStandardWebApi/SqlSuggar/CustomConnectionConfig.cs new file mode 100644 index 0000000..c0cfd70 --- /dev/null +++ b/UIStandardWebApi/SqlSuggar/CustomConnectionConfig.cs @@ -0,0 +1,53 @@ +using SqlSugar; + +namespace UIStandardWebApi.SqlSuggar +{ + /// + /// 数据库配置文件映射实体对象,专用作读取配置文件使用 + /// + public class CustomConnectionConfig + { + /// + /// 初始化从库链接--多个从库--集合 + /// + public CustomConnectionConfig() + { + SlaveConnectionConfigs = new List(); + } + + /// + /// 主库链接 + /// + public string? ConnectionString + { + get; + set; + } + + /// + /// 从库链接--多个从库--集合 + /// + public List SlaveConnectionConfigs { get; set; } + } + + /// + /// 从库链接配置文件读取 + /// + public class CustomSlaveConnectionConfig : SlaveConnectionConfig + { + private int _CustomHitRate; + + /// + ///读取配置文件中,从库数据的权重数据 + /// + public int CustomHitRate + { + get { return _CustomHitRate; } + set + { + HitRate = value; + _CustomHitRate = value; + } + } + } +} diff --git a/UIStandardWebApi/SqlSuggar/InitDatabaseExt.cs b/UIStandardWebApi/SqlSuggar/InitDatabaseExt.cs new file mode 100644 index 0000000..062ba5b --- /dev/null +++ b/UIStandardWebApi/SqlSuggar/InitDatabaseExt.cs @@ -0,0 +1,46 @@ +using SqlSugar; +using System.Reflection; +using UIStandardWebApi.Common; + +namespace UIStandardWebApi.SqlSuggar +{ + /// + /// 是否初始化数据库 + /// + public static class InitDatabaseExt + { + /// + /// 是否初始化数据库 + /// + /// + /// + public static void InitDatabase(this WebApplicationBuilder builder) + { + string? connectionString = builder.Configuration.GetConnectionString("ConnectionString"); + if (string.IsNullOrWhiteSpace(connectionString)) + { + throw new Exception("请配置数据库链接字符串~"); + } + + ConnectionConfig connection = new ConnectionConfig() + { + DbType = DbType.SqlServer, + IsAutoCloseConnection = true, + ConnectionString = connectionString + }; + using (SqlSugarClient client = new SqlSugarClient(connection)) + { + client.DbMaintenance.CreateDatabase(); + + Assembly assembly = Assembly.LoadFile(Path.Combine(AppContext.BaseDirectory, "UIStandardWebApi.Entity.dll")); + Type[] typeArray = assembly.GetTypes() + .Where(t => !t.Name.Equals("Sys_BaseModel") && t.Namespace.Equals("UIStandardWebApi.Entity")) + .ToArray(); + + client.CodeFirst.InitTables(typeArray); + + } + + } + } +} diff --git a/UIStandardWebApi/SqlSuggar/InitSqlSugarExt.cs b/UIStandardWebApi/SqlSuggar/InitSqlSugarExt.cs new file mode 100644 index 0000000..cd83ee2 --- /dev/null +++ b/UIStandardWebApi/SqlSuggar/InitSqlSugarExt.cs @@ -0,0 +1,70 @@ +using SqlSugar; + +namespace UIStandardWebApi.SqlSuggar +{ + /// + /// 初始化SqlSugar + /// + public static class InitSqlSugarExt + { + /// + /// 初始化SqlSugar + /// + /// + public static void InitSqlSugar(this WebApplicationBuilder builder) + { + CustomConnectionConfig customConnectionConfig = new CustomConnectionConfig(); + builder.Configuration.Bind("ConnectionStrings", customConnectionConfig); + + builder.Services.AddTransient(s => + { + ConnectionConfig connection = new ConnectionConfig() + { + ConnectionString = customConnectionConfig.ConnectionString, + DbType = DbType.SqlServer, + IsAutoCloseConnection = true, + InitKeyType = InitKeyType.Attribute, + SlaveConnectionConfigs = customConnectionConfig.SlaveConnectionConfigs.Select(c => new SlaveConnectionConfig() { ConnectionString = c.ConnectionString, HitRate = c.CustomHitRate }).ToList() + }; + SqlSugarClient client = new SqlSugarClient(connection); + client.Aop.OnLogExecuting = (s, p) => + { + //Console.WriteLine("*******************************************************************************************"); + //Console.WriteLine($"OnLogExecuting:输出Sql语句:{s} || 参数为:{string.Join(",", p.Select(p => p.Value))}"); + }; + + client.Aop.DataExecuting = (s, p) => + { + if (p.OperationType.Equals(DataFilterType.InsertByObject) && "CreateTime".Equals(p.EntityColumnInfo.DbColumnName)) + { + p.SetValue(DateTime.Now); + } + + if (p.OperationType.Equals(DataFilterType.UpdateByObject) && "ModifyTime".Equals(p.EntityColumnInfo.DbColumnName)) + { + p.SetValue(DateTime.Now); + } + }; + + + client.Aop.OnLogExecuted = (s, p) => + { + + //Console.WriteLine("*******************************************************************************************"); + //Console.WriteLine($"OnLogExecuted:输出Sql语句:{s} || 参数为:{string.Join(",", p.Select(p => p.Value))}"); + }; + client.Aop.OnError = e => + { + Console.WriteLine("*******************************************************************************************"); + Console.WriteLine($"OnError:Sql语句执行异常:{e.Message}"); + }; + return client; + }); + + + //初始化开启服务器 + //SocketStatic.socketListening.OpenServer(8899); + + } + } +} diff --git a/UIStandardWebApi/UIStandardWebApi.csproj b/UIStandardWebApi/UIStandardWebApi.csproj new file mode 100644 index 0000000..b651bc9 --- /dev/null +++ b/UIStandardWebApi/UIStandardWebApi.csproj @@ -0,0 +1,35 @@ + + + + net8.0 + enable + enable + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UIStandardWebApi/Utility/RegisterExt/RegistServiceExtension.cs b/UIStandardWebApi/Utility/RegisterExt/RegistServiceExtension.cs new file mode 100644 index 0000000..9229ecf --- /dev/null +++ b/UIStandardWebApi/Utility/RegisterExt/RegistServiceExtension.cs @@ -0,0 +1,53 @@ +using Newtonsoft.Json.Serialization; +using Newtonsoft.Json; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using UIStandardWebApi.Common.JwtService; + +namespace UIStandardWebApi.Utility.RegisterExt +{ + /// + /// 服务注册 + /// + public static class RegistServiceExtension + { + /// + /// 注册服务层 + /// + /// + public static void RegistService(this WebApplicationBuilder builder) + { + //builder.Services.AddTransient(); + + + builder.Services.Configure(builder.Configuration.GetSection("JWTTokenOptions")); + + } + + /// + /// AddControllers 相关 + /// + /// + public static void RegistControllers(this WebApplicationBuilder builder) + { + builder.Services.AddControllers(option => + { + + }).AddNewtonsoftJson(options => + { + //配置返回JSON首字母问题以及格式 nuget引入:Microsoft.AspNetCore.Mvc.NewtonsoftJson + options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; + //options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();//设置JSON返回格式同model一致 + + options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();//设置JSON返回格式首字母小写 + + + }).AddJsonOptions(options => + { + //配置解决中文乱码问题 + options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); + }); + } + } +} diff --git a/UIStandardWebApi/WeatherForecast.cs b/UIStandardWebApi/WeatherForecast.cs new file mode 100644 index 0000000..ff6cb4b --- /dev/null +++ b/UIStandardWebApi/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace UIStandardWebApi +{ + public class WeatherForecast + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} diff --git a/UIStandardWebApi/appsettings.Development.json b/UIStandardWebApi/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/UIStandardWebApi/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/UIStandardWebApi/appsettings.json b/UIStandardWebApi/appsettings.json new file mode 100644 index 0000000..24b7f87 --- /dev/null +++ b/UIStandardWebApi/appsettings.json @@ -0,0 +1,28 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "IsInitDatabase": "0", + "Socket": { + "ip": "192.168.1.254", + "port": "8899" + }, + "ConnectionStrings": { + "ConnectionString": "Data Source = NB10920;Initial Catalog=InSituLaboratoryWeb;User ID=sa;Password=zttZTT123;MultipleActiveResultSets=true", + "DbType": 1 + }, + "JWTTokenOptions": { + "Audience": "http://localhost:5200", + "Issuer": "http://localhost:5200", + "SecurityKey": "我是一个秘钥,秘钥长度尽量保证在16个字符以上" + }, + "StaticFileAddress": "/root/file" + + + + +}