chore: add documentation comments and stylecop rules

This commit is contained in:
2025-12-04 11:25:01 +08:00
parent 17d143a351
commit 8e4c2b0e45
142 changed files with 1309 additions and 439 deletions

View File

@@ -10,17 +10,13 @@ namespace TakeoutSaaS.MiniApi.Controllers;
/// <summary>
/// 小程序登录认证
/// </summary>
/// <remarks>
/// 小程序登录认证
/// </remarks>
/// <param name="authService"></param>
/// <remarks>提供小程序端的微信登录与 Token 刷新能力。</remarks>
/// <param name="authService">小程序认证服务</param>
[ApiVersion("1.0")]
[Authorize]
[Route("api/mini/v{version:apiVersion}/auth")]
public sealed class AuthController(IMiniAuthService authService) : BaseApiController
{
/// <summary>
/// 微信登录
/// </summary>
@@ -29,7 +25,10 @@ public sealed class AuthController(IMiniAuthService authService) : BaseApiContro
[ProducesResponseType(typeof(ApiResponse<TokenResponse>), StatusCodes.Status200OK)]
public async Task<ApiResponse<TokenResponse>> LoginWithWeChat([FromBody] WeChatLoginRequest request, CancellationToken cancellationToken)
{
// 1. 调用认证服务完成微信登录
var response = await authService.LoginWithWeChatAsync(request, cancellationToken);
// 2. 返回访问与刷新令牌
return ApiResponse<TokenResponse>.Ok(response);
}
@@ -41,7 +40,10 @@ public sealed class AuthController(IMiniAuthService authService) : BaseApiContro
[ProducesResponseType(typeof(ApiResponse<TokenResponse>), StatusCodes.Status200OK)]
public async Task<ApiResponse<TokenResponse>> RefreshToken([FromBody] RefreshTokenRequest request, CancellationToken cancellationToken)
{
// 1. 调用认证服务刷新 Token
var response = await authService.RefreshTokenAsync(request, cancellationToken);
// 2. 返回新的令牌
return ApiResponse<TokenResponse>.Ok(response);
}
}

View File

@@ -19,8 +19,6 @@ namespace TakeoutSaaS.MiniApi.Controllers;
[Route("api/mini/v{version:apiVersion}/files")]
public sealed class FilesController(IFileStorageService fileStorageService) : BaseApiController
{
private readonly IFileStorageService _fileStorageService = fileStorageService;
/// <summary>
/// 上传图片或文件。
/// </summary>
@@ -30,23 +28,28 @@ public sealed class FilesController(IFileStorageService fileStorageService) : Ba
[ProducesResponseType(typeof(ApiResponse<FileUploadResponse>), StatusCodes.Status400BadRequest)]
public async Task<ApiResponse<FileUploadResponse>> Upload([FromForm] IFormFile? file, [FromForm] string? type, CancellationToken cancellationToken)
{
// 1. 校验文件有效性
if (file == null || file.Length == 0)
{
return ApiResponse<FileUploadResponse>.Error(ErrorCodes.BadRequest, "文件不能为空");
}
// 2. 解析上传类型
if (!UploadFileTypeParser.TryParse(type, out var uploadType))
{
return ApiResponse<FileUploadResponse>.Error(ErrorCodes.BadRequest, "上传类型不合法");
}
// 3. 提取请求来源
var origin = Request.Headers["Origin"].FirstOrDefault() ?? Request.Headers["Referer"].FirstOrDefault();
await using var stream = file.OpenReadStream();
var result = await _fileStorageService.UploadAsync(
// 4. 调用存储服务执行上传
var result = await fileStorageService.UploadAsync(
new UploadFileRequest(uploadType, stream, file.FileName, file.ContentType ?? string.Empty, file.Length, origin),
cancellationToken);
// 5. 返回上传结果
return ApiResponse<FileUploadResponse>.Ok(result);
}
}

View File

@@ -23,7 +23,10 @@ public class HealthController : BaseApiController
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
public ApiResponse<object> Get()
{
// 1. 构造健康状态
var payload = new { status = "OK", service = "MiniApi", time = DateTime.UtcNow };
// 2. 返回健康响应
return ApiResponse<object>.Ok(payload);
}
}

View File

@@ -16,17 +16,13 @@ namespace TakeoutSaaS.MiniApi.Controllers;
/// <summary>
/// 当前用户信息
/// </summary>
/// <remarks>
///
/// </remarks>
/// <param name="authService"></param>
/// <remarks>提供小程序端当前用户档案查询。</remarks>
/// <param name="authService">小程序认证服务</param>
[ApiVersion("1.0")]
[Authorize]
[Route("api/mini/v{version:apiVersion}/me")]
public sealed class MeController(IMiniAuthService authService) : BaseApiController
{
/// <summary>
/// 获取用户档案
/// </summary>
@@ -35,12 +31,14 @@ public sealed class MeController(IMiniAuthService authService) : BaseApiControll
[ProducesResponseType(typeof(ApiResponse<CurrentUserProfile>), StatusCodes.Status401Unauthorized)]
public async Task<ApiResponse<CurrentUserProfile>> Get(CancellationToken cancellationToken)
{
// 1. 从 JWT 中解析用户标识
var userId = User.GetUserId();
if (userId == 0)
{
return ApiResponse<CurrentUserProfile>.Error(ErrorCodes.Unauthorized, "Token 缺少有效的用户标识");
}
// 2. 查询用户档案并返回
var profile = await authService.GetProfileAsync(userId, cancellationToken);
return ApiResponse<CurrentUserProfile>.Ok(profile);
}

View File

@@ -18,9 +18,11 @@ using TakeoutSaaS.Shared.Kernel.Ids;
using TakeoutSaaS.Shared.Web.Extensions;
using TakeoutSaaS.Shared.Web.Swagger;
// 1. 创建构建器与日志模板
var builder = WebApplication.CreateBuilder(args);
const string logTemplate = "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] [TraceId:{TraceId}] [SpanId:{SpanId}] [Service:{Service}] {SourceContext} {Message:lj}{NewLine}{Exception}";
// 2. 注册雪花 ID 生成器与 Serilog
builder.Services.AddSingleton<IIdGenerator>(_ => new SnowflakeIdGenerator());
builder.Host.UseSerilog((_, _, configuration) =>
{
@@ -36,6 +38,7 @@ builder.Host.UseSerilog((_, _, configuration) =>
outputTemplate: logTemplate);
});
// 3. 注册通用 Web 能力与 Swagger
builder.Services.AddSharedWebCore();
builder.Services.AddSharedSwagger(options =>
{
@@ -43,6 +46,8 @@ builder.Services.AddSharedSwagger(options =>
options.Description = "小程序 API 文档";
options.EnableAuthorization = true;
});
// 4. 注册多租户与业务模块
builder.Services.AddTenantResolution(builder.Configuration);
builder.Services.AddStorageModule(builder.Configuration);
builder.Services.AddStorageApplication();
@@ -51,6 +56,8 @@ builder.Services.AddSmsApplication(builder.Configuration);
builder.Services.AddMessagingModule(builder.Configuration);
builder.Services.AddMessagingApplication();
builder.Services.AddHealthChecks();
// 5. 配置 OpenTelemetry 采集
var otelSection = builder.Configuration.GetSection("Otel");
var otelEndpoint = otelSection.GetValue<string>("Endpoint");
var useConsoleExporter = otelSection.GetValue<bool?>("UseConsoleExporter") ?? builder.Environment.IsDevelopment();
@@ -102,6 +109,7 @@ builder.Services.AddOpenTelemetry()
}
});
// 6. 配置 CORS
var miniOrigins = ResolveCorsOrigins(builder.Configuration, "Cors:Mini");
builder.Services.AddCors(options =>
{
@@ -111,6 +119,7 @@ builder.Services.AddCors(options =>
});
});
// 7. 构建应用并配置中间件管道
var app = builder.Build();
app.UseCors("MiniApiCors");
@@ -123,6 +132,7 @@ app.MapPrometheusScrapingEndpoint();
app.MapControllers();
app.Run();
// 8. 解析配置中的 CORS 域名
static string[] ResolveCorsOrigins(IConfiguration configuration, string sectionKey)
{
var origins = configuration.GetSection(sectionKey).Get<string[]>();
@@ -132,6 +142,7 @@ static string[] ResolveCorsOrigins(IConfiguration configuration, string sectionK
.ToArray() ?? [];
}
// 9. 构建 CORS 策略
static void ConfigureCorsPolicy(CorsPolicyBuilder policy, string[] origins)
{
if (origins.Length == 0)