后端: - 新增 ManagedLibraryRoot / ManagedFileRecord 数据模型及 SQLite 迁移 - 新增文件库服务、端点服务及定时扫描后台任务 - 新增 REST API: drives、directories、roots CRUD、files 分页搜索、文本预览 - 新增文件流端点支持视频/音频流式传输 - 数据库切换为 SQLite,Kestrel 绑定 0.0.0.0 支持局域网访问 前端: - 管理端:磁盘浏览、目录选择、根目录添加/启用/删除/扫描 - 客户端:根目录选择、文件搜索/筛选/分页、音视频播放、文本预览 - 全新响应式 UI(桌面+移动端),CSS 变量设计系统 - HTTP 客户端支持 Vite 开发代理与生产同源自动切换 - 移除 HTTPS 强制重定向以提升移动端视频流兼容性
84 lines
3.7 KiB
C#
84 lines
3.7 KiB
C#
using Avalonia_API.Authentication;
|
||
using Avalonia_API.Services;
|
||
using Avalonia_EFCore.Database;
|
||
using Avalonia_Services.Core;
|
||
using Avalonia_Services.Endpoints;
|
||
using Avalonia_Services.Services;
|
||
using Avalonia_Services.Services.AuthService;
|
||
using Avalonia_Services.Services.FileLibrary;
|
||
using Microsoft.AspNetCore.DataProtection;
|
||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||
using Microsoft.IdentityModel.Tokens;
|
||
using System.Text;
|
||
|
||
namespace Avalonia_API.Configuration
|
||
{
|
||
/// <summary>
|
||
/// API 项目服务配置扩展类,负责注册数据库、鉴权、业务服务和统一端点。
|
||
/// </summary>
|
||
public static class ServicesConfiguration
|
||
{
|
||
/// <summary>
|
||
/// 注册统一端点及其依赖的服务(含数据库)。
|
||
/// 所有业务端点定义在 Avalonia-Services/Endpoints/AppEndpoints.cs。
|
||
/// </summary>
|
||
public static IServiceCollection AddUnifiedApiServices(this IServiceCollection services, IConfiguration configuration)
|
||
{
|
||
// ---- 数据库 ----
|
||
// 从 appsettings.json 读取 DatabaseConfiguration 节
|
||
// 注册默认数据库提供程序(SQLite / MySQL / PostgreSQL / SqlServer)
|
||
DatabaseProviderRegistry.RegisterDefaults();
|
||
|
||
var databaseConfig = configuration
|
||
.GetSection(nameof(DatabaseConfiguration))
|
||
.Get<DatabaseConfiguration>()
|
||
?? DatabaseConfiguration.ForSQLite("app.db");
|
||
|
||
// 注册 AppDataContext(共享数据上下文)
|
||
services.AddAppDatabase<AppDataContext>(databaseConfig);
|
||
|
||
// ---- 业务服务 ----
|
||
services.AddScoped<WeatherForecastService>();
|
||
services.AddScoped<IFileLibraryService, FileLibraryService>();
|
||
services.AddScoped<IFileLibraryEndpointService, FileLibraryEndpointService>();
|
||
services.AddHostedService<FileLibraryScanHostedService>();
|
||
services.AddDataProtection()
|
||
.PersistKeysToFileSystem(new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, "data-protection-keys")));
|
||
|
||
// ---- API 鉴权 ----
|
||
var jwtSection = configuration.GetSection("Jwt");
|
||
services.Configure<JwtOptions>(jwtSection);
|
||
var jwtOptions = jwtSection.Get<JwtOptions>() ?? new JwtOptions();
|
||
services
|
||
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||
.AddJwtBearer(options =>
|
||
{
|
||
options.TokenValidationParameters = new TokenValidationParameters
|
||
{
|
||
ValidateIssuer = true,
|
||
ValidateAudience = true,
|
||
ValidateLifetime = true,
|
||
ValidateIssuerSigningKey = true,
|
||
ValidIssuer = jwtOptions.Issuer,
|
||
ValidAudience = jwtOptions.Audience,
|
||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SigningKey)),
|
||
ClockSkew = TimeSpan.FromMinutes(1),
|
||
};
|
||
});
|
||
services.AddAuthorization();
|
||
services.AddScoped<JwtTokenService>();
|
||
services.AddScoped<RefreshTokenService>();
|
||
services.AddScoped<IApiAuthEndpointService, ApiAuthEndpointService>();
|
||
|
||
// ---- 统一端点 ----
|
||
var endpointBuilder = new ServiceEndpointBuilder();
|
||
AppEndpoints.Configure(endpointBuilder);
|
||
AuthEndpoints.ConfigureApi(endpointBuilder);
|
||
var endpoints = endpointBuilder.Build();
|
||
services.AddSingleton(endpoints);
|
||
|
||
return services;
|
||
}
|
||
}
|
||
}
|