2026-07-02 10:05:51 +08:00

81 lines
3.2 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using YD_TrainingCompetition_Api.Competition;
using YD_TrainingCompetition_Api.Hubs;
using YD_TrainingCompetition_Api.Options;
using YD_TrainingCompetition_Api.Protocols;
using YD_TrainingCompetition_Api.Serial;
using YD_TrainingCompetition_Api.Services;
var builder = WebApplication.CreateBuilder(args);
var listenUrls = builder.Configuration["ASPNETCORE_URLS"]
?? builder.Configuration["urls"]
?? "http://*:9996";
builder.WebHost.UseUrls(listenUrls);
builder.Services.Configure<ScoringOptions>(builder.Configuration.GetSection(ScoringOptions.SectionName));
builder.Services.Configure<Serial24GOptions>(builder.Configuration.GetSection(Serial24GOptions.SectionName));
builder.Services.Configure<RosterOptions>(builder.Configuration.GetSection(RosterOptions.SectionName));
builder.Services.Configure<HikvisionOptions>(builder.Configuration.GetSection(HikvisionOptions.SectionName));
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSignalR();
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed(_ => true)
.AllowCredentials();
});
});
builder.Services.AddSingleton<IDeviceStateStore, DeviceStateStore>();
builder.Services.AddSingleton<IRealtimeNotifier, SignalRRealtimeNotifier>();
builder.Services.AddSingleton<ISerialGateway, SerialGateway>();
builder.Services.AddSingleton<IJumpProtocolParser, JumpProtocolParser>();
builder.Services.AddSingleton<IRosterService, RosterService>();
builder.Services.AddSingleton<IParticipantDirectory, ParticipantDirectory>();
builder.Services.AddSingleton<ICompetitionSessionService, CompetitionSessionService>();
builder.Services.AddSingleton<IHikvisionAlarmStore, HikvisionAlarmStore>();
builder.Services.AddHostedService<SerialIngestWorker>();
builder.Services.AddHostedService<CompetitionCountdownWorker>();
builder.Services.AddHostedService<HikvisionIngestWorker>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
// 提供打包后内置的前端静态资源(桌面端通过 http 加载,避免 file:// 下 fetch/绝对路径失效)。
// 使用可执行文件同级的 wwwroot 绝对路径,避免内容根/工作目录差异导致静态资源 404。
var webRootPath = Path.Combine(AppContext.BaseDirectory, "wwwroot");
var hasBundledFrontend = Directory.Exists(webRootPath);
Microsoft.Extensions.FileProviders.PhysicalFileProvider? frontendFileProvider = null;
if (hasBundledFrontend)
{
frontendFileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(webRootPath);
app.UseDefaultFiles(new DefaultFilesOptions { FileProvider = frontendFileProvider });
app.UseStaticFiles(new StaticFileOptions { FileProvider = frontendFileProvider });
}
app.UseRouting();
app.UseCors();
app.MapControllers();
app.MapHub<ScoringHub>("/hubs/scoring");
// 单页应用兜底:非 API/Hub 路由回退到 index.html(仅当存在内置前端时生效)。
if (hasBundledFrontend && frontendFileProvider is not null)
{
app.MapFallbackToFile("index.html", new StaticFileOptions { FileProvider = frontendFileProvider });
}
app.Run();