cf96c56bed
本次提交完成了多项清理与规范工作: 1. 移除默认管理员硬编码配置与云同步相关代码 2. 简化前端与MAUI端的配置,关闭静态资源托管以外的冗余功能 3. 清理.gitignore与协调目录,移除临时文件与冗余规则 4. 统一项目命名规范,修正包名与版本号 5. 重构后端数据模型,移除ABP审计字段与云同步相关逻辑 6. 简化WebView配置与系统栏样式,移除不必要的平台检测代码 7. 更新文档与规则文件,完善项目规范与版本记录
173 lines
5.7 KiB
C#
173 lines
5.7 KiB
C#
#if WINDOWS
|
|
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.FileProviders;
|
|
using Microsoft.Extensions.Hosting;
|
|
using System.Text.Json;
|
|
using Hua.Todo.Application;
|
|
using Hua.Todo.Application.DynamicApi;
|
|
using Hua.Todo.Maui.Models;
|
|
using AppSettings = Hua.Todo.Maui.Models.AppSettings;
|
|
|
|
namespace Hua.Todo.Maui.Services;
|
|
|
|
/// <summary>
|
|
/// Windows 平台嵌入式 Web 服务器实现
|
|
/// 使用 ASP.NET Core 运行
|
|
/// </summary>
|
|
public class EmbeddedWebServerService : IEmbeddedWebServerService
|
|
{
|
|
private WebApplication? _webApp;
|
|
private readonly AppSettings _appSettings;
|
|
|
|
/// <summary>
|
|
/// 服务器是否正在运行
|
|
/// </summary>
|
|
public bool IsRunning => _webApp != null;
|
|
|
|
/// <summary>
|
|
/// 服务器基础 URL
|
|
/// </summary>
|
|
public string BaseUrl => _appSettings.WebServer.HostUrl;
|
|
|
|
/// <summary>
|
|
/// 初始化嵌入式 Web 服务器服务
|
|
/// </summary>
|
|
/// <param name="appSettings">应用程序配置</param>
|
|
public EmbeddedWebServerService(AppSettings appSettings)
|
|
{
|
|
_appSettings = appSettings;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 异步启动服务器。
|
|
/// 启动时机:通常在应用启动或用户手动开启服务时调用。
|
|
/// 错误处理:启动失败会抛出 ASP.NET Core 相关异常,建议在调用方进行 catch 处理。
|
|
/// 线程安全:非 UI 线程相关,可在后台线程调用;方法内部已处理重入(若已运行则直接返回)。
|
|
/// </summary>
|
|
/// <returns>表示启动操作的任务</returns>
|
|
public async Task StartAsync()
|
|
{
|
|
if (_webApp != null) return;
|
|
|
|
var builder = WebApplication.CreateBuilder();
|
|
|
|
builder.WebHost.UseUrls(_appSettings.WebServer.HostUrl);
|
|
|
|
// 配置控制器和 JSON 选项
|
|
builder.Services.AddControllers()
|
|
.AddApplicationPart(typeof(Hua.Todo.Application.ServiceCollectionExtensions).Assembly)
|
|
.AddJsonOptions(options =>
|
|
{
|
|
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
|
});
|
|
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
|
|
// 注册应用逻辑服务
|
|
builder.Services.AddApplicationServices(_appSettings.WebServer.ConnectionString);
|
|
|
|
// 配置跨域策略
|
|
builder.Services.AddCors(options =>
|
|
{
|
|
options.AddPolicy("AllowAll", policy =>
|
|
{
|
|
policy.AllowAnyOrigin()
|
|
.AllowAnyMethod()
|
|
.AllowAnyHeader();
|
|
});
|
|
});
|
|
|
|
var app = builder.Build();
|
|
|
|
// 如果配置为使用静态文件(前端托管),则配置静态文件服务
|
|
if (_appSettings.WebServer.IsUsingStatic)
|
|
{
|
|
ServeStaticFiles(app);
|
|
}
|
|
|
|
app.UseCors("AllowAll");
|
|
app.UseAuthorization();
|
|
app.UseDynamicApi();
|
|
app.MapControllers();
|
|
|
|
_webApp = app;
|
|
|
|
await _webApp.StartAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 配置静态文件服务(用于托管 Vue 前端)
|
|
/// </summary>
|
|
/// <param name="app">Web 应用程序实例</param>
|
|
private void ServeStaticFiles(WebApplication app)
|
|
{
|
|
try
|
|
{
|
|
var wwwrootPath = Path.Combine(AppContext.BaseDirectory, "wwwroot");
|
|
if (!Directory.Exists(wwwrootPath))
|
|
{
|
|
Console.WriteLine("[EmbeddedWebServer] wwwroot directory not found. Static file serving disabled.");
|
|
return;
|
|
}
|
|
var fileProvider = new PhysicalFileProvider(wwwrootPath);
|
|
var defaultFilesOptions = new DefaultFilesOptions { FileProvider = fileProvider, RequestPath = "" };
|
|
app.UseDefaultFiles(defaultFilesOptions);
|
|
|
|
var staticFileOptions = new StaticFileOptions
|
|
{
|
|
FileProvider = fileProvider,
|
|
RequestPath = "",
|
|
OnPrepareResponse = ctx =>
|
|
{
|
|
ctx.Context.Response.Headers["Cache-Control"] = "no-cache, no-store, must-revalidate";
|
|
ctx.Context.Response.Headers["Pragma"] = "no-cache";
|
|
ctx.Context.Response.Headers["Expires"] = "0";
|
|
}
|
|
};
|
|
app.UseStaticFiles(staticFileOptions);
|
|
|
|
// 处理 SPA 路由
|
|
app.Use(async (context, next) =>
|
|
{
|
|
if (context.Request.Path.HasValue)
|
|
{
|
|
var path = context.Request.Path.Value;
|
|
if (path != "/" && !path.StartsWith("/assets", StringComparison.OrdinalIgnoreCase) && !path.StartsWith("/api", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
var ext = Path.GetExtension(path);
|
|
if (string.IsNullOrEmpty(ext))
|
|
{
|
|
context.Request.Path = "/index.html";
|
|
}
|
|
}
|
|
}
|
|
await next();
|
|
});
|
|
|
|
Console.WriteLine($"[EmbeddedWebServer] Serving static files from: {wwwrootPath}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[EmbeddedWebServer] Failed to serve static files: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 异步停止服务器。
|
|
/// 释放服务器资源并停止监听。
|
|
/// </summary>
|
|
/// <returns>表示停止操作的任务</returns>
|
|
public async Task StopAsync()
|
|
{
|
|
if (_webApp == null) return;
|
|
|
|
await _webApp.StopAsync();
|
|
await _webApp.DisposeAsync();
|
|
_webApp = null;
|
|
}
|
|
}
|
|
#endif
|