TheRegister.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. using Blazored.LocalStorage;
  2. using EasyTemplate.Blazor.Web.Components;
  3. using EasyTemplate.Page.Common;
  4. using EasyTemplate.Service.Common;
  5. using EasyTemplate.Tool;
  6. using EasyTemplate.Tool.Util;
  7. using Microsoft.AspNetCore.Authentication.Cookies;
  8. using Microsoft.AspNetCore.Components.Authorization;
  9. using Microsoft.AspNetCore.Identity;
  10. using Microsoft.AspNetCore.Mvc.ApplicationModels;
  11. using Microsoft.AspNetCore.StaticFiles;
  12. using Microsoft.Extensions.FileProviders;
  13. using Microsoft.OpenApi.Models;
  14. using System.Net;
  15. using System.Net.Sockets;
  16. using System.Reflection;
  17. using System.Text;
  18. using EasyTemplate.Service;
  19. namespace EasyTemplate.Blazor.Web.Common;
  20. public static class TheRegister
  21. {
  22. /// <summary>
  23. /// 注册配置
  24. /// </summary>
  25. /// <param name="builder"></param>
  26. /// <returns></returns>
  27. public static WebApplicationBuilder? RegistService(this WebApplicationBuilder? builder)
  28. {
  29. var configuration = builder.Configuration;
  30. // Add services to the container.
  31. builder.Services.AddRazorComponents()
  32. .AddInteractiveServerComponents();
  33. builder.Services.AddConfiguration();
  34. builder.Services.AddLocalLog();
  35. builder.Services.AddSqlSugar();
  36. builder.Services.AddRedis();
  37. builder.Services.AddAntDesign();
  38. builder.Services.AddInteractiveStringLocalizer();
  39. builder.Services.AddLocalization();
  40. builder.Services.AddHttpContextAccessor();
  41. // 在Program.cs中添加更详细的错误处理
  42. builder.Services.Configure<IISServerOptions>(options =>
  43. {
  44. options.AllowSynchronousIO = true;
  45. });
  46. builder.Services.AddCors(options =>
  47. {
  48. options.AddPolicy("Policy", policy =>
  49. {
  50. policy.AllowAnyOrigin()
  51. .AllowAnyMethod()
  52. .AllowAnyHeader();
  53. });
  54. });
  55. builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
  56. .AddCookie(options =>
  57. {
  58. options.LoginPath = "/account/login"; // 登录页路径
  59. options.AccessDeniedPath = "/error/404"; // 未授权页路径
  60. options.SlidingExpiration = true; // 滑动过期
  61. });
  62. builder.Services.AddRazorPages();
  63. builder.Services.AddServerSideBlazor();
  64. builder.Services.AddAuthorization();
  65. builder.Services.Configure<ProSettings>(Setting.GetSection("ThemeSettings"));
  66. Global.SystemName = Setting.Get<string>("ThemeSettings:Title");
  67. builder.Services.AddControllers().AddNewtonsoftJson();//不加该注册,api传参易报错
  68. builder.Services.AddEndpointsApiExplorer();
  69. builder.Services.AddSwaggerGen(options =>
  70. {
  71. typeof(ApiGroupNames).GetFields().Skip(1).ToList().ForEach(f =>
  72. {
  73. //获取枚举值上的特性
  74. var info = f.GetCustomAttributes(typeof(GroupInfoAttribute), false).OfType<GroupInfoAttribute>().FirstOrDefault();
  75. options.SwaggerDoc(f.Name, new Microsoft.OpenApi.Models.OpenApiInfo
  76. {
  77. Title = info?.Title,
  78. Version = info?.Version,
  79. Description = info?.Description
  80. });
  81. });
  82. options.SwaggerDoc("all", new Microsoft.OpenApi.Models.OpenApiInfo
  83. {
  84. Title = "全部"
  85. });
  86. options.DocInclusionPredicate((docName, apiDescription) =>
  87. {
  88. if (docName != "all")
  89. {
  90. return apiDescription.GroupName == docName;
  91. }
  92. return true;
  93. });
  94. options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme()
  95. {
  96. Description = "请输入正确的Token格式:Bearer token",
  97. Name = "Authorization",
  98. In = Microsoft.OpenApi.Models.ParameterLocation.Header,
  99. Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey,
  100. BearerFormat = "JWT",
  101. Scheme = "Bearer"
  102. });
  103. //options.DocInclusionPredicate((docName, description) => true);
  104. options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement() {
  105. {
  106. new OpenApiSecurityScheme
  107. {
  108. Reference = new OpenApiReference()
  109. {
  110. Type = ReferenceType.SecurityScheme,
  111. Id = "Bearer"
  112. }
  113. },
  114. new string[]{ }
  115. }
  116. });
  117. var baseDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
  118. var xmlFile = System.AppDomain.CurrentDomain.FriendlyName + ".xml";
  119. var xmlPath = Path.Combine(baseDirectory, xmlFile);
  120. options.IncludeXmlComments(xmlPath);
  121. });
  122. //将类库中razor注册到应用中
  123. builder.Services.AddAssembly();
  124. builder.Services.AddDynamicController<ServiceLocalSelectController, ServiceActionRouteFactory>();
  125. builder.Services.AddSignalR();
  126. builder.Services.AddSignalR(options =>
  127. {
  128. options.MaximumReceiveMessageSize = 102400; // 100KB
  129. options.EnableDetailedErrors = true;
  130. });
  131. //builder.Services.AddCascadingAuthenticationState();
  132. //builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
  133. builder.Services.AddScoped<CustomAuthenticationStateProvider>();
  134. builder.Services.AddScoped<AuthenticationStateProvider>(implementationFactory => implementationFactory.GetRequiredService<CustomAuthenticationStateProvider>());
  135. // 注册 Blazored.LocalStorage 服务
  136. builder.Services.AddBlazoredLocalStorage();
  137. builder.Services.AddSingleton<INotificationService, NotificationService>();
  138. //builder.Services.AddSingleton<UdpServerService>();
  139. // 在 Startup.cs 或 Program.cs 中注册
  140. //builder.Services.AddScoped<IHostedService, UdpServerService>();
  141. // builder.Services.AddHostedService<UdpServerService>();
  142. // 注册后台UDP监听服务
  143. //builder.Services.AddSingleton<UdpListenerService>();
  144. //builder.Services.AddHostedService(sp => sp.GetRequiredService<UdpListenerService>());
  145. //for (int i = 0; i < 40; i++)
  146. //{
  147. // NozzleState ns = new NozzleState();
  148. // ns.noz = i + 1;
  149. // ns.warnstate = i % 3;
  150. // ns.oil = i % 2 == 0 ? "92#" : "95#";
  151. // GlobalTool.g_mNozzleState.Add(ns.noz, ns);
  152. //}
  153. builder.Services.AddHostedService<UdpListenerService>();
  154. builder.Services.AddHostedService<SerialPortBackgroundService>();
  155. builder.Services.AddSingleton<HandleData>();
  156. builder.Services.BuildServiceProvider().GetService<HandleData>();
  157. // builder.Services.AddSingleton<DB>();
  158. builder.Services.AddScoped<NozzleService>();
  159. builder.Services.AddScoped<Init>();
  160. //builder.Services.AddHostedService<BackgroundTimerService>();
  161. //builder.Services.AddScoped<IBackgroundService>(provider =>
  162. // provider.GetRequiredService<BackgroundTimerService>());
  163. // 注册UDP服务
  164. //builder.Services.AddScoped<IUdpService, UdpService>();
  165. //builder.Services.AddScoped<UdpBroadcastService>();
  166. /*
  167. UdpClient udpServer = new UdpClient(10000);
  168. IPEndPoint clientEndPoint = new IPEndPoint(IPAddress.Any, 0);
  169. Console.WriteLine("UDP Server started on port 10000...");
  170. while (true)
  171. {
  172. try
  173. {
  174. byte[] receiveBytes = udpServer.Receive(ref clientEndPoint);
  175. string receivedData = Encoding.UTF8.GetString(receiveBytes);
  176. Console.WriteLine($"Received: {receivedData} from {clientEndPoint}");
  177. string response = "Echo: " + receivedData;
  178. byte[] sendBytes = Encoding.UTF8.GetBytes(response);
  179. udpServer.Send(sendBytes, sendBytes.Length, clientEndPoint);
  180. }
  181. catch (Exception e)
  182. {
  183. Console.WriteLine("Error: " + e.Message);
  184. }
  185. }
  186. */
  187. return builder;
  188. }
  189. /// <summary>
  190. /// 注册应用
  191. /// </summary>
  192. /// <param name="builder"></param>
  193. /// <returns></returns>
  194. public static WebApplicationBuilder? RegistApp(this WebApplicationBuilder? builder)
  195. {
  196. var app = builder.Build();
  197. // Configure the HTTP request pipeline.
  198. if (!app.Environment.IsDevelopment())
  199. {
  200. app.UseExceptionHandler("/Error", createScopeForErrors: true);
  201. }
  202. app.UseStatusCodePagesWithReExecute("/error/{0}");
  203. app.UseSwagger();
  204. app.UseSwaggerUI(options =>
  205. {
  206. //遍历ApiGroupNames所有枚举值生成接口文档,Skip(1)是因为Enum第一个FieldInfo是内置的一个Int值
  207. typeof(ApiGroupNames).GetFields().Skip(1).ToList().ForEach(f =>
  208. {
  209. //获取枚举值上的特性
  210. var info = f.GetCustomAttributes(typeof(GroupInfoAttribute), false).OfType<GroupInfoAttribute>().FirstOrDefault();
  211. options.SwaggerEndpoint($"/swagger/{f.Name}/swagger.json", info != null ? info.Title : f.Name);
  212. });
  213. options.SwaggerEndpoint("/swagger/all/swagger.json", "全部");
  214. });
  215. app.UseStaticFiles();
  216. app.UseCors("Policy");
  217. app.UseDynamicWebApi();
  218. app.UseHttpsRedirection();
  219. app.UseRouting();
  220. app.UseAuthentication();
  221. app.UseAuthorization();
  222. app.UseAntiforgery();
  223. app.MapRazorComponents<App>()
  224. .AddInteractiveServerRenderMode();
  225. app.MapControllers();
  226. //UdpServer server = new UdpServer(); // 创建UdpServer实例并启动监听线程
  227. //Console.WriteLine("UDP Server is running...");
  228. // Console.ReadLine(); // 等待用户输入以保持程序运行,以便可以看到输出结果。实际应用中可以根据需要调整。
  229. // server.StopServer(); // 在需要停止服务器时调用此方法,例如在程序结束时。
  230. using (var scope = app.Services.CreateScope())
  231. {
  232. var myService = scope.ServiceProvider.GetRequiredService<Init>();
  233. // 初始化数据库中的油枪状态
  234. InitializeNozzleStates(scope.ServiceProvider);
  235. }
  236. app.Run();
  237. return builder;
  238. }
  239. /// <summary>
  240. /// 从数据库查询所有油枪并初始化状态
  241. /// </summary>
  242. private static void InitializeNozzleStates(IServiceProvider serviceProvider)
  243. {
  244. try
  245. {
  246. var nozzleService = serviceProvider.GetRequiredService<NozzleService>();
  247. // 异步获取油枪数据
  248. var task = Task.Run(async () => await nozzleService.GetNozzlesAsync());
  249. var nozzles = task.Result;
  250. if (nozzles != null && nozzles.Count > 0)
  251. {
  252. foreach (var nozzle in nozzles)
  253. {
  254. if (!GlobalTool.g_mNozzleState.ContainsKey(nozzle.NozzleId))
  255. {
  256. var nozzleState = new NozzleState
  257. {
  258. noz = nozzle.NozzleId,
  259. VLR = "0",
  260. oil = nozzle.product.ToString()+"#", // 可以根据需要设置默认油品
  261. nozzlestate = GlobalTool.NozzleState_Offline, // 初始状态设为离线
  262. warnstate = GlobalTool.WarningState_Normal // 初始警告状态设为正常
  263. };
  264. GlobalTool.g_mNozzleState.Add(nozzle.NozzleId, nozzleState);
  265. }
  266. }
  267. Console.WriteLine($"已初始化 {nozzles.Count} 个油枪状态");
  268. }
  269. else
  270. {
  271. Console.WriteLine("数据库中没有找到油枪数据");
  272. }
  273. }
  274. catch (Exception ex)
  275. {
  276. Console.WriteLine($"初始化油枪状态时发生错误:{ex.Message}");
  277. }
  278. }
  279. private static FileExtensionContentTypeProvider GetFileExtensionContentTypeProvider()
  280. {
  281. var provider = new FileExtensionContentTypeProvider();
  282. provider.Mappings[".iec"] = "application/octet-stream";
  283. provider.Mappings[".patch"] = "application/octet-stream";
  284. provider.Mappings[".apk"] = "application/vnd.android.package-archive";
  285. provider.Mappings[".pem"] = "application/x-x509-user-cert";
  286. provider.Mappings[".gzip"] = "application/x-gzip";
  287. provider.Mappings[".7zip"] = "application/zip";
  288. provider.Mappings[".jpg2"] = "image/jp2";
  289. provider.Mappings[".et"] = "application/kset";
  290. provider.Mappings[".dps"] = "application/ksdps";
  291. provider.Mappings[".cdr"] = "application/x-coreldraw";
  292. provider.Mappings[".shtml"] = "text/html";
  293. provider.Mappings[".php"] = "application/x-httpd-php";
  294. provider.Mappings[".php3"] = "application/x-httpd-php";
  295. provider.Mappings[".php4"] = "application/x-httpd-php";
  296. provider.Mappings[".phtml"] = "application/x-httpd-php";
  297. provider.Mappings[".pcd"] = "image/x-photo-cd";
  298. provider.Mappings[".bcmap"] = "application/octet-stream";
  299. provider.Mappings[".properties"] = "application/octet-stream";
  300. provider.Mappings[".m3u8"] = "application/x-mpegURL";
  301. return provider;
  302. }
  303. }
  304. internal class ServiceLocalSelectController : ISelectController
  305. {
  306. public bool IsController(Type type)
  307. {
  308. return type.IsPublic && type.GetCustomAttribute<DynamicControllerAttribute>() != null;
  309. }
  310. }
  311. internal class ServiceActionRouteFactory : IActionRouteFactory
  312. {
  313. public string CreateActionRouteModel(string areaName, string controllerName, ActionModel action)
  314. {
  315. var controllerType = action.ActionMethod.DeclaringType;
  316. var serviceAttribute = controllerType.GetCustomAttribute<DynamicControllerAttribute>();
  317. var _controllerName = serviceAttribute.ServiceName == string.Empty ? controllerName.Replace("Service", "") : serviceAttribute.ServiceName.Replace("Service", "");
  318. return $"api/{_controllerName.Replace("Service", "")}/{action.ActionName.Replace("Async", "")}";
  319. }
  320. }